@jhizzard/termdeck 0.8.0 → 0.10.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.
Files changed (28) hide show
  1. package/docs/orchestrator-guide.md +335 -0
  2. package/package.json +3 -1
  3. package/packages/cli/src/index.js +26 -3
  4. package/packages/cli/src/init-project.js +213 -0
  5. package/packages/cli/src/templates.js +84 -0
  6. package/packages/cli/templates/.claude-settings.json.tmpl +32 -0
  7. package/packages/cli/templates/.gitignore.tmpl +28 -0
  8. package/packages/cli/templates/CLAUDE.md.tmpl +35 -0
  9. package/packages/cli/templates/CONTRADICTIONS.md.tmpl +30 -0
  10. package/packages/cli/templates/README.md.tmpl +15 -0
  11. package/packages/cli/templates/RESTART-PROMPT.md.tmpl +38 -0
  12. package/packages/cli/templates/docs-orchestration-README.md.tmpl +29 -0
  13. package/packages/cli/templates/project_facts.md.tmpl +39 -0
  14. package/packages/client/public/app.js +781 -0
  15. package/packages/client/public/graph.html +104 -0
  16. package/packages/client/public/graph.js +683 -0
  17. package/packages/client/public/index.html +145 -0
  18. package/packages/client/public/style.css +1185 -0
  19. package/packages/server/src/graph-routes.js +555 -0
  20. package/packages/server/src/index.js +158 -5
  21. package/packages/server/src/orchestration-preview.js +256 -0
  22. package/packages/server/src/preflight.js +82 -0
  23. package/packages/server/src/rag.js +138 -0
  24. package/packages/server/src/setup/mnestra-migrations/009_memory_relationship_metadata.sql +126 -0
  25. package/packages/server/src/setup/mnestra-migrations/010_memory_recall_graph.sql +147 -0
  26. package/packages/server/src/setup/rumen/migrations/003_graph_inference_schedule.sql +49 -0
  27. package/packages/server/src/sprint-inject.js +156 -0
  28. package/packages/server/src/sprint-routes.js +503 -0
@@ -762,6 +762,275 @@
762
762
  filter: none;
763
763
  }
764
764
 
