@worca/ui 0.38.0 → 0.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/main.bundle.js +4060 -3456
- package/app/main.bundle.js.map +4 -4
- package/app/styles.css +1068 -2
- package/package.json +1 -1
- package/server/app.js +17 -0
- package/server/project-routes.js +7 -39
- package/server/templates-routes.js +742 -0
- package/server/version-check.js +11 -2
package/app/styles.css
CHANGED
|
@@ -10,6 +10,16 @@
|
|
|
10
10
|
--bg: #ffffff;
|
|
11
11
|
--bg-secondary: #f8fafc;
|
|
12
12
|
--bg-tertiary: #f1f5f9;
|
|
13
|
+
/* Card / panel surface. `--surface` was used in several places
|
|
14
|
+
* (`.run-card`, sidebar widgets, settings cards) without ever
|
|
15
|
+
* being defined, so it silently resolved to `unset` → no
|
|
16
|
+
* background. That was invisible while the page background and
|
|
17
|
+
* cards were both white, but the moment a parent panel tinted
|
|
18
|
+
* itself gray (e.g. `.pipelines-tier-section` → `--bg-secondary`)
|
|
19
|
+
* the cards turned transparent. Alias it to `--bg` so cards
|
|
20
|
+
* always render on a white (light) / dark-slate (dark) surface
|
|
21
|
+
* regardless of what's behind them. */
|
|
22
|
+
--surface: var(--bg);
|
|
13
23
|
--border: #e2e8f0;
|
|
14
24
|
--border-subtle: rgba(226, 232, 240, 0.6);
|
|
15
25
|
--muted: #94a3b8;
|
|
@@ -2942,7 +2952,18 @@ sl-option.template-grouped::part(label) {
|
|
|
2942
2952
|
font-weight: 500;
|
|
2943
2953
|
}
|
|
2944
2954
|
|
|
2945
|
-
/* Description wraps below name, aligned with label
|
|
2955
|
+
/* Description wraps below name, aligned with the label's left edge.
|
|
2956
|
+
* Shoelace renders the option as `[checked-icon] [prefix] [label] [suffix]`
|
|
2957
|
+
* on a single flex row. With `flex-wrap: wrap`, the suffix lands on
|
|
2958
|
+
* a new line — but at the parent's left edge, NOT under the label.
|
|
2959
|
+
* We push it back so "ID: foo" sits directly under "Foo" instead of
|
|
2960
|
+
* indented to the prefix slot. Shoelace's prefix slot is ~24px wide
|
|
2961
|
+
* by default; we use the same offset as the label's apparent x.
|
|
2962
|
+
*
|
|
2963
|
+
* The 14px is empirical: 24px ::part(base) padding-left minus the
|
|
2964
|
+
* ~10px the prefix slot is currently empty (no checkmark on
|
|
2965
|
+
* non-selected items). Adjust if Shoelace changes its inner spacing.
|
|
2966
|
+
*/
|
|
2946
2967
|
sl-option.template-grouped::part(suffix) {
|
|
2947
2968
|
flex-basis: 100%;
|
|
2948
2969
|
font-size: 11px;
|
|
@@ -2951,7 +2972,7 @@ sl-option.template-grouped::part(suffix) {
|
|
|
2951
2972
|
white-space: nowrap;
|
|
2952
2973
|
overflow: hidden;
|
|
2953
2974
|
text-overflow: ellipsis;
|
|
2954
|
-
padding: 0 0 4px;
|
|
2975
|
+
padding: 0 0 4px 14px;
|
|
2955
2976
|
}
|
|
2956
2977
|
|
|
2957
2978
|
/* Fix contrast on selected/current option description */
|
|
@@ -6739,3 +6760,1048 @@ sl-dialog.markdown-dialog::part(body) {
|
|
|
6739
6760
|
font-size: 0.8rem;
|
|
6740
6761
|
word-break: break-all;
|
|
6741
6762
|
}
|
|
6763
|
+
|
|
6764
|
+
/* --- Pipelines view --- */
|
|
6765
|
+
|
|
6766
|
+
.pipelines-view {
|
|
6767
|
+
padding: 24px 0;
|
|
6768
|
+
}
|
|
6769
|
+
|
|
6770
|
+
.pipelines-content {
|
|
6771
|
+
display: flex;
|
|
6772
|
+
flex-direction: column;
|
|
6773
|
+
gap: 24px;
|
|
6774
|
+
}
|
|
6775
|
+
|
|
6776
|
+
.pipelines-loading-spinner {
|
|
6777
|
+
display: flex;
|
|
6778
|
+
justify-content: center;
|
|
6779
|
+
padding: 48px;
|
|
6780
|
+
font-size: 32px;
|
|
6781
|
+
}
|
|
6782
|
+
|
|
6783
|
+
/*
|
|
6784
|
+
* Tier sections are sl-details collapsibles. The summary slot holds a
|
|
6785
|
+
* 2-row grid: top row [icon | TITLE | count | spacer], bottom row a
|
|
6786
|
+
* one-line description that wraps under the title. Shoelace's own
|
|
6787
|
+
* chevron sits to the right of our summary content.
|
|
6788
|
+
*/
|
|
6789
|
+
.pipelines-tier-section {
|
|
6790
|
+
margin-bottom: 0;
|
|
6791
|
+
}
|
|
6792
|
+
.pipelines-tier-section::part(base) {
|
|
6793
|
+
border: 1px solid var(--border-subtle, var(--border));
|
|
6794
|
+
border-radius: var(--radius-lg);
|
|
6795
|
+
/* Match the new-run-section panel chrome so the tier sections
|
|
6796
|
+
* read as the same kind of grouping (gray-tinted surface holding
|
|
6797
|
+
* a heading + a stack of items). Previously these were on the
|
|
6798
|
+
* default `--surface`, which left the cards floating with no
|
|
6799
|
+
* visual hierarchy against the page background. */
|
|
6800
|
+
background: var(--bg-secondary);
|
|
6801
|
+
}
|
|
6802
|
+
.pipelines-tier-section::part(header) {
|
|
6803
|
+
padding: 12px 16px;
|
|
6804
|
+
}
|
|
6805
|
+
.pipelines-tier-section::part(content) {
|
|
6806
|
+
padding: 12px 16px 16px;
|
|
6807
|
+
}
|
|
6808
|
+
|
|
6809
|
+
/* The summary's flex container: lay out icon + title + count + desc. */
|
|
6810
|
+
.tier-section-header {
|
|
6811
|
+
display: grid;
|
|
6812
|
+
grid-template-columns: auto auto auto 1fr;
|
|
6813
|
+
grid-template-rows: auto auto;
|
|
6814
|
+
align-items: center;
|
|
6815
|
+
gap: 4px 10px;
|
|
6816
|
+
width: 100%;
|
|
6817
|
+
}
|
|
6818
|
+
.tier-section-icon {
|
|
6819
|
+
display: inline-flex;
|
|
6820
|
+
align-items: center;
|
|
6821
|
+
color: var(--fg-muted);
|
|
6822
|
+
grid-row: 1;
|
|
6823
|
+
}
|
|
6824
|
+
.tier-section-title {
|
|
6825
|
+
font-size: 12px;
|
|
6826
|
+
font-weight: 600;
|
|
6827
|
+
letter-spacing: 0.08em;
|
|
6828
|
+
text-transform: uppercase;
|
|
6829
|
+
color: var(--fg-muted);
|
|
6830
|
+
grid-row: 1;
|
|
6831
|
+
}
|
|
6832
|
+
.tier-section-count {
|
|
6833
|
+
grid-row: 1;
|
|
6834
|
+
font-size: 11px;
|
|
6835
|
+
justify-self: start;
|
|
6836
|
+
}
|
|
6837
|
+
.tier-section-desc {
|
|
6838
|
+
grid-row: 2;
|
|
6839
|
+
grid-column: 2 / -1;
|
|
6840
|
+
margin: 0;
|
|
6841
|
+
color: var(--fg-muted);
|
|
6842
|
+
font-size: 13px;
|
|
6843
|
+
line-height: 1.4;
|
|
6844
|
+
font-weight: 400;
|
|
6845
|
+
text-transform: none;
|
|
6846
|
+
letter-spacing: 0;
|
|
6847
|
+
}
|
|
6848
|
+
|
|
6849
|
+
/*
|
|
6850
|
+
* Empty-tier placeholder — sits inside an otherwise normal
|
|
6851
|
+
* .pipelines-tier-section so the page never collapses around an empty
|
|
6852
|
+
* tier. Uses the dashed Settings-style border to read as "absence,
|
|
6853
|
+
* not error".
|
|
6854
|
+
*/
|
|
6855
|
+
.tier-section-empty {
|
|
6856
|
+
display: flex;
|
|
6857
|
+
flex-direction: column;
|
|
6858
|
+
gap: 6px;
|
|
6859
|
+
padding: 18px 20px;
|
|
6860
|
+
border: 1px dashed var(--border-subtle, var(--border));
|
|
6861
|
+
border-radius: var(--radius-lg);
|
|
6862
|
+
background: var(--surface);
|
|
6863
|
+
}
|
|
6864
|
+
.tier-section-empty-title {
|
|
6865
|
+
font-weight: 600;
|
|
6866
|
+
font-size: 13px;
|
|
6867
|
+
color: var(--fg);
|
|
6868
|
+
}
|
|
6869
|
+
.tier-section-empty-desc {
|
|
6870
|
+
margin: 0;
|
|
6871
|
+
font-size: 13px;
|
|
6872
|
+
line-height: 1.4;
|
|
6873
|
+
color: var(--fg-muted);
|
|
6874
|
+
}
|
|
6875
|
+
|
|
6876
|
+
.pipelines-grid {
|
|
6877
|
+
display: grid;
|
|
6878
|
+
/* Cards 50% wider than the original 320px min — fewer per row, more
|
|
6879
|
+
room for the description text and tag chips to breathe. The gap
|
|
6880
|
+
scales with the new width so the grid still feels balanced. */
|
|
6881
|
+
grid-template-columns: repeat(auto-fill, minmax(480px, 1fr));
|
|
6882
|
+
gap: 20px;
|
|
6883
|
+
}
|
|
6884
|
+
|
|
6885
|
+
.template-card {
|
|
6886
|
+
/* +50% on the original 140px to stay proportional with the wider
|
|
6887
|
+
grid track; longer descriptions now have headroom before the card
|
|
6888
|
+
needs to grow further. */
|
|
6889
|
+
min-height: 210px;
|
|
6890
|
+
}
|
|
6891
|
+
|
|
6892
|
+
/*
|
|
6893
|
+
* "ID: <slug>" badge — pill-shaped with a subtle gray background to
|
|
6894
|
+
* read as a handle/identifier chip rather than incidental text. Sits
|
|
6895
|
+
* inline with the file-text icon, name, and Default badge on the
|
|
6896
|
+
* card's top row (mirrors the tier section header layout). Uses
|
|
6897
|
+
* Settings-style tokens (--bg-secondary, --border-subtle) so it
|
|
6898
|
+
* lands in the same visual family as our other chips and badges.
|
|
6899
|
+
*/
|
|
6900
|
+
.template-card-id-badge {
|
|
6901
|
+
display: inline-flex;
|
|
6902
|
+
align-items: baseline;
|
|
6903
|
+
gap: 4px;
|
|
6904
|
+
padding: 2px 8px;
|
|
6905
|
+
border-radius: 9999px;
|
|
6906
|
+
background: var(--bg-secondary);
|
|
6907
|
+
border: 1px solid var(--border-subtle, var(--border));
|
|
6908
|
+
max-width: max-content;
|
|
6909
|
+
min-width: 0;
|
|
6910
|
+
}
|
|
6911
|
+
.template-card-id-label {
|
|
6912
|
+
font-size: 10px;
|
|
6913
|
+
font-weight: 600;
|
|
6914
|
+
letter-spacing: 0.06em;
|
|
6915
|
+
text-transform: uppercase;
|
|
6916
|
+
color: var(--fg-muted);
|
|
6917
|
+
flex-shrink: 0;
|
|
6918
|
+
}
|
|
6919
|
+
.template-card-id {
|
|
6920
|
+
font-family: var(--sl-font-mono);
|
|
6921
|
+
font-size: 12px;
|
|
6922
|
+
color: var(--fg);
|
|
6923
|
+
background: transparent;
|
|
6924
|
+
padding: 0;
|
|
6925
|
+
white-space: nowrap;
|
|
6926
|
+
overflow: hidden;
|
|
6927
|
+
text-overflow: ellipsis;
|
|
6928
|
+
}
|
|
6929
|
+
|
|
6930
|
+
/*
|
|
6931
|
+
* Template cards inherit `cursor: pointer` and a hover lift from the
|
|
6932
|
+
* base `.run-card` rule. The `--clickable` modifier is added by the
|
|
6933
|
+
* view only when an edit/duplicate handler is wired up; in the degraded
|
|
6934
|
+
* read-only state we strip those affordances so the card looks (and
|
|
6935
|
+
* feels) inert.
|
|
6936
|
+
*/
|
|
6937
|
+
.template-card:not(.template-card--clickable) {
|
|
6938
|
+
cursor: default;
|
|
6939
|
+
}
|
|
6940
|
+
.template-card:not(.template-card--clickable):hover {
|
|
6941
|
+
background: var(--surface);
|
|
6942
|
+
box-shadow: none;
|
|
6943
|
+
transform: none;
|
|
6944
|
+
}
|
|
6945
|
+
.template-card--clickable:focus-visible {
|
|
6946
|
+
outline: 2px solid var(--accent, #4f9eff);
|
|
6947
|
+
outline-offset: 2px;
|
|
6948
|
+
}
|
|
6949
|
+
|
|
6950
|
+
.template-default-badge {
|
|
6951
|
+
margin-right: 8px;
|
|
6952
|
+
font-weight: 600;
|
|
6953
|
+
}
|
|
6954
|
+
|
|
6955
|
+
/*
|
|
6956
|
+
* Top row is just icon + name + (optional) ★ Default. The shared
|
|
6957
|
+
* `.run-card-title { flex: 1 }` rule does the right thing here:
|
|
6958
|
+
* the title soaks up the horizontal space and pushes the Default
|
|
6959
|
+
* badge to the right edge.
|
|
6960
|
+
*
|
|
6961
|
+
* The "ID:slug" handle and the description below it are both
|
|
6962
|
+
* indented to align with the title's left edge (i.e. past the
|
|
6963
|
+
* icon's column). The icon is 16px wide and the .run-card-top
|
|
6964
|
+
* gap is 10px, so 26px of left padding aligns subsequent rows
|
|
6965
|
+
* with the title.
|
|
6966
|
+
*/
|
|
6967
|
+
.template-card-id-row {
|
|
6968
|
+
display: flex;
|
|
6969
|
+
margin-top: 6px;
|
|
6970
|
+
padding-left: 26px;
|
|
6971
|
+
}
|
|
6972
|
+
.template-card .run-card-meta {
|
|
6973
|
+
padding-left: 26px;
|
|
6974
|
+
}
|
|
6975
|
+
|
|
6976
|
+
/*
|
|
6977
|
+
* Buttons pin to the card's bottom so cards of varying heights
|
|
6978
|
+
* (description length, badge presence) line their action rows up
|
|
6979
|
+
* with each other in a tier-section grid. `margin-top: auto` on
|
|
6980
|
+
* the last child of a column-flex container absorbs the extra
|
|
6981
|
+
* vertical space.
|
|
6982
|
+
*/
|
|
6983
|
+
.template-card .run-card-actions {
|
|
6984
|
+
margin-top: auto;
|
|
6985
|
+
}
|
|
6986
|
+
|
|
6987
|
+
.template-tier-badge {
|
|
6988
|
+
font-size: 12px;
|
|
6989
|
+
text-transform: uppercase;
|
|
6990
|
+
letter-spacing: 0.04em;
|
|
6991
|
+
}
|
|
6992
|
+
|
|
6993
|
+
.template-card .run-card-stages sl-tag {
|
|
6994
|
+
margin-right: 4px;
|
|
6995
|
+
margin-bottom: 4px;
|
|
6996
|
+
}
|
|
6997
|
+
|
|
6998
|
+
.pipelines-empty {
|
|
6999
|
+
display: flex;
|
|
7000
|
+
flex-direction: column;
|
|
7001
|
+
align-items: center;
|
|
7002
|
+
justify-content: center;
|
|
7003
|
+
text-align: center;
|
|
7004
|
+
padding: 64px 24px;
|
|
7005
|
+
gap: 16px;
|
|
7006
|
+
color: var(--fg-muted);
|
|
7007
|
+
}
|
|
7008
|
+
|
|
7009
|
+
.pipelines-empty .empty-state-icon {
|
|
7010
|
+
color: var(--fg-muted);
|
|
7011
|
+
opacity: 0.5;
|
|
7012
|
+
margin-bottom: 8px;
|
|
7013
|
+
}
|
|
7014
|
+
|
|
7015
|
+
.pipelines-empty h2 {
|
|
7016
|
+
margin: 0;
|
|
7017
|
+
color: var(--fg);
|
|
7018
|
+
font-size: 20px;
|
|
7019
|
+
font-weight: 600;
|
|
7020
|
+
}
|
|
7021
|
+
|
|
7022
|
+
.pipelines-empty p {
|
|
7023
|
+
max-width: 480px;
|
|
7024
|
+
margin: 0 0 16px;
|
|
7025
|
+
line-height: 1.5;
|
|
7026
|
+
color: var(--fg-muted);
|
|
7027
|
+
}
|
|
7028
|
+
|
|
7029
|
+
.pipelines-empty .empty-state-actions {
|
|
7030
|
+
display: flex;
|
|
7031
|
+
gap: 8px;
|
|
7032
|
+
margin-bottom: 8px;
|
|
7033
|
+
}
|
|
7034
|
+
|
|
7035
|
+
.pipelines-empty .empty-state-hint {
|
|
7036
|
+
font-size: 13px;
|
|
7037
|
+
color: var(--fg-muted);
|
|
7038
|
+
border-top: 1px solid var(--border);
|
|
7039
|
+
padding-top: 16px;
|
|
7040
|
+
}
|
|
7041
|
+
|
|
7042
|
+
/* Deep-link card for template-driven settings (W-062 Phase 6) */
|
|
7043
|
+
.pipelines-deep-link-card {
|
|
7044
|
+
border: 1px solid var(--border-subtle);
|
|
7045
|
+
border-radius: var(--radius-lg);
|
|
7046
|
+
background: var(--bg-secondary);
|
|
7047
|
+
padding: 16px;
|
|
7048
|
+
margin-bottom: 24px;
|
|
7049
|
+
box-shadow: var(--shadow-sm);
|
|
7050
|
+
}
|
|
7051
|
+
|
|
7052
|
+
.pipelines-deep-link-content {
|
|
7053
|
+
display: flex;
|
|
7054
|
+
align-items: center;
|
|
7055
|
+
gap: 16px;
|
|
7056
|
+
}
|
|
7057
|
+
|
|
7058
|
+
.pipelines-deep-link-icon {
|
|
7059
|
+
display: flex;
|
|
7060
|
+
align-items: center;
|
|
7061
|
+
justify-content: center;
|
|
7062
|
+
width: 40px;
|
|
7063
|
+
height: 40px;
|
|
7064
|
+
background: var(--bg-tertiary);
|
|
7065
|
+
border-radius: var(--radius);
|
|
7066
|
+
color: var(--accent);
|
|
7067
|
+
flex-shrink: 0;
|
|
7068
|
+
}
|
|
7069
|
+
|
|
7070
|
+
.pipelines-deep-link-text {
|
|
7071
|
+
flex: 1;
|
|
7072
|
+
}
|
|
7073
|
+
|
|
7074
|
+
.pipelines-deep-link-title {
|
|
7075
|
+
font-size: 14px;
|
|
7076
|
+
font-weight: 600;
|
|
7077
|
+
color: var(--fg);
|
|
7078
|
+
margin-bottom: 4px;
|
|
7079
|
+
}
|
|
7080
|
+
|
|
7081
|
+
.pipelines-deep-link-desc {
|
|
7082
|
+
font-size: 13px;
|
|
7083
|
+
color: var(--muted);
|
|
7084
|
+
line-height: 1.4;
|
|
7085
|
+
}
|
|
7086
|
+
|
|
7087
|
+
.pipelines-deep-link-btn {
|
|
7088
|
+
display: inline-flex;
|
|
7089
|
+
align-items: center;
|
|
7090
|
+
gap: 8px;
|
|
7091
|
+
padding: 8px 16px;
|
|
7092
|
+
font-size: 13px;
|
|
7093
|
+
font-weight: 500;
|
|
7094
|
+
color: var(--fg);
|
|
7095
|
+
background: var(--bg-tertiary);
|
|
7096
|
+
border: 1px solid var(--border);
|
|
7097
|
+
border-radius: var(--radius);
|
|
7098
|
+
text-decoration: none;
|
|
7099
|
+
cursor: pointer;
|
|
7100
|
+
transition: var(--transition-fast);
|
|
7101
|
+
white-space: nowrap;
|
|
7102
|
+
}
|
|
7103
|
+
|
|
7104
|
+
.pipelines-deep-link-btn:hover {
|
|
7105
|
+
background: var(--bg);
|
|
7106
|
+
border-color: var(--border-subtle);
|
|
7107
|
+
color: var(--fg-active);
|
|
7108
|
+
}
|
|
7109
|
+
|
|
7110
|
+
|
|
7111
|
+
/* ─── Pipelines Editor ─────────────────────────────────────────────── */
|
|
7112
|
+
|
|
7113
|
+
.pipelines-editor {
|
|
7114
|
+
display: flex;
|
|
7115
|
+
flex-direction: column;
|
|
7116
|
+
height: 100%;
|
|
7117
|
+
max-height: calc(100vh - 120px);
|
|
7118
|
+
}
|
|
7119
|
+
|
|
7120
|
+
/*
|
|
7121
|
+
* Editor sub-header: lives below the page chrome's "Edit Template" title.
|
|
7122
|
+
* Shows the template name + scope badge on the left, view-mode toggle on
|
|
7123
|
+
* the right. No back button here — the page chrome already provides one.
|
|
7124
|
+
*/
|
|
7125
|
+
.editor-subheader {
|
|
7126
|
+
display: flex;
|
|
7127
|
+
align-items: center;
|
|
7128
|
+
gap: 12px;
|
|
7129
|
+
padding: 12px 16px;
|
|
7130
|
+
border-bottom: 1px solid var(--border);
|
|
7131
|
+
background: var(--bg);
|
|
7132
|
+
position: sticky;
|
|
7133
|
+
top: 0;
|
|
7134
|
+
z-index: 10;
|
|
7135
|
+
}
|
|
7136
|
+
|
|
7137
|
+
.editor-subheader-title-group {
|
|
7138
|
+
display: flex;
|
|
7139
|
+
align-items: center;
|
|
7140
|
+
gap: 8px;
|
|
7141
|
+
flex: 1;
|
|
7142
|
+
min-width: 0;
|
|
7143
|
+
}
|
|
7144
|
+
|
|
7145
|
+
/*
|
|
7146
|
+
* Inline editable Name + ID + read-only Storage in the editor
|
|
7147
|
+
* subheader. All three share the same gray-pill chassis
|
|
7148
|
+
* (`.editor-field-pill`) so the row reads as a single field group;
|
|
7149
|
+
* size/weight variants live on the per-pill modifier class.
|
|
7150
|
+
*
|
|
7151
|
+
* Name is the widest (flex-grow), ID is mid-width with a monospace
|
|
7152
|
+
* input, Storage is a fixed compact pill showing the tier.
|
|
7153
|
+
*/
|
|
7154
|
+
.editor-field-pill {
|
|
7155
|
+
display: inline-flex;
|
|
7156
|
+
align-items: center;
|
|
7157
|
+
gap: 4px;
|
|
7158
|
+
padding: 2px 4px 2px 8px;
|
|
7159
|
+
border-radius: 9999px;
|
|
7160
|
+
background: var(--bg-secondary);
|
|
7161
|
+
border: 1px solid var(--border-subtle, var(--border));
|
|
7162
|
+
min-width: 0;
|
|
7163
|
+
}
|
|
7164
|
+
.editor-field-pill-label {
|
|
7165
|
+
font-size: 10px;
|
|
7166
|
+
font-weight: 600;
|
|
7167
|
+
letter-spacing: 0.06em;
|
|
7168
|
+
text-transform: uppercase;
|
|
7169
|
+
color: var(--fg-muted);
|
|
7170
|
+
flex-shrink: 0;
|
|
7171
|
+
}
|
|
7172
|
+
|
|
7173
|
+
.editor-name-pill {
|
|
7174
|
+
flex: 1 1 240px;
|
|
7175
|
+
padding-right: 4px;
|
|
7176
|
+
}
|
|
7177
|
+
.editor-name-input {
|
|
7178
|
+
flex: 1;
|
|
7179
|
+
min-width: 0;
|
|
7180
|
+
}
|
|
7181
|
+
.editor-name-input::part(form-control-input) {
|
|
7182
|
+
font-weight: 600;
|
|
7183
|
+
}
|
|
7184
|
+
.editor-name-input::part(base) {
|
|
7185
|
+
border: none;
|
|
7186
|
+
background: transparent;
|
|
7187
|
+
box-shadow: none;
|
|
7188
|
+
min-height: 22px;
|
|
7189
|
+
}
|
|
7190
|
+
|
|
7191
|
+
.editor-id-badge {
|
|
7192
|
+
flex: 0 1 240px;
|
|
7193
|
+
}
|
|
7194
|
+
.editor-id-input {
|
|
7195
|
+
flex: 1;
|
|
7196
|
+
min-width: 0;
|
|
7197
|
+
}
|
|
7198
|
+
.editor-id-input::part(form-control-input) {
|
|
7199
|
+
font-family: var(--sl-font-mono);
|
|
7200
|
+
font-size: 12px;
|
|
7201
|
+
padding: 0 6px;
|
|
7202
|
+
}
|
|
7203
|
+
.editor-id-input::part(base) {
|
|
7204
|
+
border: none;
|
|
7205
|
+
background: transparent;
|
|
7206
|
+
box-shadow: none;
|
|
7207
|
+
min-height: 22px;
|
|
7208
|
+
}
|
|
7209
|
+
|
|
7210
|
+
.editor-storage-pill {
|
|
7211
|
+
flex: 0 0 auto;
|
|
7212
|
+
padding: 2px 10px 2px 8px;
|
|
7213
|
+
}
|
|
7214
|
+
|
|
7215
|
+
/*
|
|
7216
|
+
* Description section sits above the tab group inside the scroll
|
|
7217
|
+
* area — outside any tab so it always shows. Matches the
|
|
7218
|
+
* settings-section header style (h3.settings-section-title +
|
|
7219
|
+
* settings-field + label + textarea) so the editor reads like
|
|
7220
|
+
* the rest of the app.
|
|
7221
|
+
*/
|
|
7222
|
+
.editor-description-section {
|
|
7223
|
+
display: flex;
|
|
7224
|
+
flex-direction: column;
|
|
7225
|
+
gap: 12px;
|
|
7226
|
+
padding-bottom: 16px;
|
|
7227
|
+
margin-bottom: 4px;
|
|
7228
|
+
}
|
|
7229
|
+
.editor-description-input {
|
|
7230
|
+
width: 100%;
|
|
7231
|
+
}
|
|
7232
|
+
.editor-description-input::part(textarea) {
|
|
7233
|
+
font-size: 13px;
|
|
7234
|
+
line-height: 1.5;
|
|
7235
|
+
color: var(--fg);
|
|
7236
|
+
}
|
|
7237
|
+
.editor-storage-value {
|
|
7238
|
+
font-size: 12px;
|
|
7239
|
+
font-weight: 500;
|
|
7240
|
+
color: var(--fg);
|
|
7241
|
+
text-transform: capitalize;
|
|
7242
|
+
}
|
|
7243
|
+
|
|
7244
|
+
/*
|
|
7245
|
+
* Visual error state on a field pill — used when the ID collides
|
|
7246
|
+
* with an existing template in the same tier. The border turns
|
|
7247
|
+
* warning-amber to match the inline badge that appears next to
|
|
7248
|
+
* the input and the disabled Save button.
|
|
7249
|
+
*/
|
|
7250
|
+
.editor-field-pill--invalid {
|
|
7251
|
+
border-color: var(--sl-color-warning-600, #d97706);
|
|
7252
|
+
}
|
|
7253
|
+
.editor-id-collision-badge {
|
|
7254
|
+
flex-shrink: 0;
|
|
7255
|
+
}
|
|
7256
|
+
|
|
7257
|
+
.editor-subheader-title {
|
|
7258
|
+
font-size: 16px;
|
|
7259
|
+
font-weight: 600;
|
|
7260
|
+
margin: 0;
|
|
7261
|
+
color: var(--fg);
|
|
7262
|
+
white-space: nowrap;
|
|
7263
|
+
overflow: hidden;
|
|
7264
|
+
text-overflow: ellipsis;
|
|
7265
|
+
}
|
|
7266
|
+
|
|
7267
|
+
.icon-btn {
|
|
7268
|
+
background: none;
|
|
7269
|
+
border: none;
|
|
7270
|
+
padding: 4px;
|
|
7271
|
+
border-radius: 4px;
|
|
7272
|
+
cursor: pointer;
|
|
7273
|
+
color: var(--fg-muted);
|
|
7274
|
+
transition: var(--transition-fast);
|
|
7275
|
+
}
|
|
7276
|
+
|
|
7277
|
+
.icon-btn:hover {
|
|
7278
|
+
background: var(--bg-secondary);
|
|
7279
|
+
color: var(--fg);
|
|
7280
|
+
}
|
|
7281
|
+
|
|
7282
|
+
.editor-mode-toggle {
|
|
7283
|
+
margin-left: auto;
|
|
7284
|
+
}
|
|
7285
|
+
|
|
7286
|
+
/*
|
|
7287
|
+
* Read-only badge in the editor subheader. Sits next to the tier
|
|
7288
|
+
* badge whenever we're viewing a built-in template; visually warns
|
|
7289
|
+
* the user that nothing they type here will save.
|
|
7290
|
+
*/
|
|
7291
|
+
.editor-readonly-badge {
|
|
7292
|
+
margin-left: 4px;
|
|
7293
|
+
}
|
|
7294
|
+
|
|
7295
|
+
/*
|
|
7296
|
+
* Editor content gate: when readOnly, the form controls inside each
|
|
7297
|
+
* tab panel (and the JSON view) become non-interactive — but the
|
|
7298
|
+
* tab nav stays clickable so users can move between Models /
|
|
7299
|
+
* Stages / Agents / etc. to inspect the whole template. We scope
|
|
7300
|
+
* pointer-events:none to the panels (not the whole content) so the
|
|
7301
|
+
* `<sl-tab slot="nav">` items still take clicks.
|
|
7302
|
+
*
|
|
7303
|
+
* `aria-disabled="true"` on the wrapper tells assistive tech the
|
|
7304
|
+
* surface is locked; the per-panel muted opacity signals "look,
|
|
7305
|
+
* don't touch". Inputs visually keep their value so users can still
|
|
7306
|
+
* read and copy from them.
|
|
7307
|
+
*
|
|
7308
|
+
* Cheaper than threading a `disabled` flag through every section
|
|
7309
|
+
* and every input; tradeoff is screen readers won't announce each
|
|
7310
|
+
* control as disabled — only the panel container. Acceptable for a
|
|
7311
|
+
* read-only inspector mode.
|
|
7312
|
+
*/
|
|
7313
|
+
.editor-content--readonly sl-tab-panel,
|
|
7314
|
+
.editor-content--readonly .editor-section--json {
|
|
7315
|
+
pointer-events: none;
|
|
7316
|
+
opacity: 0.7;
|
|
7317
|
+
user-select: text; /* let users still highlight + copy values */
|
|
7318
|
+
}
|
|
7319
|
+
.editor-content--readonly sl-tab-panel *,
|
|
7320
|
+
.editor-content--readonly .editor-section--json * {
|
|
7321
|
+
cursor: default !important;
|
|
7322
|
+
}
|
|
7323
|
+
|
|
7324
|
+
/*
|
|
7325
|
+
* Editor uses the same .settings-tab-content / .settings-section-title /
|
|
7326
|
+
* .settings-cards primitives as Project Settings — define one supporting
|
|
7327
|
+
* helper here (the lead-in paragraph under a section title) and a few
|
|
7328
|
+
* tab-group tweaks so the editor's tab nav sits naturally inside its
|
|
7329
|
+
* scroll container.
|
|
7330
|
+
*/
|
|
7331
|
+
.settings-section-desc {
|
|
7332
|
+
margin: -2px 0 14px;
|
|
7333
|
+
color: var(--fg-muted);
|
|
7334
|
+
font-size: 13px;
|
|
7335
|
+
line-height: 1.5;
|
|
7336
|
+
}
|
|
7337
|
+
.settings-section-desc code {
|
|
7338
|
+
background: var(--bg-secondary);
|
|
7339
|
+
padding: 1px 5px;
|
|
7340
|
+
border-radius: 4px;
|
|
7341
|
+
font-size: 12px;
|
|
7342
|
+
}
|
|
7343
|
+
|
|
7344
|
+
.editor-tab-group {
|
|
7345
|
+
--indicator-color: var(--accent, var(--sl-color-primary-600, #4f9eff));
|
|
7346
|
+
/* Keep Shoelace's default track color (subtle border under the tab
|
|
7347
|
+
* row) so the editor matches the Project Settings convention of a
|
|
7348
|
+
* horizontal line between the nav and the panel content. Used to
|
|
7349
|
+
* be `transparent` which suppressed that divider. */
|
|
7350
|
+
}
|
|
7351
|
+
.editor-tab-group::part(base) {
|
|
7352
|
+
/* Hand the scroll to .editor-content so the tab nav stays sticky. */
|
|
7353
|
+
height: 100%;
|
|
7354
|
+
}
|
|
7355
|
+
/*
|
|
7356
|
+
* Tab nav style mirrors the project Settings tabs: 13px medium,
|
|
7357
|
+
* 10/16 padding, and a clear gap between the icon and the label
|
|
7358
|
+
* so the icon doesn't visually fuse with the first letter.
|
|
7359
|
+
*/
|
|
7360
|
+
.editor-tab-group sl-tab::part(base) {
|
|
7361
|
+
font-size: 13px;
|
|
7362
|
+
font-weight: 500;
|
|
7363
|
+
padding: 10px 16px;
|
|
7364
|
+
gap: 6px;
|
|
7365
|
+
display: flex;
|
|
7366
|
+
align-items: center;
|
|
7367
|
+
}
|
|
7368
|
+
.editor-tab-group sl-tab svg {
|
|
7369
|
+
width: 14px;
|
|
7370
|
+
height: 14px;
|
|
7371
|
+
flex-shrink: 0;
|
|
7372
|
+
}
|
|
7373
|
+
.editor-tab-group sl-tab-panel::part(base) {
|
|
7374
|
+
padding: 16px 4px 0;
|
|
7375
|
+
}
|
|
7376
|
+
|
|
7377
|
+
/*
|
|
7378
|
+
* Pipeline tab holds three sections (Stage configuration, Loop
|
|
7379
|
+
* limits, Circuit breaker) on one panel — the same shape as the
|
|
7380
|
+
* Project Settings → Pipeline tab. Each section is its own
|
|
7381
|
+
* `.settings-tab-content` flex column with gap:20px between fields
|
|
7382
|
+
* but no margin above the section heading, so without an explicit
|
|
7383
|
+
* separator they jam right up against each other. Give the three
|
|
7384
|
+
* direct children real vertical breathing room.
|
|
7385
|
+
*/
|
|
7386
|
+
.editor-pipeline-tab {
|
|
7387
|
+
display: flex;
|
|
7388
|
+
flex-direction: column;
|
|
7389
|
+
gap: 32px;
|
|
7390
|
+
}
|
|
7391
|
+
.editor-pipeline-tab > .settings-tab-content + .settings-tab-content {
|
|
7392
|
+
/* Visual separator on top of the gap so it reads as a fresh
|
|
7393
|
+
* section rather than a continuation of the previous one. */
|
|
7394
|
+
border-top: 1px solid var(--border-subtle, var(--border));
|
|
7395
|
+
padding-top: 24px;
|
|
7396
|
+
}
|
|
7397
|
+
|
|
7398
|
+
/*
|
|
7399
|
+
* Shared chrome for the template action dialogs (Create / Duplicate /
|
|
7400
|
+
* Rename / Import). Wraps the Settings-style form primitives so the
|
|
7401
|
+
* dialog body looks like a one-screen mini Settings tab.
|
|
7402
|
+
*/
|
|
7403
|
+
.template-action-dialog::part(panel) {
|
|
7404
|
+
min-width: min(520px, 100vw - 32px);
|
|
7405
|
+
}
|
|
7406
|
+
.template-action-dialog .dialog-lead {
|
|
7407
|
+
margin: 0 0 14px;
|
|
7408
|
+
color: var(--fg-muted);
|
|
7409
|
+
font-size: 13px;
|
|
7410
|
+
line-height: 1.5;
|
|
7411
|
+
}
|
|
7412
|
+
.template-action-dialog .dialog-lead code {
|
|
7413
|
+
background: var(--bg-secondary);
|
|
7414
|
+
padding: 1px 5px;
|
|
7415
|
+
border-radius: 4px;
|
|
7416
|
+
font-size: 12px;
|
|
7417
|
+
}
|
|
7418
|
+
.template-action-dialog .settings-field {
|
|
7419
|
+
margin-bottom: 14px;
|
|
7420
|
+
}
|
|
7421
|
+
.template-action-dialog .dialog-error {
|
|
7422
|
+
margin-top: 8px;
|
|
7423
|
+
}
|
|
7424
|
+
.template-action-dialog .dialog-bundle-list {
|
|
7425
|
+
margin: 4px 0 0;
|
|
7426
|
+
padding-left: 18px;
|
|
7427
|
+
font-size: 13px;
|
|
7428
|
+
color: var(--fg-muted);
|
|
7429
|
+
}
|
|
7430
|
+
.template-action-dialog .dialog-bundle-list code {
|
|
7431
|
+
font-family: var(--sl-font-mono);
|
|
7432
|
+
color: var(--fg);
|
|
7433
|
+
}
|
|
7434
|
+
|
|
7435
|
+
.editor-content {
|
|
7436
|
+
flex: 1;
|
|
7437
|
+
overflow-y: auto;
|
|
7438
|
+
padding: 16px;
|
|
7439
|
+
display: flex;
|
|
7440
|
+
flex-direction: column;
|
|
7441
|
+
gap: 24px;
|
|
7442
|
+
}
|
|
7443
|
+
|
|
7444
|
+
/* Editor Sections */
|
|
7445
|
+
|
|
7446
|
+
.editor-section {
|
|
7447
|
+
max-width: 900px;
|
|
7448
|
+
}
|
|
7449
|
+
|
|
7450
|
+
.editor-section--json {
|
|
7451
|
+
max-width: 1000px;
|
|
7452
|
+
}
|
|
7453
|
+
|
|
7454
|
+
.section-header {
|
|
7455
|
+
display: flex;
|
|
7456
|
+
align-items: center;
|
|
7457
|
+
justify-content: space-between;
|
|
7458
|
+
margin-bottom: 12px;
|
|
7459
|
+
}
|
|
7460
|
+
|
|
7461
|
+
.section-title {
|
|
7462
|
+
font-size: 15px;
|
|
7463
|
+
font-weight: 600;
|
|
7464
|
+
margin: 0;
|
|
7465
|
+
color: var(--fg);
|
|
7466
|
+
}
|
|
7467
|
+
|
|
7468
|
+
/* Stages List */
|
|
7469
|
+
|
|
7470
|
+
.stages-list {
|
|
7471
|
+
display: flex;
|
|
7472
|
+
flex-direction: column;
|
|
7473
|
+
gap: 8px;
|
|
7474
|
+
}
|
|
7475
|
+
|
|
7476
|
+
.stage-row {
|
|
7477
|
+
display: flex;
|
|
7478
|
+
align-items: center;
|
|
7479
|
+
gap: 12px;
|
|
7480
|
+
padding: 12px;
|
|
7481
|
+
background: var(--bg-secondary);
|
|
7482
|
+
border: 1px solid var(--border);
|
|
7483
|
+
border-radius: var(--radius);
|
|
7484
|
+
transition: var(--transition-fast);
|
|
7485
|
+
}
|
|
7486
|
+
|
|
7487
|
+
.stage-row--disabled {
|
|
7488
|
+
opacity: 0.5;
|
|
7489
|
+
}
|
|
7490
|
+
|
|
7491
|
+
.stage-row-info {
|
|
7492
|
+
display: flex;
|
|
7493
|
+
align-items: center;
|
|
7494
|
+
gap: 8px;
|
|
7495
|
+
flex: 1;
|
|
7496
|
+
}
|
|
7497
|
+
|
|
7498
|
+
.stage-name {
|
|
7499
|
+
font-weight: 500;
|
|
7500
|
+
font-family: var(--sl-font-mono);
|
|
7501
|
+
}
|
|
7502
|
+
|
|
7503
|
+
.stage-row.disabled .stage-name {
|
|
7504
|
+
text-decoration: line-through;
|
|
7505
|
+
}
|
|
7506
|
+
|
|
7507
|
+
.stage-row-agent {
|
|
7508
|
+
width: 200px;
|
|
7509
|
+
}
|
|
7510
|
+
|
|
7511
|
+
/* Agents Matrix */
|
|
7512
|
+
|
|
7513
|
+
.agents-matrix {
|
|
7514
|
+
display: flex;
|
|
7515
|
+
flex-direction: column;
|
|
7516
|
+
gap: 8px;
|
|
7517
|
+
}
|
|
7518
|
+
|
|
7519
|
+
.agent-row {
|
|
7520
|
+
display: flex;
|
|
7521
|
+
align-items: center;
|
|
7522
|
+
gap: 12px;
|
|
7523
|
+
padding: 10px 12px;
|
|
7524
|
+
background: var(--bg-secondary);
|
|
7525
|
+
border: 1px solid var(--border);
|
|
7526
|
+
border-radius: var(--radius);
|
|
7527
|
+
}
|
|
7528
|
+
|
|
7529
|
+
.agent-name {
|
|
7530
|
+
flex: 0 0 100px;
|
|
7531
|
+
font-weight: 500;
|
|
7532
|
+
font-family: var(--sl-font-mono);
|
|
7533
|
+
}
|
|
7534
|
+
|
|
7535
|
+
.agent-fields {
|
|
7536
|
+
display: grid;
|
|
7537
|
+
grid-template-columns: 1fr 1fr 1fr;
|
|
7538
|
+
gap: 8px;
|
|
7539
|
+
flex: 1;
|
|
7540
|
+
}
|
|
7541
|
+
|
|
7542
|
+
.agent-field {
|
|
7543
|
+
display: flex;
|
|
7544
|
+
flex-direction: column;
|
|
7545
|
+
gap: 4px;
|
|
7546
|
+
}
|
|
7547
|
+
|
|
7548
|
+
/* Loops Grid */
|
|
7549
|
+
|
|
7550
|
+
.loops-grid {
|
|
7551
|
+
display: grid;
|
|
7552
|
+
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
|
7553
|
+
gap: 12px;
|
|
7554
|
+
}
|
|
7555
|
+
|
|
7556
|
+
.loop-field {
|
|
7557
|
+
display: flex;
|
|
7558
|
+
flex-direction: column;
|
|
7559
|
+
gap: 4px;
|
|
7560
|
+
}
|
|
7561
|
+
|
|
7562
|
+
/* Circuit Breaker Grid */
|
|
7563
|
+
|
|
7564
|
+
.circuit-breaker-grid {
|
|
7565
|
+
display: grid;
|
|
7566
|
+
grid-template-columns: 1fr 1fr;
|
|
7567
|
+
gap: 16px;
|
|
7568
|
+
}
|
|
7569
|
+
|
|
7570
|
+
.cb-field {
|
|
7571
|
+
display: flex;
|
|
7572
|
+
flex-direction: column;
|
|
7573
|
+
gap: 8px;
|
|
7574
|
+
}
|
|
7575
|
+
|
|
7576
|
+
.cb-field-row {
|
|
7577
|
+
display: flex;
|
|
7578
|
+
align-items: center;
|
|
7579
|
+
gap: 8px;
|
|
7580
|
+
}
|
|
7581
|
+
|
|
7582
|
+
/* Governance */
|
|
7583
|
+
|
|
7584
|
+
.governance-content {
|
|
7585
|
+
display: flex;
|
|
7586
|
+
flex-direction: column;
|
|
7587
|
+
gap: 24px;
|
|
7588
|
+
}
|
|
7589
|
+
|
|
7590
|
+
/* JSON Editor */
|
|
7591
|
+
|
|
7592
|
+
.json-editor-wrapper {
|
|
7593
|
+
background: var(--bg-secondary);
|
|
7594
|
+
border: 1px solid var(--border);
|
|
7595
|
+
border-radius: var(--radius);
|
|
7596
|
+
padding: 4px;
|
|
7597
|
+
}
|
|
7598
|
+
|
|
7599
|
+
.json-editor {
|
|
7600
|
+
font-family: var(--sl-font-mono);
|
|
7601
|
+
font-size: 13px;
|
|
7602
|
+
line-height: 1.5;
|
|
7603
|
+
min-height: 300px;
|
|
7604
|
+
resize: vertical;
|
|
7605
|
+
}
|
|
7606
|
+
|
|
7607
|
+
.json-editor-hint {
|
|
7608
|
+
font-size: 12px;
|
|
7609
|
+
color: var(--fg-muted);
|
|
7610
|
+
margin-top: 8px;
|
|
7611
|
+
}
|
|
7612
|
+
|
|
7613
|
+
/* Diff view styles */
|
|
7614
|
+
.diff-hint {
|
|
7615
|
+
font-size: 13px;
|
|
7616
|
+
color: var(--fg-muted);
|
|
7617
|
+
margin-bottom: 16px;
|
|
7618
|
+
line-height: 1.5;
|
|
7619
|
+
}
|
|
7620
|
+
|
|
7621
|
+
.diff-reset-icon {
|
|
7622
|
+
display: inline-block;
|
|
7623
|
+
vertical-align: middle;
|
|
7624
|
+
margin: 0 4px;
|
|
7625
|
+
color: var(--accent);
|
|
7626
|
+
}
|
|
7627
|
+
|
|
7628
|
+
.diff-no-changes {
|
|
7629
|
+
text-align: center;
|
|
7630
|
+
padding: 48px 24px;
|
|
7631
|
+
color: var(--status-completed);
|
|
7632
|
+
}
|
|
7633
|
+
|
|
7634
|
+
.diff-no-changes svg {
|
|
7635
|
+
margin-bottom: 16px;
|
|
7636
|
+
color: var(--status-completed);
|
|
7637
|
+
}
|
|
7638
|
+
|
|
7639
|
+
.diff-no-changes h3 {
|
|
7640
|
+
margin: 0 0 8px 0;
|
|
7641
|
+
font-size: 16px;
|
|
7642
|
+
font-weight: 600;
|
|
7643
|
+
}
|
|
7644
|
+
|
|
7645
|
+
.diff-no-changes p {
|
|
7646
|
+
margin: 0;
|
|
7647
|
+
color: var(--fg-muted);
|
|
7648
|
+
}
|
|
7649
|
+
|
|
7650
|
+
.diff-empty,
|
|
7651
|
+
.diff-loading {
|
|
7652
|
+
padding: 24px;
|
|
7653
|
+
text-align: center;
|
|
7654
|
+
color: var(--fg-muted);
|
|
7655
|
+
}
|
|
7656
|
+
|
|
7657
|
+
.diff-loading {
|
|
7658
|
+
display: flex;
|
|
7659
|
+
align-items: center;
|
|
7660
|
+
justify-content: center;
|
|
7661
|
+
gap: 12px;
|
|
7662
|
+
}
|
|
7663
|
+
|
|
7664
|
+
.diff-table-container {
|
|
7665
|
+
overflow-x: auto;
|
|
7666
|
+
border: 1px solid var(--border);
|
|
7667
|
+
border-radius: var(--radius);
|
|
7668
|
+
}
|
|
7669
|
+
|
|
7670
|
+
.diff-table {
|
|
7671
|
+
width: 100%;
|
|
7672
|
+
border-collapse: collapse;
|
|
7673
|
+
font-size: 13px;
|
|
7674
|
+
}
|
|
7675
|
+
|
|
7676
|
+
.diff-table th {
|
|
7677
|
+
text-align: left;
|
|
7678
|
+
padding: 10px 12px;
|
|
7679
|
+
background: var(--bg-secondary);
|
|
7680
|
+
border-bottom: 2px solid var(--border);
|
|
7681
|
+
font-weight: 600;
|
|
7682
|
+
color: var(--fg);
|
|
7683
|
+
position: sticky;
|
|
7684
|
+
top: 0;
|
|
7685
|
+
}
|
|
7686
|
+
|
|
7687
|
+
.diff-table td {
|
|
7688
|
+
padding: 10px 12px;
|
|
7689
|
+
border-bottom: 1px solid var(--border-subtle);
|
|
7690
|
+
vertical-align: top;
|
|
7691
|
+
}
|
|
7692
|
+
|
|
7693
|
+
.diff-row--changed {
|
|
7694
|
+
background: rgba(251, 191, 36, 0.05);
|
|
7695
|
+
}
|
|
7696
|
+
|
|
7697
|
+
.diff-row--changed .diff-path {
|
|
7698
|
+
font-weight: 600;
|
|
7699
|
+
}
|
|
7700
|
+
|
|
7701
|
+
.diff-path code {
|
|
7702
|
+
display: block;
|
|
7703
|
+
font-family: ui-monospace, 'SF Mono', 'Menlo', monospace;
|
|
7704
|
+
font-size: 11px;
|
|
7705
|
+
color: var(--fg-muted);
|
|
7706
|
+
margin-bottom: 4px;
|
|
7707
|
+
}
|
|
7708
|
+
|
|
7709
|
+
.diff-label {
|
|
7710
|
+
display: block;
|
|
7711
|
+
font-size: 12px;
|
|
7712
|
+
color: var(--fg);
|
|
7713
|
+
}
|
|
7714
|
+
|
|
7715
|
+
.diff-value {
|
|
7716
|
+
font-family: ui-monospace, 'SF Mono', 'Menlo', monospace;
|
|
7717
|
+
font-size: 12px;
|
|
7718
|
+
max-width: 300px;
|
|
7719
|
+
overflow-x: auto;
|
|
7720
|
+
white-space: pre-wrap;
|
|
7721
|
+
word-break: break-all;
|
|
7722
|
+
}
|
|
7723
|
+
|
|
7724
|
+
.diff-value--builtin {
|
|
7725
|
+
color: var(--fg-muted);
|
|
7726
|
+
background: var(--bg-tertiary);
|
|
7727
|
+
padding: 4px 8px;
|
|
7728
|
+
border-radius: 4px;
|
|
7729
|
+
}
|
|
7730
|
+
|
|
7731
|
+
.diff-value--current {
|
|
7732
|
+
color: var(--fg);
|
|
7733
|
+
background: rgba(59, 130, 246, 0.1);
|
|
7734
|
+
padding: 4px 8px;
|
|
7735
|
+
border-radius: 4px;
|
|
7736
|
+
}
|
|
7737
|
+
|
|
7738
|
+
.diff-actions {
|
|
7739
|
+
white-space: nowrap;
|
|
7740
|
+
}
|
|
7741
|
+
|
|
7742
|
+
/* Common field styles */
|
|
7743
|
+
|
|
7744
|
+
.field-label {
|
|
7745
|
+
font-size: 12px;
|
|
7746
|
+
font-weight: 500;
|
|
7747
|
+
color: var(--fg-muted);
|
|
7748
|
+
}
|
|
7749
|
+
|
|
7750
|
+
.field-hint {
|
|
7751
|
+
font-size: 12px;
|
|
7752
|
+
color: var(--fg-muted);
|
|
7753
|
+
}
|
|
7754
|
+
|
|
7755
|
+
/* Footer */
|
|
7756
|
+
|
|
7757
|
+
.editor-footer {
|
|
7758
|
+
display: flex;
|
|
7759
|
+
align-items: center;
|
|
7760
|
+
justify-content: flex-end;
|
|
7761
|
+
gap: 8px;
|
|
7762
|
+
padding: 12px 16px;
|
|
7763
|
+
border-top: 1px solid var(--border);
|
|
7764
|
+
background: var(--bg);
|
|
7765
|
+
position: sticky;
|
|
7766
|
+
bottom: 0;
|
|
7767
|
+
z-index: 10;
|
|
7768
|
+
}
|
|
7769
|
+
|
|
7770
|
+
/* Save alert */
|
|
7771
|
+
|
|
7772
|
+
.editor-save-alert {
|
|
7773
|
+
margin-bottom: 16px;
|
|
7774
|
+
}
|
|
7775
|
+
|
|
7776
|
+
.editor-validation-alert {
|
|
7777
|
+
margin-bottom: 16px;
|
|
7778
|
+
}
|
|
7779
|
+
|
|
7780
|
+
.validation-list {
|
|
7781
|
+
margin: 8px 0 0 16px;
|
|
7782
|
+
padding-left: 20px;
|
|
7783
|
+
font-size: 13px;
|
|
7784
|
+
}
|
|
7785
|
+
|
|
7786
|
+
.validation-list li {
|
|
7787
|
+
margin-bottom: 4px;
|
|
7788
|
+
}
|
|
7789
|
+
|
|
7790
|
+
.validation-list code {
|
|
7791
|
+
font-family: var(--sl-font-mono);
|
|
7792
|
+
background: var(--bg-tertiary);
|
|
7793
|
+
padding: 2px 4px;
|
|
7794
|
+
border-radius: 3px;
|
|
7795
|
+
}
|
|
7796
|
+
|
|
7797
|
+
/* Loading state */
|
|
7798
|
+
|
|
7799
|
+
.editor-loading {
|
|
7800
|
+
display: flex;
|
|
7801
|
+
align-items: center;
|
|
7802
|
+
justify-content: center;
|
|
7803
|
+
padding: 40px;
|
|
7804
|
+
font-size: 14px;
|
|
7805
|
+
color: var(--fg-muted);
|
|
7806
|
+
gap: 8px;
|
|
7807
|
+
}
|