aicodeswitch 1.6.1 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ClaudeToOpenAIResponsesEventTransform = exports.OpenAIResponsesToClaudeEventTransform = exports.OpenAIToClaudeEventTransform = exports.rewriteStream = exports.SSESerializerTransform = exports.SSEParserTransform = void 0;
6
+ exports.ClaudeToOpenAIChatEventTransform = exports.OpenAIToClaudeEventTransform = exports.rewriteStream = exports.SSESerializerTransform = exports.SSEParserTransform = void 0;
7
7
  const stream_1 = require("stream");
8
8
  const crypto_1 = __importDefault(require("crypto"));
9
9
  const claude_openai_1 = require("./claude-openai");
@@ -406,45 +406,33 @@ class OpenAIToClaudeEventTransform extends stream_1.Transform {
406
406
  }
407
407
  }
408
408
  exports.OpenAIToClaudeEventTransform = OpenAIToClaudeEventTransform;
409
- class OpenAIResponsesToClaudeEventTransform extends stream_1.Transform {
409
+ class ClaudeToOpenAIChatEventTransform extends stream_1.Transform {
410
410
  constructor(options) {
411
411
  var _a;
412
412
  super({ objectMode: true });
413
- Object.defineProperty(this, "contentIndex", {
414
- enumerable: true,
415
- configurable: true,
416
- writable: true,
417
- value: 0
418
- });
419
- Object.defineProperty(this, "textBlockIndex", {
413
+ Object.defineProperty(this, "pendingToolCallId", {
420
414
  enumerable: true,
421
415
  configurable: true,
422
416
  writable: true,
423
417
  value: null
424
418
  });
425
- Object.defineProperty(this, "toolCalls", {
419
+ Object.defineProperty(this, "pendingToolName", {
426
420
  enumerable: true,
427
421
  configurable: true,
428
422
  writable: true,
429
- value: new Map()
430
- });
431
- Object.defineProperty(this, "toolCallKeyToBlockIndex", {
432
- enumerable: true,
433
- configurable: true,
434
- writable: true,
435
- value: new Map()
423
+ value: null
436
424
  });
437
- Object.defineProperty(this, "hasMessageStart", {
425
+ Object.defineProperty(this, "pendingToolArgs", {
438
426
  enumerable: true,
439
427
  configurable: true,
440
428
  writable: true,
441
- value: false
429
+ value: ''
442
430
  });
443
- Object.defineProperty(this, "stopReason", {
431
+ Object.defineProperty(this, "toolCallIndex", {
444
432
  enumerable: true,
445
433
  configurable: true,
446
434
  writable: true,
447
- value: 'end_turn'
435
+ value: 0
448
436
  });
449
437
  Object.defineProperty(this, "usage", {
450
438
  enumerable: true,
@@ -452,437 +440,104 @@ class OpenAIResponsesToClaudeEventTransform extends stream_1.Transform {
452
440
  writable: true,
453
441
  value: null
454
442
  });
455
- Object.defineProperty(this, "messageId", {
456
- enumerable: true,
457
- configurable: true,
458
- writable: true,
459
- value: null
460
- });
461
- Object.defineProperty(this, "model", {
462
- enumerable: true,
463
- configurable: true,
464
- writable: true,
465
- value: null
466
- });
467
- Object.defineProperty(this, "finalized", {
443
+ Object.defineProperty(this, "finished", {
468
444
  enumerable: true,
469
445
  configurable: true,
470
446
  writable: true,
471
447
  value: false
472
448
  });
473
- this.model = (_a = options === null || options === void 0 ? void 0 : options.model) !== null && _a !== void 0 ? _a : null;
474
- }
475
- getUsage() {
476
- if (!this.usage)
477
- return undefined;
478
- return Object.assign({}, this.usage);
479
- }
480
- _transform(event, _encoding, callback) {
481
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4;
482
- if (this.finalized) {
483
- callback();
484
- return;
485
- }
486
- const eventType = event.event || ((_a = event.data) === null || _a === void 0 ? void 0 : _a.type) || '';
487
- if (eventType.includes('response.created')) {
488
- const response = ((_b = event.data) === null || _b === void 0 ? void 0 : _b.response) || event.data;
489
- if (response === null || response === void 0 ? void 0 : response.id)
490
- this.messageId = response.id;
491
- if (response === null || response === void 0 ? void 0 : response.model)
492
- this.model = response.model;
493
- this.ensureMessageStart();
494
- callback();
495
- return;
496
- }
497
- if (eventType.includes('output_text')) {
498
- const deltaText = (_d = (_c = event.data) === null || _c === void 0 ? void 0 : _c.delta) !== null && _d !== void 0 ? _d : (_e = event.data) === null || _e === void 0 ? void 0 : _e.text;
499
- if (typeof deltaText === 'string' && deltaText.length > 0) {
500
- this.handleTextDelta(deltaText);
501
- }
502
- if (eventType.includes('done')) {
503
- this.closeTextBlock();
504
- }
505
- callback();
506
- return;
507
- }
508
- if (eventType.includes('tool_call')) {
509
- const toolId = ((_f = event.data) === null || _f === void 0 ? void 0 : _f.tool_call_id) || ((_g = event.data) === null || _g === void 0 ? void 0 : _g.id) || ((_j = (_h = event.data) === null || _h === void 0 ? void 0 : _h.tool_call) === null || _j === void 0 ? void 0 : _j.id) || `tool_${this.toolCalls.size + 1}`;
510
- const toolName = ((_k = event.data) === null || _k === void 0 ? void 0 : _k.name) || ((_m = (_l = event.data) === null || _l === void 0 ? void 0 : _l.tool_call) === null || _m === void 0 ? void 0 : _m.name) || 'tool';
511
- const delta = (_p = (_o = event.data) === null || _o === void 0 ? void 0 : _o.delta) !== null && _p !== void 0 ? _p : (_q = event.data) === null || _q === void 0 ? void 0 : _q.arguments;
512
- if (typeof delta === 'string') {
513
- this.handleToolDelta(toolId, toolName, delta);
514
- }
515
- if (eventType.includes('done')) {
516
- const key = toolId || toolName;
517
- this.closeToolBlock(key);
518
- }
519
- callback();
520
- return;
521
- }
522
- if (eventType.includes('response.completed')) {
523
- const response = ((_r = event.data) === null || _r === void 0 ? void 0 : _r.response) || event.data;
524
- if (response === null || response === void 0 ? void 0 : response.usage) {
525
- const inputTokens = (_v = (_t = (_s = response.usage) === null || _s === void 0 ? void 0 : _s.input_tokens) !== null && _t !== void 0 ? _t : (_u = response.usage) === null || _u === void 0 ? void 0 : _u.prompt_tokens) !== null && _v !== void 0 ? _v : 0;
526
- const outputTokens = (_z = (_x = (_w = response.usage) === null || _w === void 0 ? void 0 : _w.output_tokens) !== null && _x !== void 0 ? _x : (_y = response.usage) === null || _y === void 0 ? void 0 : _y.completion_tokens) !== null && _z !== void 0 ? _z : 0;
527
- const cacheRead = (_4 = (_1 = (_0 = response.usage) === null || _0 === void 0 ? void 0 : _0.cache_read_input_tokens) !== null && _1 !== void 0 ? _1 : (_3 = (_2 = response.usage) === null || _2 === void 0 ? void 0 : _2.prompt_tokens_details) === null || _3 === void 0 ? void 0 : _3.cached_tokens) !== null && _4 !== void 0 ? _4 : 0;
528
- this.usage = {
529
- input_tokens: inputTokens,
530
- output_tokens: outputTokens,
531
- cache_read_input_tokens: cacheRead,
532
- };
533
- }
534
- this.finalize();
535
- callback();
536
- return;
537
- }
538
- callback();
539
- }
540
- _flush(callback) {
541
- this.finalize();
542
- callback();
543
- }
544
- assignContentBlockIndex() {
545
- const index = this.contentIndex;
546
- this.contentIndex += 1;
547
- return index;
548
- }
549
- pushEvent(type, data) {
550
- this.push({ event: type, data });
551
- }
552
- ensureMessageStart() {
553
- if (this.hasMessageStart)
554
- return;
555
- const message = {
556
- id: this.messageId || `msg_${crypto_1.default.randomUUID()}`,
557
- type: 'message',
558
- role: 'assistant',
559
- content: [],
560
- model: this.model || 'unknown',
561
- stop_reason: null,
562
- stop_sequence: null,
563
- usage: {
564
- input_tokens: 0,
565
- output_tokens: 0,
566
- },
567
- };
568
- this.pushEvent('message_start', { type: 'message_start', message });
569
- this.hasMessageStart = true;
570
- }
571
- handleTextDelta(text) {
572
- this.ensureMessageStart();
573
- if (this.textBlockIndex === null) {
574
- this.textBlockIndex = this.assignContentBlockIndex();
575
- this.pushEvent('content_block_start', {
576
- type: 'content_block_start',
577
- index: this.textBlockIndex,
578
- content_block: { type: 'text' },
579
- });
580
- }
581
- this.pushEvent('content_block_delta', {
582
- type: 'content_block_delta',
583
- index: this.textBlockIndex,
584
- delta: { type: 'text_delta', text },
585
- });
586
- }
587
- closeTextBlock() {
588
- if (this.textBlockIndex === null)
589
- return;
590
- this.pushEvent('content_block_stop', {
591
- type: 'content_block_stop',
592
- index: this.textBlockIndex,
593
- });
594
- this.textBlockIndex = null;
595
- }
596
- handleToolDelta(toolId, toolName, delta) {
597
- this.ensureMessageStart();
598
- const key = toolId || toolName;
599
- if (!this.toolCalls.has(key)) {
600
- const toolBlockIndex = this.assignContentBlockIndex();
601
- this.toolCalls.set(key, { id: toolId, name: toolName, arguments: '' });
602
- this.toolCallKeyToBlockIndex.set(key, toolBlockIndex);
603
- this.pushEvent('content_block_start', {
604
- type: 'content_block_start',
605
- index: toolBlockIndex,
606
- content_block: { type: 'tool_use', id: toolId, name: toolName },
607
- });
608
- }
609
- const toolEntry = this.toolCalls.get(key);
610
- if (toolEntry) {
611
- toolEntry.arguments += delta;
612
- }
613
- const blockIndex = this.toolCallKeyToBlockIndex.get(key);
614
- if (blockIndex !== undefined) {
615
- this.pushEvent('content_block_delta', {
616
- type: 'content_block_delta',
617
- index: blockIndex,
618
- delta: { type: 'input_json_delta', partial_json: delta },
619
- });
620
- }
621
- }
622
- closeToolBlock(key) {
623
- const blockIndex = this.toolCallKeyToBlockIndex.get(key);
624
- if (blockIndex === undefined)
625
- return;
626
- this.pushEvent('content_block_stop', {
627
- type: 'content_block_stop',
628
- index: blockIndex,
629
- });
630
- this.toolCallKeyToBlockIndex.delete(key);
631
- this.toolCalls.delete(key);
632
- }
633
- finalize() {
634
- if (this.finalized)
635
- return;
636
- this.ensureMessageStart();
637
- this.closeTextBlock();
638
- for (const blockIndex of this.toolCallKeyToBlockIndex.values()) {
639
- this.pushEvent('content_block_stop', {
640
- type: 'content_block_stop',
641
- index: blockIndex,
642
- });
643
- }
644
- this.toolCallKeyToBlockIndex.clear();
645
- this.toolCalls.clear();
646
- const usage = this.usage || {
647
- input_tokens: 0,
648
- output_tokens: 0,
649
- cache_read_input_tokens: 0,
650
- };
651
- this.pushEvent('message_delta', {
652
- type: 'message_delta',
653
- delta: { stop_reason: this.stopReason, stop_sequence: null },
654
- usage,
655
- });
656
- this.pushEvent('message_stop', { type: 'message_stop' });
657
- this.finalized = true;
658
- }
659
- }
660
- exports.OpenAIResponsesToClaudeEventTransform = OpenAIResponsesToClaudeEventTransform;
661
- class ClaudeToOpenAIResponsesEventTransform extends stream_1.Transform {
662
- constructor(options) {
663
- var _a;
664
- super({ objectMode: true });
665
- Object.defineProperty(this, "responseId", {
666
- enumerable: true,
667
- configurable: true,
668
- writable: true,
669
- value: null
670
- });
671
449
  Object.defineProperty(this, "model", {
672
450
  enumerable: true,
673
451
  configurable: true,
674
452
  writable: true,
675
453
  value: null
676
454
  });
677
- Object.defineProperty(this, "createdAt", {
678
- enumerable: true,
679
- configurable: true,
680
- writable: true,
681
- value: Date.now()
682
- });
683
- Object.defineProperty(this, "outputText", {
684
- enumerable: true,
685
- configurable: true,
686
- writable: true,
687
- value: ''
688
- });
689
- Object.defineProperty(this, "textBlockIndex", {
690
- enumerable: true,
691
- configurable: true,
692
- writable: true,
693
- value: null
694
- });
695
- Object.defineProperty(this, "toolCalls", {
696
- enumerable: true,
697
- configurable: true,
698
- writable: true,
699
- value: new Map()
700
- });
701
- Object.defineProperty(this, "completedToolCalls", {
702
- enumerable: true,
703
- configurable: true,
704
- writable: true,
705
- value: []
706
- });
707
- Object.defineProperty(this, "usage", {
708
- enumerable: true,
709
- configurable: true,
710
- writable: true,
711
- value: null
712
- });
713
- Object.defineProperty(this, "hasCreated", {
714
- enumerable: true,
715
- configurable: true,
716
- writable: true,
717
- value: false
718
- });
719
455
  this.model = (_a = options === null || options === void 0 ? void 0 : options.model) !== null && _a !== void 0 ? _a : null;
720
456
  }
721
457
  getUsage() {
722
- if (!this.usage)
723
- return undefined;
724
- return Object.assign({}, this.usage);
458
+ return this.usage;
725
459
  }
726
460
  _transform(event, _encoding, callback) {
727
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
728
- const eventType = event.event || '';
729
- if (eventType === 'message_start') {
730
- const message = (_a = event.data) === null || _a === void 0 ? void 0 : _a.message;
731
- if (message === null || message === void 0 ? void 0 : message.id)
732
- this.responseId = message.id;
733
- if (message === null || message === void 0 ? void 0 : message.model)
734
- this.model = message.model;
735
- this.ensureResponseCreated();
461
+ if (this.finished) {
736
462
  callback();
737
463
  return;
738
464
  }
739
- if (eventType === 'content_block_start') {
740
- const block = (_b = event.data) === null || _b === void 0 ? void 0 : _b.content_block;
741
- const index = (_c = event.data) === null || _c === void 0 ? void 0 : _c.index;
742
- if ((block === null || block === void 0 ? void 0 : block.type) === 'text') {
743
- this.textBlockIndex = index;
744
- }
745
- if ((block === null || block === void 0 ? void 0 : block.type) === 'tool_use' && typeof index === 'number') {
746
- this.toolCalls.set(index, {
747
- id: block.id || `tool_${index}`,
748
- name: block.name || 'tool',
749
- arguments: '',
750
- });
751
- }
465
+ const type = event.event;
466
+ const data = event.data;
467
+ if (type === 'message_start' && (data === null || data === void 0 ? void 0 : data.message)) {
468
+ this.model = data.message.model || this.model;
469
+ this.push({ event: null, data: { id: data.message.id, model: this.model, choices: [{ index: 0, delta: { role: 'assistant' }, finish_reason: null }] } });
752
470
  callback();
753
471
  return;
754
472
  }
755
- if (eventType === 'content_block_delta') {
756
- const delta = (_d = event.data) === null || _d === void 0 ? void 0 : _d.delta;
757
- const index = (_e = event.data) === null || _e === void 0 ? void 0 : _e.index;
758
- if ((delta === null || delta === void 0 ? void 0 : delta.type) === 'text_delta' && typeof delta.text === 'string') {
759
- this.ensureResponseCreated();
760
- this.outputText += delta.text;
761
- this.pushEvent('response.output_text.delta', {
762
- type: 'response.output_text.delta',
763
- delta: delta.text,
764
- output_index: 0,
765
- content_index: 0,
766
- });
473
+ if (type === 'content_block_start' && (data === null || data === void 0 ? void 0 : data.content_block)) {
474
+ if (data.content_block.type === 'text') {
475
+ // 文本块开始
767
476
  }
768
- if ((delta === null || delta === void 0 ? void 0 : delta.type) === 'input_json_delta' && typeof delta.partial_json === 'string' && typeof index === 'number') {
769
- const tool = this.toolCalls.get(index);
770
- if (tool) {
771
- tool.arguments += delta.partial_json;
772
- this.ensureResponseCreated();
773
- this.pushEvent('response.output_tool_call.delta', {
774
- type: 'response.output_tool_call.delta',
775
- delta: delta.partial_json,
776
- output_index: index,
777
- tool_call_id: tool.id,
778
- name: tool.name,
779
- });
780
- }
477
+ else if (data.content_block.type === 'tool_use') {
478
+ this.pendingToolCallId = data.content_block.id;
479
+ this.pendingToolName = data.content_block.name;
480
+ this.pendingToolArgs = '';
781
481
  }
782
482
  callback();
783
483
  return;
784
484
  }
785
- if (eventType === 'content_block_stop') {
786
- const index = (_f = event.data) === null || _f === void 0 ? void 0 : _f.index;
787
- if (typeof index === 'number') {
788
- if (this.textBlockIndex === index) {
789
- this.pushEvent('response.output_text.done', {
790
- type: 'response.output_text.done',
791
- text: this.outputText,
792
- output_index: 0,
793
- content_index: 0,
794
- });
795
- this.textBlockIndex = null;
796
- }
797
- const tool = this.toolCalls.get(index);
798
- if (tool) {
799
- this.completedToolCalls.push(tool);
800
- this.pushEvent('response.output_tool_call.done', {
801
- type: 'response.output_tool_call.done',
802
- output_index: index,
803
- tool_call: {
804
- id: tool.id,
805
- name: tool.name,
806
- arguments: tool.arguments,
807
- },
808
- });
809
- this.toolCalls.delete(index);
485
+ if (type === 'content_block_delta' && (data === null || data === void 0 ? void 0 : data.delta)) {
486
+ if (data.delta.type === 'text_delta') {
487
+ const text = data.delta.text || '';
488
+ if (text) {
489
+ this.push({ event: null, data: { id: '', model: this.model, choices: [{ index: 0, delta: { content: text } }] } });
810
490
  }
811
491
  }
492
+ else if (data.delta.type === 'input_json_delta') {
493
+ this.pendingToolArgs += data.delta.partial_json || '';
494
+ }
812
495
  callback();
813
496
  return;
814
497
  }
815
- if (eventType === 'message_delta') {
816
- if ((_g = event.data) === null || _g === void 0 ? void 0 : _g.usage) {
817
- this.usage = {
818
- input_tokens: (_h = event.data.usage.input_tokens) !== null && _h !== void 0 ? _h : 0,
819
- output_tokens: (_j = event.data.usage.output_tokens) !== null && _j !== void 0 ? _j : 0,
820
- cache_read_input_tokens: (_k = event.data.usage.cache_read_input_tokens) !== null && _k !== void 0 ? _k : 0,
498
+ if (type === 'content_block_stop') {
499
+ if (this.pendingToolCallId && this.pendingToolName !== null) {
500
+ const toolCall = {
501
+ index: this.toolCallIndex,
502
+ id: this.pendingToolCallId,
503
+ type: 'function',
504
+ function: {
505
+ name: this.pendingToolName,
506
+ arguments: this.pendingToolArgs,
507
+ },
821
508
  };
509
+ this.push({ event: null, data: { id: '', model: this.model, choices: [{ index: 0, delta: { tool_calls: [toolCall] } }] } });
510
+ this.toolCallIndex++;
511
+ this.pendingToolCallId = null;
512
+ this.pendingToolName = null;
513
+ this.pendingToolArgs = '';
822
514
  }
823
515
  callback();
824
516
  return;
825
517
  }
826
- if (eventType === 'message_stop') {
827
- this.pushCompletedResponse();
518
+ if (type === 'message_stop' || (data === null || data === void 0 ? void 0 : data.type) === 'message_stop') {
519
+ this.finished = true;
520
+ this.push({ event: null, data: { id: '', model: this.model, choices: [{ index: 0, delta: {}, finish_reason: 'stop' }] } });
521
+ this.push({ event: 'done', data: { type: 'done' } });
828
522
  callback();
829
523
  return;
830
524
  }
525
+ if (data === null || data === void 0 ? void 0 : data.usage) {
526
+ this.usage = {
527
+ prompt_tokens: data.usage.input_tokens || 0,
528
+ completion_tokens: data.usage.output_tokens || 0,
529
+ total_tokens: (data.usage.input_tokens || 0) + (data.usage.output_tokens || 0),
530
+ };
531
+ }
831
532
  callback();
832
533
  }
833
- ensureResponseCreated() {
834
- if (this.hasCreated)
835
- return;
836
- const response = {
837
- id: this.responseId || `resp_${crypto_1.default.randomUUID()}`,
838
- object: 'response',
839
- model: this.model || 'unknown',
840
- output: [],
841
- created_at: this.createdAt,
842
- };
843
- this.pushEvent('response.created', { type: 'response.created', response });
844
- this.hasCreated = true;
845
- }
846
- pushEvent(event, data) {
847
- this.push({ event, data });
848
- }
849
- pushCompletedResponse() {
850
- var _a, _b, _c, _d, _e, _f;
851
- this.ensureResponseCreated();
852
- const output = [];
853
- if (this.outputText) {
854
- output.push({
855
- type: 'message',
856
- role: 'assistant',
857
- content: [{ type: 'output_text', text: this.outputText }],
858
- });
859
- }
860
- for (const tool of this.completedToolCalls) {
861
- output.push({
862
- type: 'tool_call',
863
- id: tool.id,
864
- name: tool.name,
865
- arguments: tool.arguments,
866
- });
534
+ _flush(callback) {
535
+ if (!this.finished) {
536
+ this.finished = true;
537
+ this.push({ event: null, data: { id: '', model: this.model, choices: [{ index: 0, delta: {}, finish_reason: 'stop' }] } });
538
+ this.push({ event: 'done', data: { type: 'done' } });
867
539
  }
868
- const inputTokens = (_b = (_a = this.usage) === null || _a === void 0 ? void 0 : _a.input_tokens) !== null && _b !== void 0 ? _b : 0;
869
- const cacheRead = (_d = (_c = this.usage) === null || _c === void 0 ? void 0 : _c.cache_read_input_tokens) !== null && _d !== void 0 ? _d : 0;
870
- const outputTokens = (_f = (_e = this.usage) === null || _e === void 0 ? void 0 : _e.output_tokens) !== null && _f !== void 0 ? _f : 0;
871
- const response = {
872
- id: this.responseId || `resp_${crypto_1.default.randomUUID()}`,
873
- object: 'response',
874
- model: this.model || 'unknown',
875
- output,
876
- output_text: this.outputText,
877
- status: 'completed',
878
- created_at: this.createdAt,
879
- usage: {
880
- input_tokens: inputTokens + cacheRead,
881
- output_tokens: outputTokens,
882
- total_tokens: inputTokens + cacheRead + outputTokens,
883
- },
884
- };
885
- this.pushEvent('response.completed', { type: 'response.completed', response });
540
+ callback();
886
541
  }
887
542
  }
888
- exports.ClaudeToOpenAIResponsesEventTransform = ClaudeToOpenAIResponsesEventTransform;
543
+ exports.ClaudeToOpenAIChatEventTransform = ClaudeToOpenAIChatEventTransform;
@@ -1 +1 @@
1
- .app{display:flex;width:100%;height:100%}.sidebar{width:260px;background:var(--bg-sidebar);color:var(--text-primary);display:flex;flex-direction:column;padding:0 0 80px;border-radius:20px;box-shadow:0 8px 32px var(--shadow-primary),0 0 20px #0478574d;margin:16px;position:relative;z-index:1;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.1)}.logo{padding:28px 20px;border-bottom:2px solid rgba(255,255,255,.2);text-align:center;position:relative;overflow:hidden}.logo:before{content:"✨";position:absolute;top:12px;left:12px;font-size:16px;opacity:.7;transition:all .3s ease}.logo:after{content:"🌟";position:absolute;top:12px;right:12px;font-size:16px;opacity:.7;transition:all .3s ease}.logo:hover:before,.logo:focus:before{animation:sparkle 3s ease-in-out infinite}.logo:hover:after,.logo:focus:after{animation:sparkle 3s ease-in-out infinite 1.5s}@keyframes sparkle{0%,to{transform:scale(1) rotate(0);opacity:.7}50%{transform:scale(1.2) rotate(180deg);opacity:1}}.logo h2{font-size:22px;font-weight:800;background:linear-gradient(135deg,#fff,#f8f8ff,#e6e6fa);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;text-shadow:0 2px 4px rgba(0,0,0,.1),0 0 20px rgba(4,120,87,.3);position:relative;z-index:1;letter-spacing:1px;text-transform:uppercase;transition:all .3s ease}.logo:hover h2,.logo:focus h2{animation:logoGlow 4s ease-in-out infinite}@keyframes logoGlow{0%,to{text-shadow:0 2px 4px rgba(0,0,0,.1),0 0 20px rgba(4,120,87,.3)}50%{text-shadow:0 2px 4px rgba(0,0,0,.1),0 0 30px rgba(4,120,87,.5),0 0 40px rgba(4,120,87,.3)}}.nav-menu{list-style:none;padding:16px 0;margin:0}.nav-menu li{margin:8px 12px}.nav-menu a{display:block;padding:14px 20px;color:var(--text-sidebar);text-decoration:none;border-radius:12px;transition:all .3s ease-out;font-weight:500;position:relative;overflow:hidden}.nav-menu a:before{content:"";position:absolute;top:0;left:-100%;width:100%;height:100%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.15),transparent);transition:left .5s ease-out}.nav-menu a:hover:before{left:100%}.nav-menu a:hover{background-color:#ffffff1a;transform:translate(4px);box-shadow:0 4px 12px #0f172a33}.nav-menu a.active{background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary));box-shadow:0 4px 16px var(--shadow-primary)}.main-content{flex:1;padding:24px;overflow-y:auto;background:var(--bg-primary);position:relative;z-index:1;margin:16px 16px 16px 0;border-radius:20px}.main-content:before{content:"";position:absolute;top:0;left:0;right:0;bottom:0;background-image:radial-gradient(circle at 20% 80%,rgba(255,206,92,.1) 0%,transparent 50%),radial-gradient(circle at 80% 20%,rgba(134,204,202,.1) 0%,transparent 50%),radial-gradient(circle at 40% 40%,rgba(255,113,206,.05) 0%,transparent 50%);pointer-events:none}.page-header{margin-bottom:24px;position:relative;z-index:1}.page-header h1{font-family:Fredoka,sans-serif;font-size:28px;font-weight:700;color:var(--accent-primary);margin-bottom:8px;text-shadow:0 2px 4px var(--shadow-primary)}.page-header p{color:var(--text-muted);font-size:16px;font-weight:400}.card{background:var(--bg-card);border-radius:20px;padding:24px;box-shadow:0 8px 32px var(--shadow-secondary),0 0 16px #0478571a;margin-bottom:24px;border:1px solid var(--border-primary);position:relative;overflow:hidden;transition:all .3s ease-out;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.card:before{content:"";position:absolute;top:0;left:0;right:0;height:4px;background:linear-gradient(90deg,var(--accent-primary),var(--accent-secondary),var(--accent-primary));border-radius:20px 20px 0 0;background-size:200% 100%;transition:all .3s ease}.card:hover:before{animation:gradientShift 3s ease-in-out infinite}@keyframes gradientShift{0%,to{background-position:0% 50%}50%{background-position:100% 50%}}.card:hover{transform:translateY(-2px);box-shadow:0 12px 40px #6a7bb433,0 8px 24px #ff71ce26}.btn{padding:10px 20px;border:none;border-radius:12px;cursor:pointer;font-size:14px;font-weight:600;transition:all .3s ease-out;position:relative;overflow:hidden;box-shadow:0 2px 8px #0000001a;white-space:nowrap}.btn:before{content:"";position:absolute;top:50%;left:50%;width:0;height:0;background:#ffffff4d;border-radius:50%;transform:translate(-50%,-50%);transition:width .6s,height .6s}.btn:hover:before{width:300px;height:300px}.btn:hover{transform:translateY(-1px);box-shadow:0 4px 16px #00000026}.btn:active{transform:translateY(0)}.btn:disabled{opacity:.4;cursor:not-allowed}.btn-primary{background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary));color:#fff;position:relative;overflow:hidden}.btn-primary:before{content:"";position:absolute;top:0;left:-100%;width:100%;height:100%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.3),transparent);transition:left .5s ease}.btn-primary:hover:before{left:100%}.btn-primary:hover{transform:translateY(-2px);box-shadow:0 8px 25px #04785766}.btn-danger{background:var(--accent-danger);color:#fff}.btn-danger:hover{background:#ea580c}.btn-success{background:var(--accent-success);color:#fff}.btn-success:hover{background:#059669}.btn-secondary{background:var(--accent-secondary);color:#fff}.btn-secondary:hover{background:var(--accent-primary)}.btn-sm{padding:4px 8px}table{width:100%;border-collapse:collapse;margin-top:16px;border-radius:12px;overflow:hidden;box-shadow:0 4px 16px #6a7bb41a}table th,table td{padding:16px;text-align:left;border-bottom:1px solid var(--border-secondary);color:var(--text-primary)}table th{background:var(--bg-table-header);font-weight:700;color:var(--text-secondary);font-family:Fredoka,sans-serif;font-size:14px}.form-group{margin-bottom:20px}.form-group label{display:block;margin-bottom:8px;color:var(--text-primary);font-size:14px;font-weight:600;font-family:Nunito,sans-serif}.form-group input,.form-group select,.form-group textarea{width:100%;padding:12px 16px;border:2px solid var(--border-primary);border-radius:12px;font-size:14px;font-family:Nunito,sans-serif;background:var(--bg-secondary);color:var(--text-primary);transition:all .3s ease-out}.form-group input:focus,.form-group select:focus,.form-group textarea:focus{outline:none;border-color:var(--accent-primary);box-shadow:0 0 0 3px var(--shadow-secondary);background:var(--bg-secondary)}.modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:#000000b3;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);display:flex;justify-content:center;align-items:center;z-index:1000;animation:modalFadeIn .3s ease-out}@keyframes modalFadeIn{0%{opacity:0}to{opacity:1}}.modal{background:var(--bg-secondary);-webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px);border-radius:24px;padding:32px;min-width:500px;max-width:90%;max-height:90%;overflow-y:auto;box-shadow:0 20px 60px var(--shadow-primary),0 8px 32px var(--shadow-secondary);border:1px solid var(--border-secondary);animation:modalSlideIn .4s ease-out}@keyframes modalSlideIn{0%{opacity:0;transform:translateY(-20px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}.modal-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px}.modal-header h2{font-size:20px;color:var(--text-primary)}.modal-footer{display:flex;justify-content:flex-end;gap:10px;margin-top:20px}.action-buttons{display:flex;gap:8px}.badge{display:inline-block;padding:6px 12px;border-radius:20px;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;box-shadow:0 2px 8px #0000001a;margin-top:-40px;margin-right:-24px}.badge-success{background:var(--accent-success);color:#fff}.badge-warning{background:var(--accent-warning);color:#fff}.badge-danger{background:var(--accent-danger);color:#fff}.empty-state{text-align:center;padding:60px 20px;color:var(--text-muted);font-family:Nunito,sans-serif}.empty-state p{margin-bottom:20px;font-size:16px;font-weight:500}.toolbar{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px}.theme-toggle{position:absolute;bottom:20px;left:20px;right:20px;display:flex;align-items:center;justify-content:center;gap:12px;padding:12px;background:#ffffff14;border-radius:12px;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.1);transition:all .3s ease-out}.theme-toggle:hover{background:#ffffff1f}.theme-toggle button{background:none;border:none;color:var(--text-sidebar);cursor:pointer;padding:8px;border-radius:8px;transition:all .3s ease-out;display:flex;align-items:center;justify-content:center}.theme-toggle button:hover{background:#ffffff26}.theme-toggle button.active{background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary));color:#fff;box-shadow:0 2px 8px var(--shadow-primary),0 0 8px #04785780;animation:pulse 2s ease-in-out infinite}@keyframes pulse{0%,to{transform:scale(1)}50%{transform:scale(1.05)}}.update-notification{position:absolute;bottom:80px;left:20px;right:20px;background:linear-gradient(135deg,#10b98126,#05966926);border:1px solid rgba(16,185,129,.4);border-radius:12px;padding:12px;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);animation:slideUp .3s ease-out;box-shadow:0 4px 12px #10b98133;margin-bottom:12px}@keyframes slideUp{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.update-notification-content{display:flex;align-items:center;gap:10px;margin-bottom:8px}.update-icon{font-size:18px;animation:bounce 1s ease-in-out infinite}@keyframes bounce{0%,to{transform:translateY(0)}50%{transform:translateY(-3px)}}.update-text{flex:1}.update-title{font-size:13px;font-weight:600;color:var(--text-sidebar);margin-bottom:2px}.update-versions{font-size:11px;color:#ffffffb3;font-family:Monaco,Menlo,monospace}.update-message{font-size:10px;color:var(--text-sidebar);margin-bottom:2px}.update-message code{background:#ffffff1a;padding:2px 4px;border-radius:4px;font-family:Monaco,Menlo,monospace;margin-top:2px;display:inline-block}.update-link{display:block;text-align:center;padding:6px 12px;background:linear-gradient(135deg,var(--accent-success),#059669);color:#fff;text-decoration:none;border-radius:8px;font-size:12px;font-weight:600;transition:all .3s ease-out}.update-link:hover{transform:translateY(-1px);box-shadow:0 4px 12px #10b98166}@media (prefers-reduced-motion: reduce){.nav-menu a,.card,.btn,.form-group input,.form-group select,.form-group textarea,.modal-overlay,.modal,table tr{transition:none;animation:none}.nav-menu a:hover,.card:hover,.btn:hover,table tr:hover{transform:none}.btn:before{display:none}}.markdown-content{line-height:1.7;color:var(--text-primary);max-width:100%;overflow-x:auto}.markdown-content h1{font-size:2em;font-weight:700;margin-top:0;margin-bottom:.8em;color:var(--text-primary);border-bottom:2px solid var(--border-color);padding-bottom:.3em}.markdown-content h2{font-size:1.6em;font-weight:600;margin-top:1.5em;margin-bottom:.6em;color:var(--text-primary);border-bottom:1px solid var(--border-color);padding-bottom:.25em}.markdown-content h3{font-size:1.3em;font-weight:600;margin-top:1.2em;margin-bottom:.5em;color:var(--text-primary)}.markdown-content h4{font-size:1.1em;font-weight:600;margin-top:1em;margin-bottom:.4em;color:var(--text-primary)}.markdown-content p{margin-bottom:1em;line-height:1.8}.markdown-content ul,.markdown-content ol{margin-bottom:1em;padding-left:2em}.markdown-content li{margin-bottom:.5em;line-height:1.7}.markdown-content code{background:var(--bg-secondary);padding:.2em .4em;border-radius:4px;font-size:.9em;font-family:Monaco,Menlo,Ubuntu Mono,Consolas,monospace;color:var(--accent-secondary);border:1px solid var(--border-color)}.markdown-content pre{background:var(--bg-secondary);padding:1em;border-radius:8px;overflow-x:auto;margin-bottom:1em;border:1px solid var(--border-color)}.markdown-content pre code{background:none;padding:0;border:none;color:var(--text-primary);font-size:.95em}.markdown-content blockquote{border-left:4px solid var(--accent-primary);padding-left:1em;margin-left:0;margin-bottom:1em;color:var(--text-secondary);font-style:italic}.markdown-content a{color:var(--accent-primary);text-decoration:none;border-bottom:1px solid transparent;transition:all .2s ease}.markdown-content a:hover{color:var(--accent-secondary);border-bottom-color:var(--accent-secondary)}.markdown-content table{width:100%;border-collapse:collapse;margin-bottom:1em}.markdown-content table th,.markdown-content table td{padding:.75em;text-align:left;border:1px solid var(--border-color)}.markdown-content table th{background:var(--bg-secondary);font-weight:600}.markdown-content hr{border:none;border-top:2px solid var(--border-color);margin:2em 0}.markdown-content strong{font-weight:600;color:var(--text-primary)}.markdown-content em{font-style:italic}.markdown-content img{max-width:100%;height:auto;border-radius:8px;margin:1em 0}*{margin:0;padding:0;box-sizing:border-box}:root{--bg-primary: linear-gradient(135deg, #F7FEE7 0%, #F0FDF4 100%);--bg-secondary: rgba(255, 255, 255, .95);--bg-sidebar: linear-gradient(135deg, #0F5132 0%, #065F46 100%);--bg-card: rgba(255, 255, 255, .98);--bg-code: #f4fff7;--bg-table-header: linear-gradient(135deg, #A7F3D0 0%, #6EE7B7 100%);--text-primary: #14532D;--text-secondary: #064E3B;--text-muted: #065F46;--text-sidebar: #FFFFFF;--text-on-dark: #FFFFFF;--border-primary: rgba(15, 81, 50, .2);--border-secondary: rgba(6, 95, 70, .2);--accent-primary: #0F5132;--accent-secondary: #047857;--accent-light: #a1e9c7;--accent-success: #047857;--accent-warning: #D97706;--accent-danger: #DC2626;--shadow-primary: rgba(15, 81, 50, .3);--shadow-secondary: rgba(15, 81, 50, .15);--bg-route-item: rgba(248, 249, 250, .9);--bg-route-item-hover: rgba(230, 244, 234, .95);--bg-route-item-selected: rgba(161, 233, 199, .25);--text-route-muted: #6c757d;--text-info: #2faeee}[data-theme=dark]{--bg-primary: linear-gradient(135deg, #0A1A0F 0%, #0F2415 100%);--bg-secondary: rgba(15, 36, 21, .9);--bg-sidebar: linear-gradient(135deg, #0F5132 0%, #065F46 100%);--bg-card: rgba(25, 51, 31, .95);--bg-code: #0f172a;--bg-table-header: linear-gradient(135deg, #0F5132 0%, #047857 100%);--text-primary: #ECFEF5;--text-secondary: #A7F3D0;--text-muted: #6EE7B7;--text-sidebar: #FFFFFF;--text-on-dark: #ECFEF5;--border-primary: rgba(15, 81, 50, .5);--border-secondary: rgba(6, 95, 70, .5);--accent-primary: #0F5132;--accent-secondary: #047857;--accent-light: #002d18;--accent-success: #10B981;--accent-warning: #F59E0B;--accent-danger: #EF4444;--shadow-primary: rgba(15, 81, 50, .4);--shadow-secondary: rgba(6, 95, 70, .3);--bg-route-item: rgba(20, 46, 28, .7);--bg-route-item-hover: rgba(30, 60, 38, .85);--bg-route-item-selected: rgba(16, 185, 129, .15);--text-route-muted: #A7F3D0}body{font-family:Nunito,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background:var(--bg-primary);color:var(--text-primary);transition:all .3s ease;min-height:100vh}code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}#root{width:100vw;height:100vh;overflow:hidden}::-webkit-scrollbar{width:12px;height:12px}::-webkit-scrollbar-track{background:var(--bg-secondary);border-radius:8px}::-webkit-scrollbar-thumb{background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary));border-radius:8px;border:2px solid var(--bg-secondary);box-shadow:0 2px 4px #0000001a;transition:all .3s ease}::-webkit-scrollbar-thumb:hover{background:linear-gradient(135deg,var(--accent-secondary),var(--accent-primary));box-shadow:0 4px 8px #0003;transform:scale(1.1)}::-webkit-scrollbar-thumb:active{background:var(--accent-primary);box-shadow:0 6px 12px #0000004d}::-webkit-scrollbar-corner{background:var(--bg-secondary)}*{scrollbar-width:thin;scrollbar-color:var(--accent-primary) var(--bg-secondary)}::-webkit-scrollbar-button{display:none}html{scroll-behavior:smooth}
1
+ .app{display:flex;width:100%;height:100%}.sidebar{width:260px;background:var(--bg-sidebar);color:var(--text-primary);display:flex;flex-direction:column;padding:0 0 80px;border-radius:20px;box-shadow:0 8px 32px var(--shadow-primary),0 0 20px #0478574d;margin:16px;position:relative;z-index:1;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.1)}.logo{padding:28px 20px;border-bottom:2px solid rgba(255,255,255,.2);text-align:center;position:relative;overflow:hidden}.logo:before{content:"✨";position:absolute;top:12px;left:12px;font-size:16px;opacity:.7;transition:all .3s ease}.logo:after{content:"🌟";position:absolute;top:12px;right:12px;font-size:16px;opacity:.7;transition:all .3s ease}.logo:hover:before,.logo:focus:before{animation:sparkle 3s ease-in-out infinite}.logo:hover:after,.logo:focus:after{animation:sparkle 3s ease-in-out infinite 1.5s}@keyframes sparkle{0%,to{transform:scale(1) rotate(0);opacity:.7}50%{transform:scale(1.2) rotate(180deg);opacity:1}}.logo h2{font-size:22px;font-weight:800;background:linear-gradient(135deg,#fff,#f8f8ff,#e6e6fa);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;text-shadow:0 2px 4px rgba(0,0,0,.1),0 0 20px rgba(4,120,87,.3);position:relative;z-index:1;letter-spacing:1px;text-transform:uppercase;transition:all .3s ease}.logo:hover h2,.logo:focus h2{animation:logoGlow 4s ease-in-out infinite}@keyframes logoGlow{0%,to{text-shadow:0 2px 4px rgba(0,0,0,.1),0 0 20px rgba(4,120,87,.3)}50%{text-shadow:0 2px 4px rgba(0,0,0,.1),0 0 30px rgba(4,120,87,.5),0 0 40px rgba(4,120,87,.3)}}.nav-menu{list-style:none;padding:16px 0;margin:0}.nav-menu li{margin:8px 12px}.nav-menu a{display:block;padding:14px 20px;color:var(--text-sidebar);text-decoration:none;border-radius:12px;transition:all .3s ease-out;font-weight:500;position:relative;overflow:hidden}.nav-menu a:before{content:"";position:absolute;top:0;left:-100%;width:100%;height:100%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.15),transparent);transition:left .5s ease-out}.nav-menu a:hover:before{left:100%}.nav-menu a:hover{background-color:#ffffff1a;transform:translate(4px);box-shadow:0 4px 12px #0f172a33}.nav-menu a.active{background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary));box-shadow:0 4px 16px var(--shadow-primary)}.main-content{flex:1;padding:24px;overflow-y:auto;background:var(--bg-primary);position:relative;z-index:1;margin:16px 16px 16px 0;border-radius:20px}.main-content:before{content:"";position:absolute;top:0;left:0;right:0;bottom:0;background-image:radial-gradient(circle at 20% 80%,rgba(255,206,92,.1) 0%,transparent 50%),radial-gradient(circle at 80% 20%,rgba(134,204,202,.1) 0%,transparent 50%),radial-gradient(circle at 40% 40%,rgba(255,113,206,.05) 0%,transparent 50%);pointer-events:none}.page-header{margin-bottom:24px;position:relative;z-index:1}.page-header h1{font-family:Fredoka,sans-serif;font-size:28px;font-weight:700;color:var(--accent-primary);margin-bottom:8px;text-shadow:0 2px 4px var(--shadow-primary)}.page-header p{color:var(--text-muted);font-size:16px;font-weight:400}.card{background:var(--bg-card);border-radius:20px;padding:24px;box-shadow:0 8px 32px var(--shadow-secondary),0 0 16px #0478571a;margin-bottom:24px;border:1px solid var(--border-primary);position:relative;overflow:hidden;transition:all .3s ease-out;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.card:before{content:"";position:absolute;top:0;left:0;right:0;height:4px;background:linear-gradient(90deg,var(--accent-primary),var(--accent-secondary),var(--accent-primary));border-radius:20px 20px 0 0;background-size:200% 100%;transition:all .3s ease}.card:hover:before{animation:gradientShift 3s ease-in-out infinite}@keyframes gradientShift{0%,to{background-position:0% 50%}50%{background-position:100% 50%}}.card:hover{transform:translateY(-2px);box-shadow:0 12px 40px #6a7bb433,0 8px 24px #ff71ce26}.btn{padding:10px 20px;border:none;border-radius:12px;cursor:pointer;font-size:14px;font-weight:600;transition:all .3s ease-out;position:relative;overflow:hidden;box-shadow:0 2px 8px #0000001a;white-space:nowrap}.btn:before{content:"";position:absolute;top:50%;left:50%;width:0;height:0;background:#ffffff4d;border-radius:50%;transform:translate(-50%,-50%);transition:width .6s,height .6s}.btn:hover:before{width:300px;height:300px}.btn:hover{transform:translateY(-1px);box-shadow:0 4px 16px #00000026}.btn:active{transform:translateY(0)}.btn:disabled{opacity:.4;cursor:not-allowed}.btn-primary{background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary));color:#fff;position:relative;overflow:hidden}.btn-primary:before{content:"";position:absolute;top:0;left:-100%;width:100%;height:100%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.3),transparent);transition:left .5s ease}.btn-primary:hover:before{left:100%}.btn-primary:hover{transform:translateY(-2px);box-shadow:0 8px 25px #04785766}.btn-danger{background:var(--accent-danger);color:#fff}.btn-danger:hover{background:#ea580c}.btn-success{background:var(--accent-success);color:#fff}.btn-success:hover{background:#059669}.btn-secondary{background:var(--accent-secondary);color:#fff}.btn-secondary:hover{background:var(--accent-primary)}.btn-sm{padding:4px 8px}table{width:100%;border-collapse:collapse;margin-top:16px;border-radius:12px;overflow:hidden;box-shadow:0 4px 16px #6a7bb41a}table th,table td{padding:16px;text-align:left;border-bottom:1px solid var(--border-secondary);color:var(--text-primary)}table th{background:var(--bg-table-header);font-weight:700;color:var(--text-secondary);font-family:Fredoka,sans-serif;font-size:14px}.form-group{margin-bottom:20px}.form-group label{display:block;margin-bottom:8px;color:var(--text-primary);font-size:14px;font-weight:600;font-family:Nunito,sans-serif}.form-group input,.form-group select,.form-group textarea{width:100%;padding:12px 16px;border:2px solid var(--border-primary);border-radius:12px;font-size:14px;font-family:Nunito,sans-serif;background:var(--bg-secondary);color:var(--text-primary);transition:all .3s ease-out}.form-group input:focus,.form-group select:focus,.form-group textarea:focus{outline:none;border-color:var(--accent-primary);box-shadow:0 0 0 3px var(--shadow-secondary);background:var(--bg-secondary)}.modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:#000000b3;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);display:flex;justify-content:center;align-items:center;z-index:1000;animation:modalFadeIn .3s ease-out}@keyframes modalFadeIn{0%{opacity:0}to{opacity:1}}.modal{background:var(--bg-secondary);-webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px);border-radius:24px;padding:32px;min-width:500px;max-width:90%;max-height:90%;overflow-y:auto;box-shadow:0 20px 60px var(--shadow-primary),0 8px 32px var(--shadow-secondary);border:1px solid var(--border-secondary);animation:modalSlideIn .4s ease-out}@keyframes modalSlideIn{0%{opacity:0;transform:translateY(-20px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}.modal-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px}.modal-header h2{font-size:20px;color:var(--text-primary)}.modal-footer{display:flex;justify-content:flex-end;gap:10px;margin-top:20px}.action-buttons{display:flex;gap:8px}.badge{display:inline-block;padding:6px 12px;border-radius:20px;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;box-shadow:0 2px 8px #0000001a;margin-top:-40px;margin-right:-24px}.badge-success{background:var(--accent-success);color:#fff}.badge-warning{background:var(--accent-warning);color:#fff}.badge-danger{background:var(--accent-danger);color:#fff}.empty-state{text-align:center;padding:60px 20px;color:var(--text-muted);font-family:Nunito,sans-serif}.empty-state p{margin-bottom:20px;font-size:16px;font-weight:500}.toolbar{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px}.theme-toggle{position:absolute;bottom:20px;left:20px;right:20px;display:flex;align-items:center;justify-content:center;gap:12px;padding:12px;background:#ffffff14;border-radius:12px;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.1);transition:all .3s ease-out}.theme-toggle:hover{background:#ffffff1f}.theme-toggle button{background:none;border:none;color:var(--text-sidebar);cursor:pointer;padding:8px;border-radius:8px;transition:all .3s ease-out;display:flex;align-items:center;justify-content:center}.theme-toggle button:hover{background:#ffffff26}.theme-toggle button.active{background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary));color:#fff;box-shadow:0 2px 8px var(--shadow-primary),0 0 8px #04785780;animation:pulse 2s ease-in-out infinite}@keyframes pulse{0%,to{transform:scale(1)}50%{transform:scale(1.05)}}.update-notification{position:absolute;bottom:80px;left:20px;right:20px;background:linear-gradient(135deg,#10b98126,#05966926);border:1px solid rgba(16,185,129,.4);border-radius:12px;padding:12px;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);animation:slideUp .3s ease-out;box-shadow:0 4px 12px #10b98133;margin-bottom:12px}@keyframes slideUp{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.update-notification-content{display:flex;align-items:center;gap:10px;margin-bottom:8px}.update-icon{font-size:18px;animation:bounce 1s ease-in-out infinite}@keyframes bounce{0%,to{transform:translateY(0)}50%{transform:translateY(-3px)}}.update-text{flex:1}.update-title{font-size:13px;font-weight:600;color:var(--text-sidebar);margin-bottom:2px}.update-versions{font-size:11px;color:#ffffffb3;font-family:Monaco,Menlo,monospace}.update-message{font-size:10px;color:var(--text-sidebar);margin-bottom:2px}.update-message code{background:#ffffff1a;padding:2px 4px;border-radius:4px;font-family:Monaco,Menlo,monospace;margin-top:2px;display:inline-block}.update-link{display:block;text-align:center;padding:6px 12px;background:linear-gradient(135deg,var(--accent-success),#059669);color:#fff;text-decoration:none;border-radius:8px;font-size:12px;font-weight:600;transition:all .3s ease-out}.update-link:hover{transform:translateY(-1px);box-shadow:0 4px 12px #10b98166}@media (prefers-reduced-motion: reduce){.nav-menu a,.card,.btn,.form-group input,.form-group select,.form-group textarea,.modal-overlay,.modal,table tr{transition:none;animation:none}.nav-menu a:hover,.card:hover,.btn:hover,table tr:hover{transform:none}.btn:before{display:none}}.markdown-content{line-height:1.7;color:var(--text-primary);max-width:100%;overflow-x:auto}.markdown-content h1{font-size:2em;font-weight:700;margin-top:0;margin-bottom:.8em;color:var(--text-primary);border-bottom:2px solid var(--border-color);padding-bottom:.3em}.markdown-content h2{font-size:1.6em;font-weight:600;margin-top:1.5em;margin-bottom:.6em;color:var(--text-primary);border-bottom:1px solid var(--border-color);padding-bottom:.25em}.markdown-content h3{font-size:1.3em;font-weight:600;margin-top:1.2em;margin-bottom:.5em;color:var(--text-primary)}.markdown-content h4{font-size:1.1em;font-weight:600;margin-top:1em;margin-bottom:.4em;color:var(--text-primary)}.markdown-content p{margin-bottom:1em;line-height:1.8}.markdown-content ul,.markdown-content ol{margin-bottom:1em;padding-left:2em}.markdown-content li{margin-bottom:.5em;line-height:1.7}.markdown-content code{background:var(--bg-secondary);padding:.2em .4em;border-radius:4px;font-size:.9em;font-family:Monaco,Menlo,Ubuntu Mono,Consolas,monospace;color:var(--accent-secondary);border:1px solid var(--border-color)}.markdown-content pre{background:var(--bg-secondary);padding:1em;border-radius:8px;overflow-x:auto;margin-bottom:1em;border:1px solid var(--border-color)}.markdown-content pre code{background:none;padding:0;border:none;color:var(--text-primary);font-size:.95em}.markdown-content blockquote{border-left:4px solid var(--accent-primary);padding-left:1em;margin-left:0;margin-bottom:1em;color:var(--text-secondary);font-style:italic}.markdown-content a{color:var(--accent-primary);text-decoration:none;border-bottom:1px solid var(--accent-secondary);transition:all .2s ease}.markdown-content a:hover{color:var(--accent-secondary)}.markdown-content table{width:100%;border-collapse:collapse;margin-bottom:1em}.markdown-content table th,.markdown-content table td{padding:.75em;text-align:left;border:1px solid var(--border-color)}.markdown-content table th{background:var(--bg-secondary);font-weight:600}.markdown-content hr{border:none;border-top:2px solid var(--border-color);margin:2em 0}.markdown-content strong{font-weight:600;color:var(--text-primary)}.markdown-content em{font-style:italic}.markdown-content img{max-width:100%;height:auto;border-radius:8px;margin:1em 0}*{margin:0;padding:0;box-sizing:border-box}:root{--bg-primary: linear-gradient(135deg, #F7FEE7 0%, #F0FDF4 100%);--bg-secondary: rgba(255, 255, 255, .95);--bg-sidebar: linear-gradient(135deg, #0F5132 0%, #065F46 100%);--bg-card: rgba(255, 255, 255, .98);--bg-code: #f4fff7;--bg-table-header: linear-gradient(135deg, #A7F3D0 0%, #6EE7B7 100%);--text-primary: #14532D;--text-secondary: #064E3B;--text-muted: #065F46;--text-sidebar: #FFFFFF;--text-on-dark: #FFFFFF;--border-primary: rgba(15, 81, 50, .2);--border-secondary: rgba(6, 95, 70, .2);--accent-primary: #0F5132;--accent-secondary: #047857;--accent-light: #a1e9c7;--accent-success: #047857;--accent-warning: #D97706;--accent-danger: #DC2626;--shadow-primary: rgba(15, 81, 50, .3);--shadow-secondary: rgba(15, 81, 50, .15);--bg-route-item: rgba(248, 249, 250, .9);--bg-route-item-hover: rgba(230, 244, 234, .95);--bg-route-item-selected: rgba(161, 233, 199, .25);--text-route-muted: #6c757d;--text-info: #2faeee}[data-theme=dark]{--bg-primary: linear-gradient(135deg, #0A1A0F 0%, #0F2415 100%);--bg-secondary: rgba(15, 36, 21, .9);--bg-sidebar: linear-gradient(135deg, #0F5132 0%, #065F46 100%);--bg-card: rgba(25, 51, 31, .95);--bg-code: #0f172a;--bg-table-header: linear-gradient(135deg, #0F5132 0%, #047857 100%);--text-primary: #ECFEF5;--text-secondary: #A7F3D0;--text-muted: #6EE7B7;--text-sidebar: #FFFFFF;--text-on-dark: #ECFEF5;--border-primary: rgba(15, 81, 50, .5);--border-secondary: rgba(6, 95, 70, .5);--accent-primary: #0F5132;--accent-secondary: #047857;--accent-light: #002d18;--accent-success: #10B981;--accent-warning: #F59E0B;--accent-danger: #EF4444;--shadow-primary: rgba(15, 81, 50, .4);--shadow-secondary: rgba(6, 95, 70, .3);--bg-route-item: rgba(20, 46, 28, .7);--bg-route-item-hover: rgba(30, 60, 38, .85);--bg-route-item-selected: rgba(16, 185, 129, .15);--text-route-muted: #A7F3D0}body{font-family:Nunito,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background:var(--bg-primary);color:var(--text-primary);transition:all .3s ease;min-height:100vh}code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}#root{width:100vw;height:100vh;overflow:hidden}::-webkit-scrollbar{width:12px;height:12px}::-webkit-scrollbar-track{background:var(--bg-secondary);border-radius:8px}::-webkit-scrollbar-thumb{background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary));border-radius:8px;border:2px solid var(--bg-secondary);box-shadow:0 2px 4px #0000001a;transition:all .3s ease}::-webkit-scrollbar-thumb:hover{background:linear-gradient(135deg,var(--accent-secondary),var(--accent-primary));box-shadow:0 4px 8px #0003;transform:scale(1.1)}::-webkit-scrollbar-thumb:active{background:var(--accent-primary);box-shadow:0 6px 12px #0000004d}::-webkit-scrollbar-corner{background:var(--bg-secondary)}*{scrollbar-width:thin;scrollbar-color:var(--accent-primary) var(--bg-secondary)}::-webkit-scrollbar-button{display:none}html{scroll-behavior:smooth}