765
+ /* ===== Orchestration preview button + modal (Sprint 37 T3) ===== */
766
+ .prompt-preview-project {
767
+ background: transparent;
768
+ border: 1px solid var(--tg-border);
769
+ color: var(--tg-text-dim);
770
+ font-size: 11px;
771
+ font-weight: 600;
772
+ padding: 6px 10px;
773
+ border-radius: 4px;
774
+ cursor: pointer;
775
+ font-family: var(--tg-sans);
776
+ letter-spacing: 0.4px;
777
+ text-transform: lowercase;
778
+ }
779
+ .prompt-preview-project:hover:not(:disabled) {
780
+ color: var(--tg-text);
781
+ border-color: var(--tg-accent-dim);
782
+ }
783
+ .prompt-preview-project:disabled {
784
+ opacity: 0.4;
785
+ cursor: not-allowed;
786
+ }
787
+
788
+ .preview-project-modal {
789
+ display: none;
790
+ position: fixed;
791
+ inset: 0;
792
+ z-index: 3000;
793
+ align-items: center;
794
+ justify-content: center;
795
+ }
796
+ .preview-project-modal.open { display: flex; }
797
+ .preview-project-backdrop {
798
+ position: absolute;
799
+ inset: 0;
800
+ background: rgba(0, 0, 0, 0.72);
801
+ }
802
+ .preview-project-card {
803
+ position: relative;
804
+ background: var(--tg-surface);
805
+ border: 1px solid var(--tg-accent-dim);
806
+ border-radius: 10px;
807
+ padding: 18px 22px 16px;
808
+ width: 760px;
809
+ max-width: calc(100vw - 40px);
810
+ max-height: calc(100vh - 60px);
811
+ display: flex;
812
+ flex-direction: column;
813
+ box-shadow: 0 16px 48px rgba(0, 0, 0, 0.55);
814
+ font-family: var(--tg-sans);
815
+ color: var(--tg-text);
816
+ }
817
+ .ppm-header {
818
+ display: flex;
819
+ justify-content: space-between;
820
+ align-items: flex-start;
821
+ gap: 16px;
822
+ margin-bottom: 6px;
823
+ }
824
+ .ppm-header h3 {
825
+ margin: 0 0 2px;
826
+ font-size: 16px;
827
+ color: var(--tg-accent);
828
+ }
829
+ .ppm-help {
830
+ margin: 0;
831
+ font-size: 12px;
832
+ color: var(--tg-text-dim);
833
+ }
834
+ .ppm-help code {
835
+ background: var(--tg-bg);
836
+ padding: 1px 5px;
837
+ border-radius: 3px;
838
+ font-family: var(--tg-mono);
839
+ font-size: 11px;
840
+ }
841
+ .ppm-close {
842
+ background: transparent;
843
+ border: none;
844
+ color: var(--tg-text-dim);
845
+ font-size: 22px;
846
+ line-height: 1;
847
+ cursor: pointer;
848
+ padding: 0 6px;
849
+ }
850
+ .ppm-close:hover { color: var(--tg-text); }
851
+ .ppm-meta {
852
+ font-family: var(--tg-mono);
853
+ font-size: 11px;
854
+ color: var(--tg-text-dim);
855
+ padding: 6px 8px;
856
+ background: var(--tg-bg);
857
+ border-radius: 4px;
858
+ margin: 8px 0 6px;
859
+ word-break: break-all;
860
+ }
861
+ .ppm-meta b { color: var(--tg-text); font-weight: 600; }
862
+ .ppm-meta .ppm-meta-tag {
863
+ display: inline-block;
864
+ font-size: 10px;
865
+ text-transform: uppercase;
866
+ letter-spacing: 0.6px;
867
+ padding: 1px 6px;
868
+ border-radius: 3px;
869
+ margin-left: 6px;
870
+ }
871
+ .ppm-meta .ppm-meta-tag.exists { background: rgba(255, 191, 105, 0.18); color: var(--tg-amber); }
872
+ .ppm-meta .ppm-meta-tag.fresh { background: rgba(158, 206, 106, 0.18); color: var(--tg-green); }
873
+ .ppm-status {
874
+ font-size: 12px;
875
+ min-height: 16px;
876
+ margin: 2px 0 6px;
877
+ color: var(--tg-text-dim);
878
+ }
879
+ .ppm-status.error { color: var(--tg-red); }
880
+ .ppm-status.ok { color: var(--tg-green); }
881
+ .ppm-tree {
882
+ flex: 1 1 auto;
883
+ overflow-y: auto;
884
+ border: 1px solid var(--tg-border);
885
+ border-radius: 6px;
886
+ background: var(--tg-bg);
887
+ padding: 4px;
888
+ margin-bottom: 12px;
889
+ min-height: 200px;
890
+ }
891
+ .ppm-empty {
892
+ padding: 18px;
893
+ font-size: 12px;
894
+ color: var(--tg-text-dim);
895
+ text-align: center;
896
+ }
897
+ .ppm-section {
898
+ margin: 4px 0;
899
+ }
900
+ .ppm-section-label {
901
+ font-size: 10px;
902
+ text-transform: uppercase;
903
+ letter-spacing: 0.6px;
904
+ color: var(--tg-text-dim);
905
+ padding: 4px 8px;
906
+ }
907
+ .ppm-row {
908
+ display: block;
909
+ padding: 0;
910
+ margin: 2px 0;
911
+ border-radius: 4px;
912
+ border: 1px solid transparent;
913
+ }
914
+ .ppm-row.create { border-color: rgba(158, 206, 106, 0.18); }
915
+ .ppm-row.skip { border-color: rgba(255, 191, 105, 0.18); opacity: 0.85; }
916
+ .ppm-row-header {
917
+ display: flex;
918
+ align-items: center;
919
+ gap: 8px;
920
+ padding: 6px 10px;
921
+ cursor: pointer;
922
+ user-select: none;
923
+ background: transparent;
924
+ border: none;
925
+ width: 100%;
926
+ text-align: left;
927
+ color: var(--tg-text);
928
+ font-family: var(--tg-mono);
929
+ font-size: 12px;
930
+ }
931
+ .ppm-row-header:hover { background: var(--tg-surface); }
932
+ .ppm-row-icon {
933
+ flex: 0 0 auto;
934
+ width: 12px;
935
+ text-align: center;
936
+ color: var(--tg-text-dim);
937
+ font-size: 10px;
938
+ }
939
+ .ppm-row-path {
940
+ flex: 1 1 auto;
941
+ overflow: hidden;
942
+ text-overflow: ellipsis;
943
+ white-space: nowrap;
944
+ }
945
+ .ppm-row-meta {
946
+ flex: 0 0 auto;
947
+ font-size: 10px;
948
+ color: var(--tg-text-dim);
949
+ }
950
+ .ppm-row-tag {
951
+ flex: 0 0 auto;
952
+ font-size: 9px;
953
+ text-transform: uppercase;
954
+ letter-spacing: 0.6px;
955
+ padding: 1px 5px;
956
+ border-radius: 3px;
957
+ }
958
+ .ppm-row-tag.create { background: rgba(158, 206, 106, 0.18); color: var(--tg-green); }
959
+ .ppm-row-tag.skip { background: rgba(255, 191, 105, 0.18); color: var(--tg-amber); }
960
+ .ppm-row-body {
961
+ display: none;
962
+ max-height: 240px;
963
+ overflow: auto;
964
+ padding: 6px 10px 10px;
965
+ background: rgba(0, 0, 0, 0.2);
966
+ border-top: 1px solid var(--tg-border);
967
+ }
968
+ .ppm-row.expanded .ppm-row-body { display: block; }
969
+ .ppm-row-body pre {
970
+ margin: 0;
971
+ font-family: var(--tg-mono);
972
+ font-size: 11px;
973
+ color: var(--tg-text);
974
+ white-space: pre-wrap;
975
+ word-break: break-word;
976
+ }
977
+ .ppm-row-body .ppm-row-truncated {
978
+ margin-top: 6px;
979
+ font-size: 10px;
980
+ color: var(--tg-text-dim);
981
+ font-style: italic;
982
+ }
983
+ .ppm-row-body .ppm-row-skip-reason {
984
+ margin-bottom: 6px;
985
+ font-size: 11px;
986
+ color: var(--tg-amber);
987
+ }
988
+ .ppm-actions {
989
+ display: flex;
990
+ justify-content: space-between;
991
+ align-items: center;
992
+ gap: 12px;
993
+ }
994
+ .ppm-force {
995
+ font-size: 11px;
996
+ color: var(--tg-text-dim);
997
+ display: flex;
998
+ align-items: center;
999
+ gap: 6px;
1000
+ cursor: pointer;
1001
+ }
1002
+ .ppm-force input { cursor: pointer; }
1003
+ .ppm-action-buttons { display: flex; gap: 8px; }
1004
+ .ppm-cancel,
1005
+ .ppm-generate {
1006
+ font-size: 12px;
1007
+ font-weight: 600;
1008
+ padding: 6px 16px;
1009
+ border-radius: 4px;
1010
+ cursor: pointer;
1011
+ font-family: var(--tg-sans);
1012
+ border: 1px solid var(--tg-border);
1013
+ }
1014
+ .ppm-cancel {
1015
+ background: transparent;
1016
+ color: var(--tg-text-dim);
1017
+ }
1018
+ .ppm-cancel:hover {
1019
+ color: var(--tg-text);
1020
+ border-color: var(--tg-border-active);
1021
+ }
1022
+ .ppm-generate {
1023
+ background: var(--tg-accent);
1024
+ color: var(--tg-bg);
1025
+ border-color: var(--tg-accent);
1026
+ }
1027
+ .ppm-generate:hover:not(:disabled) { filter: brightness(1.1); }
1028
+ .ppm-generate:disabled {
1029
+ opacity: 0.4;
1030
+ cursor: not-allowed;
1031
+ filter: none;
1032
+ }
1033
+
765
1034
  /* ===== Rumen insights badge + briefing modal ===== */
