@youtyan/code-viewer 0.5.3 → 0.5.5

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/web/style.css CHANGED
@@ -4916,6 +4916,11 @@ body.query-history-panel-open #content {
4916
4916
  }
4917
4917
  .db-history-pane-content {
4918
4918
  flex: 1;
4919
+ /* min-height: 0 がないと、子の min-content size に引っ張られて親
4920
+ * (.db-history-pane の固定高さ) を超えて伸び、内側の overflow-y:auto
4921
+ * がスクロールバーを出さない (= 「クエリ履歴/ログ一覧がスクロールできない」
4922
+ * 既存バグの根本原因)。 */
4923
+ min-height: 0;
4919
4924
  display: flex;
4920
4925
  flex-direction: column;
4921
4926
  overflow: hidden;
@@ -5820,6 +5825,11 @@ body[data-sidebar-font-size="xlarge"] .db-container {
5820
5825
  overflow: hidden;
5821
5826
  border-top: 1px solid var(--border);
5822
5827
  background: var(--bg);
5828
+ /* flex container にしないと、子 (.db-history-pane-content) の flex:1 が
5829
+ * 効かず、子がコンテンツサイズに伸びて親の overflow:hidden が clip するだけ
5830
+ * の状態になる。結果、子内部の overflow-y:auto がスクロールバーを出さない。 */
5831
+ display: flex;
5832
+ flex-direction: column;
5823
5833
  }
5824
5834
  .db-history-pane[hidden] { display: none; }
5825
5835
  .db-tools-section {
@@ -7721,14 +7731,22 @@ body.db-resizing {
7721
7731
  /* --- Snapshot & Diff --- */
7722
7732
  .db-snapshot-view {
7723
7733
  padding: 12px;
7724
- overflow-y: auto;
7725
7734
  height: 100%;
7735
+ display: flex;
7736
+ flex-direction: column;
7737
+ min-height: 0;
7738
+ }
7739
+ /* hidden 属性は本来 display:none を当てるが、上の .db-snapshot-view の
7740
+ * display:flex に specificity で負けるので明示的に再宣言する。
7741
+ * (これを書かないと snapshot tab から離脱しても view が表示されたままになる) */
7742
+ .db-snapshot-view[hidden] {
7743
+ display: none;
7726
7744
  }
7727
7745
  .db-snapshot-guide {
7728
7746
  border: 1px solid var(--border);
7729
7747
  border-radius: 6px;
7730
7748
  padding: 10px 12px;
7731
- margin-bottom: 12px;
7749
+ margin-bottom: 8px;
7732
7750
  background: var(--bg-soft);
7733
7751
  }
7734
7752
  .db-snapshot-guide-title {
@@ -7763,7 +7781,12 @@ body.db-resizing {
7763
7781
  .db-snapshot-toolbar {
7764
7782
  display: flex;
7765
7783
  gap: 6px;
7766
- margin-bottom: 12px;
7784
+ margin-bottom: 8px;
7785
+ }
7786
+ /* tableSelector が開いている時、上の Take snapshot ボタンの「もう一回押せそう感」を消す。 */
7787
+ .db-snapshot-create-btn.is-active-dialog {
7788
+ opacity: 0.5;
7789
+ cursor: not-allowed;
7767
7790
  }
7768
7791
  .db-snapshot-create-btn,
7769
7792
  .db-snapshot-refresh-btn,
@@ -7781,38 +7804,446 @@ body.db-resizing {
7781
7804
  .db-snapshot-job-cancel-btn:hover {
7782
7805
  background: var(--bg-mute);
7783
7806
  }
7784
- .db-snapshot-table-selector {
7807
+ .db-snapshot-progress-area {
7808
+ margin-bottom: 12px;
7809
+ display: flex;
7810
+ flex-direction: column;
7811
+ gap: 4px;
7812
+ }
7813
+ .db-snapshot-progress-row {
7814
+ display: flex;
7815
+ align-items: center;
7816
+ gap: 8px;
7817
+ padding: 6px 10px;
7785
7818
  border: 1px solid var(--border);
7786
7819
  border-radius: 6px;
7787
- padding: 10px;
7788
- margin-bottom: 12px;
7789
7820
  background: var(--bg-soft);
7821
+ font-size: var(--db-font-base);
7822
+ }
7823
+ .db-snapshot-progress-row.running {
7824
+ border-color: color-mix(in srgb, var(--warning, #d29922) 40%, var(--border));
7825
+ background: color-mix(in srgb, var(--warning, #d29922) 8%, var(--bg-soft));
7826
+ }
7827
+ .db-snapshot-progress-row.error {
7828
+ border-color: color-mix(in srgb, var(--danger) 40%, var(--border));
7829
+ background: color-mix(in srgb, var(--danger) 8%, var(--bg-soft));
7830
+ }
7831
+ .db-snapshot-progress-row.aborted {
7832
+ color: var(--fg-muted);
7833
+ }
7834
+ .db-snapshot-progress-row.done {
7835
+ border-color: color-mix(in srgb, var(--success) 40%, var(--border));
7836
+ background: color-mix(in srgb, var(--success) 8%, var(--bg-soft));
7837
+ }
7838
+ .db-snapshot-progress-label {
7839
+ flex: 1;
7840
+ overflow: hidden;
7841
+ text-overflow: ellipsis;
7842
+ white-space: nowrap;
7843
+ }
7844
+ .db-snapshot-progress-row .db-snapshot-job-cancel-btn {
7845
+ padding: 2px 10px;
7846
+ font-size: calc(var(--db-font-base) - 1px);
7847
+ }
7848
+ .db-snapshot-error-message {
7849
+ color: var(--danger);
7850
+ font-size: calc(var(--db-font-base) - 1px);
7851
+ overflow: hidden;
7852
+ text-overflow: ellipsis;
7853
+ white-space: nowrap;
7854
+ max-width: 100%;
7855
+ }
7856
+ /* 左ペイン (snapshot 一覧 + sticky 比較プルダウン) / 右ペイン (diff) の 2 ペイン
7857
+ * 構成。snapshot が何百件あろうとプルダウンは左ペインの上に sticky で残り、
7858
+ * diff 結果は右ペインで独立してスクロールできる。 */
7859
+ .db-snapshot-main-area {
7860
+ flex: 1;
7861
+ min-height: 0;
7862
+ display: flex;
7863
+ flex-direction: column;
7864
+ overflow: hidden;
7865
+ }
7866
+ .db-snapshot-split {
7867
+ flex: 1;
7868
+ min-height: 0;
7869
+ display: flex;
7870
+ gap: 12px;
7871
+ align-items: stretch;
7872
+ }
7873
+ .db-snapshot-left-pane {
7874
+ flex: 0 0 380px;
7875
+ min-width: 280px;
7876
+ max-width: 50%;
7877
+ display: flex;
7878
+ flex-direction: column;
7879
+ overflow-y: auto;
7880
+ border: 1px solid var(--border);
7881
+ border-radius: 6px;
7882
+ background: var(--bg);
7883
+ }
7884
+ .db-snapshot-right-pane {
7885
+ flex: 1;
7886
+ min-width: 0;
7887
+ overflow-y: auto;
7888
+ /* 横スクロールはペインで受けない。各テーブルの .db-snapshot-diff-rows-viewport
7889
+ * (overflow-x:auto) が body 行だけを横スクロールする。ペインで両軸 scroll に
7890
+ * すると目次バー / テーブル名バー / 列ヘッダの sticky が横スクロールで全部
7891
+ * 流れて積層がぐちゃぐちゃになるので明示的に hidden にする。 */
7892
+ overflow-x: hidden;
7893
+ border: 1px solid var(--border);
7894
+ border-radius: 6px;
7895
+ background: var(--bg);
7896
+ /* sticky な toc を pane の左右いっぱいに広げたいので、ここでは
7897
+ * left/right padding を取らず、内部の .db-snapshot-diff-inline 側で
7898
+ * inset を持たせる。toc だけ pane の端まで広がる。 */
7899
+ padding: 0;
7900
+ /* sticky 帯 (目次バー + テーブル名 + 列ヘッダ) ぶん、scrollIntoView の
7901
+ * 停止位置を下げる。chip クリック時に section が sticky 裏に隠れて
7902
+ * 「中途半端な位置で止まる」のを防ぐ。 */
7903
+ scroll-padding-top: calc(
7904
+ var(--snap-diff-toc-h) + var(--snap-diff-table-header-h) +
7905
+ var(--snap-diff-col-header-h)
7906
+ );
7907
+ }
7908
+ .db-snapshot-diff-inline {
7909
+ /* sticky 3 段 (目次 / テーブル名 / 列ヘッダ) の高さを CSS 変数で持ち、
7910
+ * top 計算と scroll-padding-top を一箇所で管理する。 */
7911
+ --snap-diff-toc-h: 40px;
7912
+ --snap-diff-table-header-h: 34px;
7913
+ --snap-diff-col-header-h: 30px;
7914
+ padding: 0 12px 12px;
7915
+ }
7916
+ .db-snapshot-right-pane:empty::before {
7917
+ content: attr(data-empty);
7918
+ display: block;
7919
+ color: var(--fg-muted);
7920
+ font-size: var(--db-font-base);
7921
+ padding: 16px;
7922
+ text-align: center;
7923
+ }
7924
+ .db-snapshot-sticky-header {
7925
+ position: sticky;
7926
+ top: 0;
7927
+ z-index: 1;
7928
+ background: var(--bg);
7929
+ padding: 8px 10px;
7930
+ border-bottom: 1px solid var(--border);
7931
+ }
7932
+ .db-snapshot-list-section {
7933
+ padding: 8px 10px 12px;
7934
+ }
7935
+ .db-snapshot-item.is-before {
7936
+ border-left: 3px solid var(--accent);
7937
+ background: color-mix(in srgb, var(--accent) 6%, transparent);
7938
+ }
7939
+ .db-snapshot-item.is-after {
7940
+ border-left: 3px solid var(--success);
7941
+ background: color-mix(in srgb, var(--success) 6%, transparent);
7942
+ }
7943
+ .db-snapshot-compare-badge {
7944
+ display: inline-block;
7945
+ padding: 1px 6px;
7946
+ margin-left: 4px;
7947
+ border-radius: 10px;
7948
+ font-size: calc(var(--db-font-base) - 1px);
7949
+ background: var(--bg-soft);
7950
+ color: var(--fg-muted);
7951
+ border: 1px solid var(--border);
7952
+ }
7953
+ .db-snapshot-item.is-before .db-snapshot-compare-badge {
7954
+ background: color-mix(in srgb, var(--accent) 15%, var(--bg));
7955
+ color: var(--accent);
7956
+ border-color: color-mix(in srgb, var(--accent) 40%, var(--border));
7957
+ }
7958
+ .db-snapshot-item.is-after .db-snapshot-compare-badge {
7959
+ background: color-mix(in srgb, var(--success) 15%, var(--bg));
7960
+ color: var(--success);
7961
+ border-color: color-mix(in srgb, var(--success) 40%, var(--border));
7962
+ }
7963
+ .db-snapshot-diff-header {
7964
+ font-weight: 600;
7965
+ font-size: var(--db-font-base);
7966
+ padding-bottom: 8px;
7967
+ margin-bottom: 8px;
7968
+ border-bottom: 1px solid var(--border);
7969
+ color: var(--fg);
7970
+ }
7971
+ /* 差分テーブル目次バー: 右ペイン上部に sticky 配置、横スクロールで多くの
7972
+ * テーブルにも対応。chip クリックで該当 section へジャンプ。
7973
+ * .db-snapshot-diff-inline の左右 padding (12px) を打ち消して、pane の
7974
+ * 左右端まで隙間なく広げる (sticky 時に下のテーブル行が透けない)。 */
7975
+ .db-snapshot-diff-toc {
7976
+ position: sticky;
7977
+ top: 0;
7978
+ z-index: 30;
7979
+ display: flex;
7980
+ gap: 6px;
7981
+ padding: 8px 12px;
7982
+ margin: 0 -12px 8px;
7983
+ background: var(--bg);
7984
+ border-bottom: 1px solid var(--border);
7985
+ box-shadow: 0 2px 4px color-mix(in srgb, var(--fg) 5%, transparent);
7986
+ overflow-x: auto;
7987
+ overflow-y: hidden;
7988
+ white-space: nowrap;
7989
+ scroll-padding: 0 12px;
7990
+ height: var(--snap-diff-toc-h);
7991
+ box-sizing: border-box;
7992
+ }
7993
+ .db-snapshot-diff-toc-chip {
7994
+ flex: 0 0 auto;
7995
+ display: inline-flex;
7996
+ align-items: center;
7997
+ gap: 6px;
7998
+ padding: 4px 10px;
7999
+ border: 1px solid var(--border);
8000
+ border-radius: 12px;
8001
+ background: var(--bg-soft);
8002
+ color: var(--fg);
8003
+ cursor: pointer;
8004
+ font-size: calc(var(--db-font-base) - 1px);
8005
+ font-family: inherit;
8006
+ }
8007
+ .db-snapshot-diff-toc-chip:hover {
8008
+ background: var(--bg-mute);
8009
+ }
8010
+ .db-snapshot-diff-toc-chip.active {
8011
+ border-color: color-mix(in srgb, var(--accent) 60%, var(--border));
8012
+ background: color-mix(in srgb, var(--accent) 12%, var(--bg));
8013
+ color: var(--accent);
8014
+ font-weight: 500;
8015
+ }
8016
+ .db-snapshot-diff-toc-chip-name {
8017
+ overflow: hidden;
8018
+ text-overflow: ellipsis;
8019
+ max-width: 200px;
8020
+ }
8021
+ .db-snapshot-diff-toc-chip-stats {
8022
+ display: inline-flex;
8023
+ gap: 4px;
8024
+ font-size: calc(var(--db-font-base) - 2px);
8025
+ }
8026
+ .db-snapshot-diff-table-stats {
8027
+ display: inline-flex;
8028
+ gap: 6px;
8029
+ }
8030
+ /* git diff 風の色: +N 緑 / ~N 黄 / -N 赤。chip 内でも table header 内でも
8031
+ * 同じ色を共有する。font-weight 500 で数値を読みやすく強調。 */
8032
+ .db-snapshot-diff-stat {
8033
+ font-weight: 500;
8034
+ font-variant-numeric: tabular-nums;
8035
+ }
8036
+ .db-snapshot-diff-stat.add {
8037
+ color: var(--success);
8038
+ }
8039
+ .db-snapshot-diff-stat.upd {
8040
+ color: var(--warning, #d29922);
8041
+ }
8042
+ .db-snapshot-diff-stat.del {
8043
+ color: var(--danger);
8044
+ }
8045
+ /* 比較対象として片側 snapshot にしか含まれていないテーブル用のラベル。
8046
+ * 「-N削除」と誤認させない、ニュートラル色 + 「未取得」テキスト。 */
8047
+ .db-snapshot-diff-coverage-badge {
8048
+ display: inline-block;
8049
+ padding: 1px 8px;
8050
+ border-radius: 10px;
8051
+ font-size: calc(var(--db-font-base) - 2px);
8052
+ font-weight: 500;
8053
+ border: 1px dashed var(--border);
8054
+ background: var(--bg-soft);
8055
+ color: var(--fg-muted);
8056
+ white-space: nowrap;
8057
+ }
8058
+ .db-snapshot-diff-coverage-note {
8059
+ padding: 12px 14px;
8060
+ color: var(--fg-muted);
8061
+ font-size: calc(var(--db-font-base) - 1px);
8062
+ background: var(--bg-soft);
8063
+ border-top: 1px dashed var(--border);
8064
+ line-height: 1.5;
8065
+ }
8066
+ .db-snapshot-diff-toc-chip.coverage-incomplete {
8067
+ border-style: dashed;
8068
+ }
8069
+ /* 比較プルダウン (left pane 上部 sticky エリア) */
8070
+ .db-snapshot-diff-create {
8071
+ display: flex;
8072
+ flex-direction: column;
8073
+ gap: 6px;
8074
+ }
8075
+ .db-snapshot-diff-row {
8076
+ display: flex;
8077
+ align-items: stretch;
8078
+ gap: 6px;
8079
+ /* min-width: 0 がないと、select の content が parent の幅を超えて押し広げる
8080
+ * (flex item の default min-width:auto の落とし穴)。 */
8081
+ min-width: 0;
8082
+ }
8083
+ .db-snapshot-diff-row-label {
8084
+ /* select と同じ高さに揃え、垂直中央寄せ。padding を select に合わせる
8085
+ * ことで微妙な「badge だけ浮いてる」ズレを消す。 */
8086
+ display: inline-flex;
8087
+ align-items: center;
8088
+ justify-content: center;
8089
+ min-width: 56px;
8090
+ padding: 0 8px;
8091
+ border-radius: 10px;
8092
+ font-size: calc(var(--db-font-base) - 1px);
8093
+ border: 1px solid var(--border);
8094
+ line-height: 1;
8095
+ }
8096
+ .db-snapshot-diff-row.is-before .db-snapshot-diff-row-label {
8097
+ background: color-mix(in srgb, var(--accent) 15%, var(--bg));
8098
+ color: var(--accent);
8099
+ border-color: color-mix(in srgb, var(--accent) 40%, var(--border));
8100
+ }
8101
+ .db-snapshot-diff-row.is-after .db-snapshot-diff-row-label {
8102
+ background: color-mix(in srgb, var(--success) 15%, var(--bg));
8103
+ color: var(--success);
8104
+ border-color: color-mix(in srgb, var(--success) 40%, var(--border));
8105
+ }
8106
+ .db-snapshot-diff-row .db-snapshot-diff-select {
8107
+ flex: 1 1 0;
8108
+ min-width: 0;
8109
+ max-width: 100%;
8110
+ box-sizing: border-box;
8111
+ }
8112
+ /* sticky header 自体も box-sizing で枠を超えないよう保証する。 */
8113
+ .db-snapshot-sticky-header {
8114
+ box-sizing: border-box;
8115
+ width: 100%;
8116
+ }
8117
+ .db-snapshot-diff-create {
8118
+ width: 100%;
8119
+ min-width: 0;
8120
+ }
8121
+ /* sticky header 内のすべての子に box-sizing と min-width:0 を強制し、
8122
+ * select の min-content による親の押し広げ、ボタンの stretch overflow を防ぐ。 */
8123
+ .db-snapshot-sticky-header *,
8124
+ .db-snapshot-sticky-header *::before,
8125
+ .db-snapshot-sticky-header *::after {
8126
+ box-sizing: border-box;
8127
+ }
8128
+ .db-snapshot-sticky-header .db-snapshot-diff-create > * {
8129
+ max-width: 100%;
8130
+ min-width: 0;
8131
+ }
8132
+ /* ボタンは「全幅にする」のをやめ、左寄せの自然幅にする。stretch すると
8133
+ * 親が押し広がった時に物理的にはみ出すリスクがある。 */
8134
+ .db-snapshot-diff-btn {
8135
+ align-self: flex-start;
8136
+ }
8137
+ .db-snapshot-table-selector {
8138
+ /* 取得ダイアログとして「いまここを操作している」感を出すため、上の toolbar
8139
+ * から少し離して、accent 色のボーダーで強調する。 */
8140
+ border: 1px solid color-mix(in srgb, var(--accent) 40%, var(--border));
8141
+ border-radius: 6px;
8142
+ padding: 12px;
8143
+ margin-bottom: 12px;
8144
+ background: color-mix(in srgb, var(--accent) 3%, var(--bg-soft));
8145
+ box-shadow: 0 1px 4px color-mix(in srgb, var(--accent) 8%, transparent);
7790
8146
  }
7791
8147
  .db-snapshot-table-selector-header {
8148
+ display: flex;
8149
+ justify-content: space-between;
8150
+ align-items: baseline;
7792
8151
  font-weight: 600;
7793
8152
  margin-bottom: 8px;
7794
8153
  font-size: var(--db-font-base);
7795
8154
  }
8155
+ .db-snapshot-table-counter {
8156
+ font-weight: 400;
8157
+ font-size: calc(var(--db-font-base) - 1px);
8158
+ color: var(--fg-muted);
8159
+ }
8160
+ .db-snapshot-table-filter {
8161
+ margin-bottom: 8px;
8162
+ }
8163
+ .db-snapshot-table-filter-input {
8164
+ width: 100%;
8165
+ padding: 6px 10px;
8166
+ border: 1px solid var(--border);
8167
+ border-radius: 4px;
8168
+ font-size: var(--db-font-base);
8169
+ background: var(--bg);
8170
+ color: var(--fg);
8171
+ box-sizing: border-box;
8172
+ }
7796
8173
  .db-snapshot-table-checkboxes {
7797
8174
  display: flex;
7798
- flex-wrap: wrap;
7799
- gap: 4px 12px;
8175
+ flex-direction: column;
7800
8176
  margin-bottom: 8px;
7801
- max-height: 200px;
8177
+ max-height: 280px;
7802
8178
  overflow-y: auto;
8179
+ border: 1px solid var(--border);
8180
+ border-radius: 4px;
8181
+ background: var(--bg);
7803
8182
  }
7804
- .db-snapshot-table-label {
8183
+ .db-snapshot-table-row {
7805
8184
  display: flex;
7806
8185
  align-items: center;
7807
- gap: 4px;
8186
+ gap: 8px;
8187
+ padding: 6px 10px;
7808
8188
  font-size: var(--db-font-base);
7809
8189
  cursor: pointer;
8190
+ border-bottom: 1px solid var(--border);
8191
+ }
8192
+ .db-snapshot-table-row:last-child {
8193
+ border-bottom: none;
8194
+ }
8195
+ .db-snapshot-table-row:hover {
8196
+ background: var(--bg-soft);
8197
+ }
8198
+ .db-snapshot-table-row-name {
8199
+ /* 件数を name の直後にくっつけたいので flex:1 で伸ばさない。
8200
+ * 長いテーブル名は ellipsis で詰めるが、count はその直後に密着する。 */
8201
+ flex: 0 1 auto;
8202
+ min-width: 0;
8203
+ overflow: hidden;
8204
+ text-overflow: ellipsis;
8205
+ white-space: nowrap;
8206
+ }
8207
+ .db-snapshot-table-row-count {
8208
+ color: var(--fg-muted);
8209
+ font-size: calc(var(--db-font-base) - 1px);
8210
+ flex: 0 0 auto;
8211
+ margin-right: auto;
8212
+ }
8213
+ .db-snapshot-table-row-empty {
8214
+ padding: 16px;
8215
+ text-align: center;
8216
+ color: var(--fg-muted);
8217
+ font-size: calc(var(--db-font-base) - 1px);
8218
+ }
8219
+ .db-snapshot-note-row {
8220
+ margin-bottom: 8px;
8221
+ }
8222
+ .db-snapshot-note-row .db-snapshot-note-field {
8223
+ display: flex;
8224
+ align-items: center;
8225
+ gap: 8px;
8226
+ width: 100%;
8227
+ }
8228
+ .db-snapshot-note-row .db-snapshot-note-input {
8229
+ flex: 1;
8230
+ min-width: 0;
8231
+ }
8232
+ .db-snapshot-action-row {
8233
+ display: flex;
8234
+ gap: 6px;
8235
+ align-items: center;
8236
+ }
8237
+ .db-snapshot-confirm-btn:disabled {
8238
+ opacity: 0.5;
8239
+ cursor: not-allowed;
7810
8240
  }
7811
8241
  .db-snapshot-select-actions {
7812
8242
  display: flex;
7813
8243
  gap: 6px;
7814
8244
  align-items: center;
7815
8245
  flex-wrap: wrap;
8246
+ margin-bottom: 8px;
7816
8247
  }
7817
8248
  .db-snapshot-select-actions button {
7818
8249
  padding: 4px 10px;
@@ -7837,10 +8268,30 @@ body.db-resizing {
7837
8268
  flex: 1;
7838
8269
  min-width: 120px;
7839
8270
  }
7840
- .db-snapshot-confirm-btn {
7841
- background: var(--accent) !important;
7842
- color: #fff !important;
7843
- border-color: var(--accent) !important;
8271
+ /* primary action は「下線 + accent 文字」程度の subtle 強調にとどめ、
8272
+ * 既存の toolbar 系ボタン (Take snapshot / Refresh) と高さ・形を揃える。
8273
+ * 「独自の青塗りボタン」を避けて視覚的な統一感を出す。 */
8274
+ .db-snapshot-confirm-btn,
8275
+ .db-snapshot-cancel-btn,
8276
+ .db-snapshot-diff-btn {
8277
+ padding: 6px 14px;
8278
+ border: 1px solid var(--border);
8279
+ border-radius: 4px;
8280
+ background: var(--bg-soft);
8281
+ color: var(--fg);
8282
+ cursor: pointer;
8283
+ font-size: var(--db-font-base);
8284
+ }
8285
+ .db-snapshot-confirm-btn:not(:disabled),
8286
+ .db-snapshot-diff-btn:not(:disabled) {
8287
+ border-color: color-mix(in srgb, var(--accent) 40%, var(--border));
8288
+ color: var(--accent);
8289
+ font-weight: 500;
8290
+ }
8291
+ .db-snapshot-confirm-btn:hover:not(:disabled),
8292
+ .db-snapshot-cancel-btn:hover,
8293
+ .db-snapshot-diff-btn:hover:not(:disabled) {
8294
+ background: var(--bg-mute);
7844
8295
  }
7845
8296
  .db-snapshot-section-title {
7846
8297
  font-size: calc(var(--db-font-base) + 1px);
@@ -7940,18 +8391,8 @@ body.db-resizing {
7940
8391
  color: var(--fg);
7941
8392
  font-size: var(--db-font-base);
7942
8393
  }
7943
- .db-snapshot-diff-btn {
7944
- padding: 4px 14px;
7945
- border: 1px solid var(--accent);
7946
- border-radius: 4px;
7947
- background: var(--accent);
7948
- color: #fff;
7949
- cursor: pointer;
7950
- font-size: var(--db-font-base);
7951
- }
7952
- .db-snapshot-diff-btn:hover {
7953
- opacity: 0.9;
7954
- }
8394
+ /* diff-btn の旧独自青塗りは廃止。上の confirm/cancel と同じ neutral + accent
8395
+ * subtle スタイル (line 8119-) を共有する。 */
7955
8396
  .db-snapshot-diff-section {
7956
8397
  margin-top: 16px;
7957
8398
  }
@@ -8048,10 +8489,12 @@ body.db-resizing {
8048
8489
  font-size: var(--db-font-base);
8049
8490
  }
8050
8491
  .db-snapshot-diff-table {
8492
+ /* 各テーブルは「テーブル名 (sticky)」「列ヘッダ (sticky, scrollLeft 同期)」
8493
+ * 「rows-viewport (overflow-x:auto)」の 3 層構造。
8494
+ * overflow:hidden は付けない (内部 sticky を殺す)。 */
8051
8495
  border: 1px solid var(--border);
8052
8496
  border-radius: 6px;
8053
8497
  margin-bottom: 8px;
8054
- overflow: hidden;
8055
8498
  }
8056
8499
  .db-snapshot-diff-table-header {
8057
8500
  display: flex;
@@ -8061,88 +8504,58 @@ body.db-resizing {
8061
8504
  background: var(--bg-soft);
8062
8505
  font-size: var(--db-font-base);
8063
8506
  cursor: pointer;
8507
+ /* 目次バーのすぐ下に隙間ゼロで張り付く。 */
8508
+ position: sticky;
8509
+ top: var(--snap-diff-toc-h);
8510
+ z-index: 20;
8511
+ height: var(--snap-diff-table-header-h);
8512
+ box-sizing: border-box;
8513
+ border-top-left-radius: 6px;
8514
+ border-top-right-radius: 6px;
8064
8515
  }
8065
8516
  .db-snapshot-diff-table-header:hover {
8066
8517
  background: var(--bg-mute);
8067
8518
  }
8068
- .db-snapshot-diff-table-name {
8069
- font-weight: 600;
8070
- }
8071
- .db-snapshot-diff-table-stats {
8072
- color: var(--fg-muted);
8073
- }
8074
- .db-snapshot-diff-rows-container {
8075
- max-height: 400px;
8076
- overflow-y: auto;
8077
- }
8078
- .db-snapshot-diff-row {
8079
- padding: 6px 10px;
8519
+ .db-snapshot-diff-col-header-wrap {
8520
+ /* 列ヘッダ専用 wrap。rows-viewport (overflow-x:auto) の scrollLeft を JS で
8521
+ * 同期して、横スクロール時もデータ列と列名の位置が揃うようにする。
8522
+ * 自身は overflow:hidden で内部 table が右にはみ出ても scrollbar を出さない。
8523
+ * 上端は table-header (背景同色 var(--bg-soft)) と地続きに見せたいので
8524
+ * border-top は持たない。下端 1px だけが列ヘッダと body の境界を描く。 */
8525
+ position: sticky;
8526
+ top: calc(
8527
+ var(--snap-diff-toc-h) + var(--snap-diff-table-header-h) - 1px
8528
+ );
8529
+ z-index: 15;
8530
+ height: var(--snap-diff-col-header-h);
8531
+ box-sizing: border-box;
8532
+ overflow: hidden;
8533
+ background: var(--bg-soft);
8080
8534
  border-bottom: 1px solid var(--border);
8081
- font-size: var(--db-font-base);
8082
- }
8083
- .db-snapshot-diff-row:last-child {
8084
- border-bottom: none;
8085
8535
  }
8086
- .db-snapshot-diff-row.inserted {
8087
- background: var(--diff-addition-bg, rgba(46, 160, 67, 0.05));
8088
- }
8089
- .db-snapshot-diff-row.deleted {
8090
- background: var(--diff-deletion-bg, rgba(248, 81, 73, 0.05));
8091
- }
8092
- .db-snapshot-diff-row.updated {
8093
- background: var(--diff-change-bg, rgba(210, 153, 34, 0.05));
8536
+ .db-snapshot-diff-rows-viewport {
8537
+ /* body 行だけが横スクロール対象。縦は親 (.db-snapshot-right-pane) が受ける。 */
8538
+ overflow-x: auto;
8539
+ overflow-y: visible;
8094
8540
  }
8095
- .db-snapshot-diff-type {
8096
- display: inline-block;
8097
- padding: 1px 5px;
8098
- border-radius: 3px;
8099
- font-size: calc(var(--db-font-base) - 2px);
8541
+ .db-snapshot-diff-table-name {
8100
8542
  font-weight: 600;
8101
- margin-right: 6px;
8102
- font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
8103
- }
8104
- .db-snapshot-diff-type.inserted {
8105
- background: color-mix(in srgb, var(--success) 15%, var(--bg));
8106
- color: var(--success);
8107
- }
8108
- .db-snapshot-diff-type.deleted {
8109
- background: color-mix(in srgb, var(--danger) 15%, var(--bg));
8110
- color: var(--danger);
8111
8543
  }
8112
- .db-snapshot-diff-type.updated {
8113
- background: color-mix(in srgb, var(--warning, #d29922) 15%, var(--bg));
8114
- color: var(--warning, #d29922);
8115
- }
8116
- .db-snapshot-diff-key {
8117
- font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
8544
+ .db-snapshot-diff-table-stats {
8118
8545
  color: var(--fg-muted);
8119
- font-size: calc(var(--db-font-base) - 1px);
8120
- }
8121
- .db-snapshot-diff-changes,
8122
- .db-snapshot-diff-values {
8123
- margin-top: 4px;
8124
- padding-left: 16px;
8125
- }
8126
- .db-snapshot-diff-change-row,
8127
- .db-snapshot-diff-value-entry {
8128
- margin-bottom: 2px;
8129
- font-size: calc(var(--db-font-base) - 1px);
8130
- display: block;
8131
- }
8132
- .db-snapshot-diff-change-row .col-name,
8133
- .db-snapshot-diff-value-entry .col-name {
8134
- color: var(--accent);
8135
- font-weight: 500;
8136
- }
8137
- .db-snapshot-diff-change-row .old-val,
8138
- .db-snapshot-diff-value-entry .old-val {
8139
- color: var(--danger);
8140
- text-decoration: line-through;
8141
- }
8142
- .db-snapshot-diff-change-row .new-val,
8143
- .db-snapshot-diff-value-entry .new-val {
8144
- color: var(--success);
8145
8546
  }
8547
+ /* (旧) .db-snapshot-diff-rows-container は廃止。新構造では
8548
+ * .db-snapshot-diff-rows-viewport (overflow-x:auto) が body 行の横スクロールを
8549
+ * 担い、列ヘッダは .db-snapshot-diff-col-header-wrap に分離されて
8550
+ * scrollLeft 同期で追従する。 */
8551
+ /* (deleted) 旧 row-based diff レイアウトの dead CSS を削除した。
8552
+ * - .db-snapshot-diff-row / .db-snapshot-diff-type / .db-snapshot-diff-key
8553
+ * - .db-snapshot-diff-changes / .db-snapshot-diff-values
8554
+ * - .db-snapshot-diff-change-row / .db-snapshot-diff-value-entry
8555
+ * 現行は <table class="db-snap-diff-grid"> での grid 描画に移行済み。
8556
+ * 残しておくと .db-snapshot-diff-row が sticky 上部の before/after プルダウン行
8557
+ * (snapshot-view.ts の .db-snapshot-diff-row.is-before/.is-after) と
8558
+ * クラス名衝突して padding/border-bottom が漏れる。 */
8146
8559
  .db-snapshot-diff-more {
8147
8560
  padding: 6px 10px;
8148
8561
  color: var(--fg-muted);
@@ -8156,37 +8569,59 @@ body.db-resizing {
8156
8569
  font-size: var(--db-font-base);
8157
8570
  }
8158
8571
 
8159
- /* Diff grid table */
8572
+ /* Diff grid table
8573
+ * 構造: 各テーブルにつき 2 つの <table class="db-snap-diff-grid"> を作る。
8574
+ * - 列ヘッダ用 (thead のみ、.db-snapshot-diff-col-header-wrap 内)
8575
+ * - body 用 (tbody のみ、.db-snapshot-diff-rows-viewport 内)
8576
+ * 両 table に同じ <colgroup> を入れ、JS (ResizeObserver) で body 側の各 col
8577
+ * 実幅を測って header 側に同じ width を反映する。これで横スクロール時も
8578
+ * 列ヘッダとデータ列が完全に揃う。
8579
+ * border-collapse:separate にする理由: collapse だと隣接 border をセル側が
8580
+ * 描く仕様で、sticky 化やテーブル分割と相性が悪く subpixel 透けの原因になる。 */
8160
8581
  .db-snap-diff-grid {
8161
- width: 100%;
8162
- border-collapse: collapse;
8582
+ min-width: 100%;
8583
+ width: max-content;
8584
+ border-collapse: separate;
8585
+ border-spacing: 0;
8163
8586
  font-size: var(--db-font-base);
8164
8587
  table-layout: auto;
8165
8588
  }
8166
8589
  .db-snap-diff-grid th {
8167
- position: sticky;
8168
- top: 0;
8590
+ /* 列ヘッダの下端は col-header-wrap.border-bottom が描くので th 側では持たない。
8591
+ * 縦罫線は持たない (gutter と data 列の境界は type-cell.border-right が担う)。 */
8169
8592
  background: var(--bg-soft);
8170
- border: 1px solid var(--border);
8171
8593
  padding: 4px 8px;
8172
8594
  font-weight: 600;
8173
8595
  text-align: left;
8174
8596
  white-space: nowrap;
8175
- z-index: 1;
8176
8597
  }
8177
8598
  .db-snap-diff-grid td {
8178
- border: 1px solid var(--border);
8599
+ /* 縦罫線は持たない。横罫線のみで行を区切る (GitHub PR diff 同様)
8600
+ * gutter と data 列の境界は type-cell.border-right が担う。 */
8601
+ border-bottom: 1px solid var(--border);
8179
8602
  padding: 3px 8px;
8180
8603
  max-width: 300px;
8181
8604
  overflow: hidden;
8182
8605
  text-overflow: ellipsis;
8183
8606
  white-space: nowrap;
8184
8607
  }
8185
- .db-snap-diff-grid tr.snap-diff-add {
8186
- background: var(--diff-add-bg);
8608
+ .db-snap-diff-grid tbody tr:last-child td {
8609
+ border-bottom: 0;
8187
8610
  }
8188
- .db-snap-diff-grid tr.snap-diff-del {
8189
- background: var(--diff-del-bg);
8611
+ /* 1 レコード境界の視覚化:
8612
+ * - updated は trBefore(snap-diff-record-start) + trAfter(snap-diff-record-end) の 2 行
8613
+ * - inserted/deleted は 1 行に snap-diff-record-start snap-diff-record-end 両方
8614
+ * 行間の通常 border (1px var(--border)) よりはっきり濃く太くしないと、ペア内
8615
+ * の - と + の境目とレコード境界が区別できない。
8616
+ * - 横境界: 2px var(--fg-muted) (灰色の濃い線)
8617
+ * - gutter 縦印: inset 3px var(--fg-muted) で record の左に bracket 風
8618
+ * (実 border ではないので border-collapse / 列幅同期に影響しない) */
8619
+ .db-snap-diff-grid tr.snap-diff-record-end td {
8620
+ border-bottom: 2px solid var(--fg-muted);
8621
+ }
8622
+ .db-snap-diff-grid tr.snap-diff-record-start td:first-child,
8623
+ .db-snap-diff-grid tr.snap-diff-record-end td:first-child {
8624
+ box-shadow: inset 3px 0 0 var(--fg-muted);
8190
8625
  }
8191
8626
  .db-snap-diff-grid .snap-diff-type-cell {
8192
8627
  font-weight: 600;
@@ -8195,10 +8630,25 @@ body.db-resizing {
8195
8630
  background: var(--bg-soft);
8196
8631
  text-align: center;
8197
8632
  min-width: 50px;
8633
+ /* gutter と data 列の境界は唯一ここの border-right が描く。
8634
+ * 他のセルは縦罫線を持たない。 */
8635
+ border-right: 1px solid var(--border);
8636
+ }
8637
+ .db-snap-diff-grid tr.snap-diff-del .snap-diff-type-cell {
8638
+ color: var(--danger);
8639
+ }
8640
+ .db-snap-diff-grid tr.snap-diff-add .snap-diff-type-cell {
8641
+ color: var(--success);
8198
8642
  }
8199
8643
  .db-snap-diff-grid .snap-diff-changed-cell {
8200
8644
  font-weight: 600;
8201
8645
  }
8646
+ .db-snap-diff-grid tr.snap-diff-del .snap-diff-changed-cell {
8647
+ background: var(--diff-del-bg);
8648
+ }
8649
+ .db-snap-diff-grid tr.snap-diff-add .snap-diff-changed-cell {
8650
+ background: var(--diff-add-bg);
8651
+ }
8202
8652
 
8203
8653
  /* Inline dialog (replaces confirm/prompt) */
8204
8654
  .db-snapshot-inline-dialog {