766
1035
  .rumen-badge {
767
1036
  display: none;
@@ -2465,3 +2734,919 @@
2465
2734
  @media (min-width: 1920px) {
2466
2735
  .term-panel { min-height: 200px; min-width: 300px; }
2467
2736
  }
2737
+
2738
+ /* ===== ORCHESTRATOR GUIDE RIGHT-RAIL (Sprint 37 T1) =====
2739
+ Fixed-position rail so it doesn't disrupt the grid flow. Default
2740
+ collapsed: a 32px tab strip on the right edge. Expanded: 360px panel
2741
+ sliding in from the right, overlaying the rightmost grid area. The
2742
+ grid keeps its full width — overlap is by design so we don't have
2743
+ to reflow .grid-container or the orchestrator-grid CSS at lines
2744
+ 315-344. */
2745
+ .guide-rail {
2746
+ position: fixed;
2747
+ top: 74px; /* below two-row topbar (42 + 32) */
2748
+ right: 0;
2749
+ bottom: 50px; /* above prompt-bar */
2750
+ width: 32px;
2751
+ z-index: 50; /* above grid, below modals (>=1000) */
2752
+ display: flex;
2753
+ pointer-events: none;
2754
+ font-family: var(--tg-sans);
2755
+ transition: width 180ms ease;
2756
+ }
2757
+ .guide-rail[data-collapsed="false"] {
2758
+ width: 360px;
2759
+ }
2760
+ .guide-rail-toggle {
2761
+ pointer-events: auto;
2762
+ flex: 0 0 32px;
2763
+ writing-mode: vertical-rl;
2764
+ transform: rotate(180deg);
2765
+ background: var(--tg-surface);
2766
+ border: 1px solid var(--tg-border);
2767
+ border-right: none;
2768
+ border-radius: var(--tg-radius-sm) 0 0 var(--tg-radius-sm);
2769
+ color: var(--tg-text-dim);
2770
+ cursor: pointer;
2771
+ padding: 12px 6px;
2772
+ display: flex;
2773
+ align-items: center;
2774
+ justify-content: center;
2775
+ gap: 8px;
2776
+ font-size: 11px;
2777
+ letter-spacing: 0.4px;
2778
+ text-transform: uppercase;
2779
+ transition: background 0.15s, color 0.15s, border-color 0.15s;
2780
+ align-self: stretch;
2781
+ }
2782
+ .guide-rail-toggle:hover {
2783
+ background: var(--tg-surface-hover);
2784
+ color: var(--tg-text-bright);
2785
+ border-color: var(--tg-border-active);
2786
+ }
2787
+ .guide-rail[data-collapsed="false"] .guide-rail-toggle {
2788
+ color: var(--tg-accent);
2789
+ }
2790
+ .guide-rail-toggle .grt-icon {
2791
+ writing-mode: horizontal-tb;
2792
+ transform: rotate(180deg);
2793
+ font-size: 13px;
2794
+ opacity: 0.85;
2795
+ }
2796
+ .guide-rail-body {
2797
+ pointer-events: auto;
2798
+ flex: 1 1 auto;
2799
+ background: var(--tg-surface);
2800
+ border: 1px solid var(--tg-border);
2801
+ border-right: none;
2802
+ border-radius: var(--tg-radius) 0 0 var(--tg-radius);
2803
+ display: flex;
2804
+ flex-direction: column;
2805
+ min-width: 0;
2806
+ box-shadow: -4px 0 16px rgba(0, 0, 0, 0.25);
2807
+ opacity: 0;
2808
+ visibility: hidden;
2809
+ transform: translateX(8px);
2810
+ transition: opacity 180ms ease, transform 180ms ease, visibility 0s linear 180ms;
2811
+ }
2812
+ .guide-rail[data-collapsed="false"] .guide-rail-body {
2813
+ opacity: 1;
2814
+ visibility: visible;
2815
+ transform: translateX(0);
2816
+ transition: opacity 180ms ease, transform 180ms ease, visibility 0s;
2817
+ }
2818
+ .guide-rail-header {
2819
+ display: flex;
2820
+ align-items: center;
2821
+ justify-content: space-between;
2822
+ padding: 10px 14px;
2823
+ border-bottom: 1px solid var(--tg-border);
2824
+ flex-shrink: 0;
2825
+ }
2826
+ .guide-rail-header h3 {
2827
+ margin: 0;
2828
+ font-size: 13px;
2829
+ font-weight: 600;
2830
+ color: var(--tg-text-bright);
2831
+ letter-spacing: -0.2px;
2832
+ }
2833
+ .guide-rail-close {
2834
+ background: none;
2835
+ border: none;
2836
+ color: var(--tg-text-dim);
2837
+ font-size: 14px;
2838
+ cursor: pointer;
2839
+ padding: 2px 6px;
2840
+ border-radius: 3px;
2841
+ line-height: 1;
2842
+ }
2843
+ .guide-rail-close:hover {
2844
+ color: var(--tg-text-bright);
2845
+ background: var(--tg-bg);
2846
+ }
2847
+ .guide-rail-search {
2848
+ padding: 8px 12px;
2849
+ border-bottom: 1px solid var(--tg-border);
2850
+ flex-shrink: 0;
2851
+ }
2852
+ .guide-rail-search input {
2853
+ width: 100%;
2854
+ background: var(--tg-bg);
2855
+ border: 1px solid var(--tg-border);
2856
+ border-radius: var(--tg-radius-sm);
2857
+ color: var(--tg-text);
2858
+ font-family: var(--tg-sans);
2859
+ font-size: 12px;
2860
+ padding: 6px 10px;
2861
+ outline: none;
2862
+ }
2863
+ .guide-rail-search input:focus {
2864
+ border-color: var(--tg-accent-dim);
2865
+ }
2866
+ .guide-rail-toc {
2867
+ flex-shrink: 0;
2868
+ max-height: 168px;
2869
+ overflow-y: auto;
2870
+ padding: 6px 8px;
2871
+ border-bottom: 1px solid var(--tg-border);
2872
+ display: flex;
2873
+ flex-direction: column;
2874
+ gap: 1px;
2875
+ }
2876
+ .guide-rail-toc a {
2877
+ color: var(--tg-text-dim);
2878
+ text-decoration: none;
2879
+ font-size: 11.5px;
2880
+ padding: 4px 8px;
2881
+ border-radius: 3px;
2882
+ cursor: pointer;
2883
+ display: block;
2884
+ white-space: nowrap;
2885
+ overflow: hidden;
2886
+ text-overflow: ellipsis;
2887
+ }
2888
+ .guide-rail-toc a:hover {
2889
+ color: var(--tg-text-bright);
2890
+ background: var(--tg-bg);
2891
+ }
2892
+ .guide-rail-toc a.active {
2893
+ color: var(--tg-accent);
2894
+ background: var(--tg-bg);
2895
+ }
2896
+ .guide-rail-toc a.hidden { display: none; }
2897
+ .guide-rail-content {
2898
+ flex: 1 1 auto;
2899
+ overflow-y: auto;
2900
+ padding: 14px 16px 24px;
2901
+ font-size: 12.5px;
2902
+ line-height: 1.55;
2903
+ color: var(--tg-text);
2904
+ min-height: 0;
2905
+ outline: none;
2906
+ }
2907
+ .guide-rail-content.has-filter section.guide-section.hidden { display: none; }
2908
+ .guide-rail-content section.guide-section { margin: 0 0 18px; }
2909
+ .guide-rail-content section.guide-section.expanded { background: var(--tg-bg); border-radius: var(--tg-radius-sm); padding: 8px 10px; }
2910
+ .guide-rail-content h1 {
2911
+ font-size: 15px;
2912
+ color: var(--tg-text-bright);
2913
+ margin: 0 0 10px;
2914
+ font-weight: 600;
2915
+ }
2916
+ .guide-rail-content h2 {
2917
+ font-size: 13.5px;
2918
+ color: var(--tg-text-bright);
2919
+ margin: 16px 0 6px;
2920
+ font-weight: 600;
2921
+ scroll-margin-top: 8px;
2922
+ }
2923
+ .guide-rail-content h3 {
2924
+ font-size: 12.5px;
2925
+ color: var(--tg-text-bright);
2926
+ margin: 12px 0 4px;
2927
+ font-weight: 600;
2928
+ }
2929
+ .guide-rail-content p { margin: 0 0 8px; }
2930
+ .guide-rail-content ul,
2931
+ .guide-rail-content ol { margin: 4px 0 10px 18px; }
2932
+ .guide-rail-content li { margin: 2px 0; }
2933
+ .guide-rail-content code {
2934
+ background: var(--tg-bg);
2935
+ border: 1px solid var(--tg-border);
2936
+ border-radius: 3px;
2937
+ padding: 1px 4px;
2938
+ font-family: var(--tg-mono);
2939
+ font-size: 11px;
2940
+ color: var(--tg-cyan);
2941
+ }
2942
+ .guide-rail-content pre {
2943
+ background: var(--tg-bg);
2944
+ border: 1px solid var(--tg-border);
2945
+ border-radius: var(--tg-radius-sm);
2946
+ padding: 8px 10px;
2947
+ margin: 6px 0 10px;
2948
+ overflow-x: auto;
2949
+ }
2950
+ .guide-rail-content pre code {
2951
+ background: none;
2952
+ border: none;
2953
+ padding: 0;
2954
+ color: var(--tg-text);
2955
+ font-size: 11px;
2956
+ }
2957
+ .guide-rail-content a {
2958
+ color: var(--tg-accent);
2959
+ text-decoration: none;
2960
+ }
2961
+ .guide-rail-content a:hover { text-decoration: underline; }
2962
+ .guide-rail-content blockquote {
2963
+ border-left: 2px solid var(--tg-accent-dim);
2964
+ padding-left: 10px;
2965
+ color: var(--tg-text-dim);
2966
+ margin: 6px 0 10px;
2967
+ font-style: italic;
2968
+ }
2969
+ .guide-rail-content table {
2970
+ border-collapse: collapse;
2971
+ width: 100%;
2972
+ margin: 6px 0 10px;
2973
+ font-size: 11.5px;
2974
+ }
2975
+ .guide-rail-content th,
2976
+ .guide-rail-content td {
2977
+ border: 1px solid var(--tg-border);
2978
+ padding: 4px 8px;
2979
+ text-align: left;
2980
+ vertical-align: top;
2981
+ }
2982
+ .guide-rail-content th {
2983
+ background: var(--tg-bg);
2984
+ color: var(--tg-text-bright);
2985
+ font-weight: 600;
2986
+ }
2987
+ .guide-rail-content hr {
2988
+ border: none;
2989
+ border-top: 1px solid var(--tg-border);
2990
+ margin: 14px 0;
2991
+ }
2992
+ .guide-rail-content em.no-match {
2993
+ display: block;
2994
+ text-align: center;
2995
+ color: var(--tg-text-dim);
2996
+ padding: 24px 12px;
2997
+ font-style: normal;
2998
+ }
2999
+ .guide-loading {
3000
+ color: var(--tg-text-dim);
3001
+ font-size: 12px;
3002
+ padding: 8px 0;
3003
+ font-style: italic;
3004
+ }
3005
+
3006
+ /* On narrow viewports the rail would eat the whole grid — keep the tab
3007
+ always visible but cap expanded width. */
3008
+ @media (max-width: 900px) {
3009
+ .guide-rail[data-collapsed="false"] { width: min(360px, 80vw); }
3010
+ }
3011
+
3012
+ /* ===== SPRINT RUNNER MODAL (Sprint 37 T4) ===== */
3013
+ .sprint-modal {
3014
+ display: none;
3015
+ position: fixed;
3016
+ inset: 0;
3017
+ z-index: 3100;
3018
+ align-items: center;
3019
+ justify-content: center;
3020
+ }
3021
+ .sprint-modal.open { display: flex; }
3022
+ .sprint-backdrop {
3023
+ position: absolute;
3024
+ inset: 0;
3025
+ background: rgba(0, 0, 0, 0.72);
3026
+ }
3027
+ .sprint-card {
3028
+ position: relative;
3029
+ background: var(--tg-surface);
3030
+ border: 1px solid var(--tg-accent-dim);
3031
+ border-radius: 10px;
3032
+ padding: 22px 24px 18px;
3033
+ width: 720px;
3034
+ max-width: calc(100vw - 40px);
3035
+ max-height: calc(100vh - 60px);
3036
+ overflow-y: auto;
3037
+ box-shadow: 0 16px 48px rgba(0, 0, 0, 0.55);
3038
+ font-family: var(--tg-sans);
3039
+ color: var(--tg-text);
3040
+ }
3041
+ .sprint-card h3 {
3042
+ margin: 0 0 4px;
3043
+ font-size: 16px;
3044
+ color: var(--tg-accent);
3045
+ }
3046
+ .sprint-help {
3047
+ margin: 0 0 16px;
3048
+ font-size: 12px;
3049
+ color: var(--tg-text-dim);
3050
+ line-height: 1.5;
3051
+ }
3052
+ .sprint-help code {
3053
+ background: var(--tg-bg);
3054
+ padding: 1px 5px;
3055
+ border-radius: 3px;
3056
+ font-family: var(--tg-mono);
3057
+ font-size: 11px;
3058
+ }
3059
+ .sprint-row {
3060
+ display: grid;
3061
+ grid-template-columns: 1fr 1fr 1fr;
3062
+ gap: 10px;
3063
+ margin-bottom: 10px;
3064
+ }
3065
+ .sprint-card label {
3066
+ display: block;
3067
+ margin-bottom: 10px;
3068
+ }
3069
+ .sprint-card label > span {
3070
+ display: block;
3071
+ font-size: 11px;
3072
+ color: var(--tg-text-dim);
3073
+ margin-bottom: 3px;
3074
+ text-transform: uppercase;
3075
+ letter-spacing: 0.5px;
3076
+ }
3077
+ .sprint-card label > span em {
3078
+ font-style: normal;
3079
+ text-transform: none;
3080
+ color: var(--tg-text-dim);
3081
+ opacity: 0.7;
3082
+ font-size: 10px;
3083
+ margin-left: 4px;
3084
+ }
3085
+ .sprint-full { display: block; margin-bottom: 14px; }
3086
+ .sprint-card input[type="text"],
3087
+ .sprint-card select {
3088
+ width: 100%;
3089
+ background: var(--tg-bg);
3090
+ border: 1px solid var(--tg-border);
3091
+ color: var(--tg-text);
3092
+ font-size: 13px;
3093
+ padding: 7px 10px;
3094
+ border-radius: var(--tg-radius-sm);
3095
+ font-family: var(--tg-mono);
3096
+ box-sizing: border-box;
3097
+ }
3098
+ .sprint-card input[type="text"]:focus,
3099
+ .sprint-card select:focus {
3100
+ outline: none;
3101
+ border-color: var(--tg-accent-dim);
3102
+ }
3103
+ .sprint-lanes {
3104
+ display: grid;
3105
+ grid-template-columns: 1fr 1fr;
3106
+ gap: 10px;
3107
+ margin: 4px 0 14px;
3108
+ }
3109
+ .sprint-lane {
3110
+ background: var(--tg-bg);
3111
+ border: 1px solid var(--tg-border);
3112
+ border-radius: var(--tg-radius-sm);
3113
+ padding: 10px 12px;
3114
+ }
3115
+ .sprint-lane h4 {
3116
+ margin: 0 0 6px;
3117
+ font-size: 11px;
3118
+ color: var(--tg-accent);
3119
+ letter-spacing: 0.5px;
3120
+ }
3121
+ .sprint-lane .sprint-lane-name { margin-bottom: 6px; }
3122
+ .sprint-options { margin: 8px 0 12px; }
3123
+ .sprint-check {
3124
+ display: flex;
3125
+ align-items: flex-start;
3126
+ gap: 8px;
3127
+ font-size: 12px;
3128
+ color: var(--tg-text-dim);
3129
+ margin-bottom: 6px;
3130
+ }
3131
+ .sprint-check input { margin-top: 2px; }
3132
+ .sprint-check em { font-style: normal; opacity: 0.7; margin-left: 4px; }
3133
+ .sprint-status {
3134
+ font-size: 12px;
3135
+ min-height: 16px;
3136
+ margin: 4px 0 8px;
3137
+ color: var(--tg-text-dim);
3138
+ }
3139
+ .sprint-status.error { color: var(--tg-red); }
3140
+ .sprint-status.ok { color: var(--tg-green); }
3141
+ .sprint-actions {
3142
+ display: flex;
3143
+ justify-content: flex-end;
3144
+ gap: 8px;
3145
+ margin-top: 8px;
3146
+ }
3147
+ .sprint-cancel,
3148
+ .sprint-kickoff {
3149
+ padding: 7px 14px;
3150
+ border-radius: var(--tg-radius-sm);
3151
+ border: 1px solid var(--tg-border);
3152
+ background: var(--tg-bg);
3153
+ color: var(--tg-text);
3154
+ font-family: var(--tg-sans);
3155
+ font-size: 12px;
3156
+ cursor: pointer;
3157
+ }
3158
+ .sprint-kickoff {
3159
+ border-color: var(--tg-accent-dim);
3160
+ background: var(--tg-accent-dim);
3161
+ color: var(--tg-bg);
3162
+ font-weight: 600;
3163
+ }
3164
+ .sprint-kickoff:disabled { opacity: 0.55; cursor: not-allowed; }
3165
+ .sprint-cancel:hover { border-color: var(--tg-accent-dim); }
3166
+
3167
+ .sprint-result h4 {
3168
+ margin: 4px 0 8px;
3169
+ font-size: 14px;
3170
+ color: var(--tg-accent);
3171
+ }
3172
+ .sprint-result-meta {
3173
+ font-family: var(--tg-mono);
3174
+ font-size: 11px;
3175
+ color: var(--tg-text-dim);
3176
+ margin-bottom: 12px;
3177
+ line-height: 1.5;
3178
+ }
3179
+ .sprint-lanes-status {
3180
+ display: grid;
3181
+ grid-template-columns: 1fr 1fr 1fr 1fr;
3182
+ gap: 8px;
3183
+ margin-bottom: 14px;
3184
+ }
3185
+ .sprint-lane-status {
3186
+ background: var(--tg-bg);
3187
+ border: 1px solid var(--tg-border);
3188
+ border-radius: var(--tg-radius-sm);
3189
+ padding: 8px 10px;
3190
+ font-family: var(--tg-mono);
3191
+ }
3192
+ .sprint-lane-status h4 {
3193
+ margin: 0 0 4px;
3194
+ font-size: 11px;
3195
+ color: var(--tg-accent);
3196
+ }
3197
+ .sprint-lane-status .counts {
3198
+ font-size: 12px;
3199
+ color: var(--tg-text);
3200
+ }
3201
+ .sprint-lane-status .last-entry {
3202
+ font-size: 10px;
3203
+ color: var(--tg-text-dim);
3204
+ margin-top: 2px;
3205
+ }
3206
+ .sprint-tail-wrap h5 {
3207
+ margin: 0 0 4px;
3208
+ font-size: 11px;
3209
+ color: var(--tg-text-dim);
3210
+ text-transform: uppercase;
3211
+ letter-spacing: 0.5px;
3212
+ }
3213
+ .sprint-tail {
3214
+ background: var(--tg-bg);
3215
+ border: 1px solid var(--tg-border);
3216
+ border-radius: var(--tg-radius-sm);
3217
+ padding: 10px 12px;
3218
+ font-family: var(--tg-mono);
3219
+ font-size: 11px;
3220
+ color: var(--tg-text);
3221
+ max-height: 240px;
3222
+ overflow: auto;
3223
+ white-space: pre-wrap;
3224
+ margin: 0 0 12px;
3225
+ }
3226
+
3227
+ /* ===== Knowledge graph view (Sprint 38 T4) ===== */
3228
+ /* Standalone /graph.html. The body opts in via .graph-page so dashboard
3229
+ styles aren't inadvertently applied (no terminal grid, no panel chrome). */
3230
+
3231
+ body.graph-page {
3232
+ margin: 0;
3233
+ padding: 0;
3234
+ background: var(--tg-bg);
3235
+ color: var(--tg-text);
3236
+ font-family: var(--tg-sans);
3237
+ overflow: hidden;
3238
+ display: flex;
3239
+ flex-direction: column;
3240
+ height: 100vh;
3241
+ }
3242
+
3243
+ .graph-topbar {
3244
+ display: flex;
3245
+ align-items: center;
3246
+ gap: 16px;
3247
+ padding: 8px 16px;
3248
+ background: var(--tg-surface);
3249
+ border-bottom: 1px solid var(--tg-border);
3250
+ flex-shrink: 0;
3251
+ min-height: 44px;
3252
+ }
3253
+ .graph-tb-left {
3254
+ display: flex;
3255
+ align-items: center;
3256
+ gap: 8px;
3257
+ }
3258
+ .graph-tb-back {
3259
+ display: inline-flex;
3260
+ align-items: center;
3261
+ gap: 6px;
3262
+ color: var(--tg-text-bright);
3263
+ text-decoration: none;
3264
+ font-weight: 600;
3265
+ padding: 4px 8px;
3266
+ border-radius: var(--tg-radius-sm);
3267
+ transition: background 120ms;
3268
+ }
3269
+ .graph-tb-back:hover { background: var(--tg-surface-hover); }
3270
+ .graph-tb-divider {
3271
+ color: var(--tg-text-dim);
3272
+ }
3273
+ .graph-tb-title {
3274
+ color: var(--tg-text);
3275
+ font-weight: 500;
3276
+ }
3277
+ .graph-tb-controls {
3278
+ display: flex;
3279
+ align-items: center;
3280
+ gap: 12px;
3281
+ flex: 1;
3282
+ justify-content: center;
3283
+ }
3284
+ .graph-tb-control {
3285
+ display: inline-flex;
3286
+ align-items: center;
3287
+ gap: 6px;
3288
+ font-size: 12px;
3289
+ color: var(--tg-text-dim);
3290
+ }
3291
+ .graph-tb-control select,
3292
+ .graph-tb-control input {
3293
+ background: var(--tg-bg);
3294
+ color: var(--tg-text);
3295
+ border: 1px solid var(--tg-border);
3296
+ border-radius: var(--tg-radius-sm);
3297
+ padding: 5px 8px;
3298
+ font-family: var(--tg-mono);
3299
+ font-size: 12px;
3300
+ min-width: 140px;
3301
+ }
3302
+ .graph-tb-control select:focus,
3303
+ .graph-tb-control input:focus {
3304
+ outline: none;
3305
+ border-color: var(--tg-accent);
3306
+ }
3307
+ .graph-tb-search-wrap input {
3308
+ min-width: 220px;
3309
+ }
3310
+ .graph-tb-btn {
3311
+ background: var(--tg-bg);
3312
+ color: var(--tg-text);
3313
+ border: 1px solid var(--tg-border);
3314
+ border-radius: var(--tg-radius-sm);
3315
+ padding: 5px 10px;
3316
+ font-size: 12px;
3317
+ font-family: var(--tg-mono);
3318
+ cursor: pointer;
3319
+ transition: all 120ms;
3320
+ }
3321
+ .graph-tb-btn:hover {
3322
+ background: var(--tg-surface-hover);
3323
+ border-color: var(--tg-border-active);
3324
+ }
3325
+ .graph-tb-right {
3326
+ display: flex;
3327
+ gap: 12px;
3328
+ align-items: center;
3329
+ }
3330
+ .graph-tb-stat {
3331
+ font-size: 11px;
3332
+ font-family: var(--tg-mono);
3333
+ color: var(--tg-text-dim);
3334
+ padding: 3px 8px;
3335
+ background: var(--tg-bg);
3336
+ border: 1px solid var(--tg-border);
3337
+ border-radius: 999px;
3338
+ }
3339
+
3340
+ .graph-filters {
3341
+ display: flex;
3342
+ gap: 6px;
3343
+ padding: 8px 16px;
3344
+ background: var(--tg-surface);
3345
+ border-bottom: 1px solid var(--tg-border);
3346
+ flex-wrap: wrap;
3347
+ flex-shrink: 0;
3348
+ align-items: center;
3349
+ }
3350
+ .gf-chip {
3351
+ display: inline-flex;
3352
+ align-items: center;
3353
+ gap: 6px;
3354
+ padding: 3px 9px 3px 7px;
3355
+ font-size: 11px;
3356
+ font-family: var(--tg-mono);
3357
+ color: var(--tg-text-dim);
3358
+ background: var(--tg-bg);
3359
+ border: 1px solid var(--tg-border);
3360
+ border-radius: 999px;
3361
+ cursor: pointer;
3362
+ transition: all 150ms;
3363
+ opacity: 0.55;
3364
+ }
3365
+ .gf-chip:hover { opacity: 1; }
3366
+ .gf-chip.active {
3367
+ opacity: 1;
3368
+ color: var(--tg-text-bright);
3369
+ background: var(--tg-surface-hover);
3370
+ }
3371
+ .gf-chip-dot {
3372
+ width: 8px;
3373
+ height: 8px;
3374
+ border-radius: 50%;
3375
+ flex-shrink: 0;
3376
+ }
3377
+ .gf-chip-count {
3378
+ color: var(--tg-text-dim);
3379
+ font-size: 10px;
3380
+ padding: 0 4px;
3381
+ background: rgba(255, 255, 255, 0.04);
3382
+ border-radius: 999px;
3383
+ }
3384
+ .gf-chip.active .gf-chip-count {
3385
+ color: var(--tg-text);
3386
+ background: rgba(255, 255, 255, 0.08);
3387
+ }
3388
+
3389
+ .graph-stage {
3390
+ position: relative;
3391
+ flex: 1;
3392
+ overflow: hidden;
3393
+ background: var(--tg-bg);
3394
+ }
3395
+ .graph-svg {
3396
+ display: block;
3397
+ width: 100%;
3398
+ height: 100%;
3399
+ cursor: grab;
3400
+ }
3401
+ .graph-svg:active {
3402
+ cursor: grabbing;
3403
+ }
3404
+ .graph-zoom-root {
3405
+ will-change: transform;
3406
+ }
3407
+ .graph-nodes circle {
3408
+ transition: stroke 200ms, opacity 200ms;
3409
+ }
3410
+ .graph-nodes circle:hover {
3411
+ stroke: #eef1ff;
3412
+ stroke-width: 2;
3413
+ }
3414
+ .graph-edges line {
3415
+ transition: stroke-opacity 200ms;
3416
+ }
3417
+
3418
+ @keyframes graph-node-pulse {
3419
+ 0% { stroke-width: 1.2; }
3420
+ 50% { stroke-width: 4; stroke: #eef1ff; }
3421
+ 100% { stroke-width: 1.2; }
3422
+ }
3423
+ .graph-node-pulse {
3424
+ animation: graph-node-pulse 1.4s ease-in-out infinite;
3425
+ }
3426
+
3427
+ .graph-loading,
3428
+ .graph-empty {
3429
+ position: absolute;
3430
+ inset: 0;
3431
+ display: flex;
3432
+ flex-direction: column;
3433
+ align-items: center;
3434
+ justify-content: center;
3435
+ gap: 12px;
3436
+ color: var(--tg-text-dim);
3437
+ font-family: var(--tg-mono);
3438
+ pointer-events: none;
3439
+ padding: 24px;
3440
+ text-align: center;
3441
+ }
3442
+ .graph-loading-spinner {
3443
+ width: 28px;
3444
+ height: 28px;
3445
+ border-radius: 50%;
3446
+ border: 2px solid var(--tg-border);
3447
+ border-top-color: var(--tg-accent);
3448
+ animation: graph-spin 720ms linear infinite;
3449
+ }
3450
+ @keyframes graph-spin {
3451
+ to { transform: rotate(360deg); }
3452
+ }
3453
+ .graph-empty h3 {
3454
+ color: var(--tg-text);
3455
+ margin: 0;
3456
+ font-size: 16px;
3457
+ font-family: var(--tg-sans);
3458
+ }
3459
+ .graph-empty p {
3460
+ max-width: 540px;
3461
+ line-height: 1.55;
3462
+ color: var(--tg-text-dim);
3463
+ margin: 0;
3464
+ }
3465
+ .graph-empty code {
3466
+ background: var(--tg-surface);
3467
+ padding: 1px 5px;
3468
+ border-radius: 3px;
3469
+ font-size: 11px;
3470
+ }
3471
+
3472
+ .graph-tooltip {
3473
+ position: fixed;
3474
+ pointer-events: none;
3475
+ background: rgba(15, 17, 23, 0.95);
3476
+ color: var(--tg-text);
3477
+ border: 1px solid var(--tg-border-active);
3478
+ border-radius: var(--tg-radius-sm);
3479
+ padding: 6px 10px;
3480
+ font-family: var(--tg-mono);
3481
+ font-size: 11px;
3482
+ backdrop-filter: blur(6px);
3483
+ box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
3484
+ z-index: 50;
3485
+ max-width: 320px;
3486
+ }
3487
+
3488
+ /* Drawer — right-side overlay shown when a node is clicked. */
3489
+ .graph-drawer {
3490
+ position: absolute;
3491
+ top: 0;
3492
+ right: 0;
3493
+ width: 420px;
3494
+ max-width: 90vw;
3495
+ height: 100%;
3496
+ background: var(--tg-surface);
3497
+ border-left: 1px solid var(--tg-border);
3498
+ box-shadow: -8px 0 24px rgba(0, 0, 0, 0.35);
3499
+ display: flex;
3500
+ flex-direction: column;
3501
+ transform: translateX(100%);
3502
+ transition: transform 220ms ease-out;
3503
+ z-index: 30;
3504
+ }
3505
+ .graph-drawer.open {
3506
+ transform: translateX(0);
3507
+ }
3508
+ .graph-drawer-header {
3509
+ display: flex;
3510
+ align-items: center;
3511
+ justify-content: space-between;
3512
+ padding: 12px 14px;
3513
+ border-bottom: 1px solid var(--tg-border);
3514
+ flex-shrink: 0;
3515
+ }
3516
+ .gd-h-meta {
3517
+ display: flex;
3518
+ gap: 8px;
3519
+ align-items: center;
3520
+ font-family: var(--tg-mono);
3521
+ font-size: 11px;
3522
+ color: var(--tg-text-dim);
3523
+ }
3524
+ .gd-project {
3525
+ font-weight: 600;
3526
+ color: var(--tg-text-bright);
3527
+ }
3528
+ .gd-source-type {
3529
+ padding: 1px 6px;
3530
+ background: var(--tg-bg);
3531
+ border-radius: 3px;
3532
+ border: 1px solid var(--tg-border);
3533
+ }
3534
+ .gd-created::before {
3535
+ content: '·';
3536
+ margin-right: 6px;
3537
+ color: var(--tg-border-active);
3538
+ }
3539
+ .graph-drawer-close {
3540
+ background: transparent;
3541
+ border: 0;
3542
+ color: var(--tg-text-dim);
3543
+ font-size: 20px;
3544
+ line-height: 1;
3545
+ cursor: pointer;
3546
+ padding: 4px 8px;
3547
+ border-radius: var(--tg-radius-sm);
3548
+ }
3549
+ .graph-drawer-close:hover {
3550
+ color: var(--tg-text-bright);
3551
+ background: var(--tg-surface-hover);
3552
+ }
3553
+ .graph-drawer-body {
3554
+ flex: 1;
3555
+ overflow: auto;
3556
+ padding: 14px;
3557
+ }
3558
+ .gd-content {
3559
+ background: var(--tg-bg);
3560
+ border: 1px solid var(--tg-border);
3561
+ border-radius: var(--tg-radius-sm);
3562
+ padding: 12px;
3563
+ font-family: var(--tg-mono);
3564
+ font-size: 12px;
3565
+ color: var(--tg-text);
3566
+ white-space: pre-wrap;
3567
+ word-break: break-word;
3568
+ max-height: 40vh;
3569
+ overflow: auto;
3570
+ margin: 0 0 16px;
3571
+ }
3572
+ .gd-section {
3573
+ margin: 0 0 8px;
3574
+ font-size: 11px;
3575
+ text-transform: uppercase;
3576
+ letter-spacing: 0.5px;
3577
+ color: var(--tg-text-dim);
3578
+ font-family: var(--tg-mono);
3579
+ }
3580
+ .gd-neighbors {
3581
+ display: flex;
3582
+ flex-direction: column;
3583
+ gap: 4px;
3584
+ }
3585
+ .gd-neighbor {
3586
+ display: grid;
3587
+ grid-template-columns: 10px 1fr auto;
3588
+ align-items: center;
3589
+ gap: 8px;
3590
+ padding: 7px 8px;
3591
+ background: var(--tg-bg);
3592
+ border: 1px solid var(--tg-border);
3593
+ border-radius: var(--tg-radius-sm);
3594
+ cursor: pointer;
3595
+ text-align: left;
3596
+ transition: border-color 120ms, background 120ms;
3597
+ font-family: var(--tg-sans);
3598
+ color: var(--tg-text);
3599
+ }
3600
+ .gd-neighbor:hover {
3601
+ border-color: var(--tg-border-active);
3602
+ background: var(--tg-surface-hover);
3603
+ }
3604
+ .gd-neighbor-dot {
3605
+ width: 8px;
3606
+ height: 8px;
3607
+ border-radius: 50%;
3608
+ }
3609
+ .gd-neighbor-label {
3610
+ font-size: 12px;
3611
+ overflow: hidden;
3612
+ text-overflow: ellipsis;
3613
+ white-space: nowrap;
3614
+ }
3615
+ .gd-neighbor-meta {
3616
+ font-size: 10px;
3617
+ color: var(--tg-text-dim);
3618
+ font-family: var(--tg-mono);
3619
+ }
3620
+ .gd-empty {
3621
+ padding: 20px 12px;
3622
+ text-align: center;
3623
+ color: var(--tg-text-dim);
3624
+ font-size: 12px;
3625
+ background: var(--tg-bg);
3626
+ border: 1px dashed var(--tg-border);
3627
+ border-radius: var(--tg-radius-sm);
3628
+ }
3629
+ .graph-drawer-footer {
3630
+ display: flex;
3631
+ gap: 8px;
3632
+ padding: 10px 14px;
3633
+ border-top: 1px solid var(--tg-border);
3634
+ flex-shrink: 0;
3635
+ }
3636
+ .graph-drawer-action {
3637
+ flex: 1;
3638
+ background: var(--tg-bg);
3639
+ color: var(--tg-text);
3640
+ border: 1px solid var(--tg-border);
3641
+ border-radius: var(--tg-radius-sm);
3642
+ padding: 6px 10px;
3643
+ font-size: 12px;
3644
+ font-family: var(--tg-mono);
3645
+ cursor: pointer;
3646
+ transition: all 120ms;
3647
+ }
3648
+ .graph-drawer-action:hover {
3649
+ background: var(--tg-surface-hover);
3650
+ border-color: var(--tg-border-active);
3651
+ color: var(--tg-text-bright);
3652
+ }