@quilltap/theme-storybook 1.0.97 → 1.0.98

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/CHANGELOG.md CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  All notable changes to `@quilltap/theme-storybook` will be documented in this file.
4
4
 
5
+ ## [1.0.98] - 2026-11-02
6
+
7
+ ### Fixed
8
+ - Contrast and focus fixes mirrored from the app's WCAG pass: `.qt-storyteller-mode-option:hover`, `.qt-floating-dialog-close:hover` and `.qt-intervene-toggle:hover` use `--color-accent-foreground` on the accent fill; `.qt-chat-system-bar-time` drops its 0.75 opacity; `.qt-tab-close` rests at 0.8 opacity; `.qt-chat-system-bar`, `.qt-chat-announcement-chip` and `.qt-mention-chip` get a 2px ring on `:focus-visible`.
9
+
10
+ ### Added
11
+ - `.qt-tab-select` (the workspace tab's selectable button) and a focus ring on `.qt-tab-strip .qt-tab:has(.qt-tab-select:focus-visible)`.
12
+ - Families the mirror was missing: alerts (`qt-alert*`, with secondary text and links inheriting the alert colour and links underlined), the footer (`qt-footer*`, path without opacity), settings form shells (`qt-settings-shell*`, `-section-heading`, `-field-group`, `-toggle-row` with an accent-foreground hover) and the settings page's story-background treatment (inactive tab tint 90/10).
13
+
5
14
  ## [1.0.97] - 2026-11-02
6
15
 
7
16
  ### Fixed
package/dist/index.css CHANGED
@@ -1226,7 +1226,7 @@ body {
1226
1226
  }
1227
1227
  .qt-floating-dialog-close:hover {
1228
1228
  background: var(--color-accent);
1229
- color: var(--color-foreground);
1229
+ color: var(--color-accent-foreground);
1230
1230
  }
1231
1231
  .qt-floating-dialog-body {
1232
1232
  flex: 1 1 0%;
@@ -2309,6 +2309,10 @@ body {
2309
2309
  background: var(--qt-chat-system-bar-hover-bg);
2310
2310
  outline: none;
2311
2311
  }
2312
+ .qt-chat-system-bar:focus-visible {
2313
+ outline: 2px solid var(--color-ring);
2314
+ outline-offset: 2px;
2315
+ }
2312
2316
  .qt-chat-system-bar-sender {
2313
2317
  color: var(--qt-chat-system-bar-sender-fg);
2314
2318
  font-weight: 600;
@@ -2333,7 +2337,6 @@ body {
2333
2337
  }
2334
2338
  .qt-chat-system-bar-time {
2335
2339
  color: var(--qt-chat-system-bar-fg);
2336
- opacity: 0.75;
2337
2340
  white-space: nowrap;
2338
2341
  }
2339
2342
  .qt-chat-system-bar-chevron {
@@ -2377,6 +2380,10 @@ body {
2377
2380
  background: var(--qt-chat-system-bar-hover-bg);
2378
2381
  outline: none;
2379
2382
  }
2383
+ .qt-chat-announcement-chip:focus-visible {
2384
+ outline: 2px solid var(--color-ring);
2385
+ outline-offset: 2px;
2386
+ }
2380
2387
  .qt-chat-announcement-chip .qt-chat-system-bar-kind {
2381
2388
  flex: 0 1 auto;
2382
2389
  max-width: 22ch;
@@ -3651,6 +3658,10 @@ body {
3651
3658
  background: color-mix(in srgb, var(--color-primary) 26%, transparent);
3652
3659
  outline: none;
3653
3660
  }
3661
+ .qt-mention-chip:focus-visible {
3662
+ outline: 2px solid var(--color-ring);
3663
+ outline-offset: 2px;
3664
+ }
3654
3665
  .qt-typeahead-menu {
3655
3666
  position: absolute;
3656
3667
  z-index: 50;
@@ -5160,6 +5171,25 @@ body {
5160
5171
  border-color: var(--qt-tab-active-border);
5161
5172
  box-shadow: 0 3px 0 0 var(--qt-tab-active-border) inset;
5162
5173
  }
5174
+ .qt-tab-select {
5175
+ display: inline-flex;
5176
+ align-items: center;
5177
+ gap: inherit;
5178
+ min-width: 0;
5179
+ padding: 0;
5180
+ border: none;
5181
+ background: none;
5182
+ color: inherit;
5183
+ font: inherit;
5184
+ cursor: pointer;
5185
+ }
5186
+ .qt-tab-select:focus-visible {
5187
+ outline: none;
5188
+ }
5189
+ .qt-tab-strip .qt-tab:has(.qt-tab-select:focus-visible) {
5190
+ outline: 2px solid var(--color-ring);
5191
+ outline-offset: 2px;
5192
+ }
5163
5193
  .qt-tab-label {
5164
5194
  max-width: 14rem;
5165
5195
  overflow: hidden;
@@ -5174,7 +5204,7 @@ body {
5174
5204
  height: 1.5rem;
5175
5205
  margin: -0.175rem -0.25rem -0.175rem 0;
5176
5206
  border-radius: 0.25rem;
5177
- opacity: 0.55;
5207
+ opacity: 0.8;
5178
5208
  transition: opacity 0.15s ease, background 0.15s ease;
5179
5209
  }
5180
5210
  .qt-tab-close:hover {
@@ -5591,7 +5621,7 @@ li:is(.qt-chat-narration, .qt-chat-ooc, .qt-chat-inner-monologue) {
5591
5621
  }
5592
5622
  .qt-storyteller-mode-option:hover {
5593
5623
  background: var(--qt-storyteller-mode-hover-bg, var(--color-accent));
5594
- color: var(--qt-storyteller-mode-hover-fg, var(--color-foreground));
5624
+ color: var(--qt-storyteller-mode-hover-fg, var(--color-accent-foreground));
5595
5625
  }
5596
5626
  .qt-storyteller-mode-option-active,
5597
5627
  .qt-storyteller-mode-option-active:hover {
@@ -5792,6 +5822,7 @@ li:is(.qt-chat-narration, .qt-chat-ooc, .qt-chat-inner-monologue) {
5792
5822
  }
5793
5823
  .qt-intervene-toggle:hover {
5794
5824
  background-color: var(--qt-intervene-toggle-hover-bg, var(--color-accent));
5825
+ color: var(--qt-intervene-toggle-hover-fg, var(--color-accent-foreground));
5795
5826
  }
5796
5827
  .qt-intervene-toggle--off {
5797
5828
  color: var(--qt-intervene-toggle-off-fg, var(--color-muted-foreground));
@@ -5803,6 +5834,205 @@ li:is(.qt-chat-narration, .qt-chat-ooc, .qt-chat-inner-monologue) {
5803
5834
  currentColor calc(50% + 0.75px),
5804
5835
  transparent calc(50% + 0.75px));
5805
5836
  }
5837
+ .qt-alert,
5838
+ .qt-alert-success,
5839
+ .qt-alert-warning,
5840
+ .qt-alert-error,
5841
+ .qt-alert-info {
5842
+ border-radius: 0.5rem;
5843
+ border-width: 1px;
5844
+ border-style: solid;
5845
+ padding: 0.75rem 1rem;
5846
+ font-size: 0.875rem;
5847
+ line-height: 1.25rem;
5848
+ }
5849
+ .qt-alert-success {
5850
+ background-color: var(--qt-alert-success-bg);
5851
+ color: var(--qt-alert-success-fg);
5852
+ border-color: var(--qt-alert-success-border);
5853
+ }
5854
+ .qt-alert-warning {
5855
+ background-color: var(--qt-alert-warning-bg);
5856
+ color: var(--qt-alert-warning-fg);
5857
+ border-color: var(--qt-alert-warning-border);
5858
+ }
5859
+ .qt-alert-error {
5860
+ background-color: var(--qt-alert-error-bg);
5861
+ color: var(--qt-alert-error-fg);
5862
+ border-color: var(--qt-alert-error-border);
5863
+ }
5864
+ .qt-alert-info {
5865
+ background-color: var(--qt-alert-info-bg);
5866
+ color: var(--qt-alert-info-fg);
5867
+ border-color: var(--qt-alert-info-border);
5868
+ }
5869
+ :is(.qt-alert, .qt-alert-success, .qt-alert-warning, .qt-alert-error, .qt-alert-info) :is(.qt-text-small, .qt-text-muted, .qt-text-secondary, .qt-text-xs) {
5870
+ color: inherit;
5871
+ }
5872
+ :is(.qt-alert, .qt-alert-success, .qt-alert-warning, .qt-alert-error, .qt-alert-info) a {
5873
+ color: inherit;
5874
+ text-decoration: underline;
5875
+ text-underline-offset: 2px;
5876
+ }
5877
+ .qt-page-container[style*=--story-background-url] .qt-settings-header {
5878
+ border-radius: 0.5rem;
5879
+ padding: 1rem;
5880
+ margin-left: -1rem;
5881
+ margin-right: -1rem;
5882
+ background: color-mix(in srgb, var(--color-background) 80%, transparent);
5883
+ backdrop-filter: blur(8px);
5884
+ -webkit-backdrop-filter: blur(8px);
5885
+ }
5886
+ .qt-page-container[style*=--story-background-url] .qt-tab-group .qt-tab {
5887
+ background: color-mix(in srgb, var(--color-background) 90%, var(--color-muted-foreground) 10%);
5888
+ border-color: var(--color-border);
5889
+ }
5890
+ .qt-page-container[style*=--story-background-url] .qt-tab-group .qt-tab:hover:not(.qt-tab-active) {
5891
+ background: color-mix(in srgb, var(--color-background) 84%, var(--color-muted-foreground) 16%);
5892
+ }
5893
+ .qt-page-container[style*=--story-background-url] .qt-tab-group .qt-tab.qt-tab-active {
5894
+ background: color-mix(in srgb, var(--color-background) 88%, transparent);
5895
+ border-color: var(--color-border);
5896
+ }
5897
+ .qt-page-container[style*=--story-background-url] .qt-tab-group .qt-tab.qt-tab-active::after {
5898
+ background: color-mix(in srgb, var(--color-background) 88%, transparent);
5899
+ }
5900
+ .qt-page-container[style*=--story-background-url] .qt-tab-divider {
5901
+ display: none;
5902
+ }
5903
+ .qt-page-container[style*=--story-background-url] :has(> .qt-tab-group) {
5904
+ margin-bottom: 0 !important;
5905
+ }
5906
+ .qt-page-container[style*=--story-background-url] .qt-tab-group {
5907
+ position: relative;
5908
+ z-index: 1;
5909
+ margin-bottom: -1px;
5910
+ }
5911
+ .qt-page-container[style*=--story-background-url] .qt-settings-panel {
5912
+ border-bottom-left-radius: 0.5rem;
5913
+ border-bottom-right-radius: 0.5rem;
5914
+ padding: 1.5rem 1rem;
5915
+ margin-left: -1rem;
5916
+ margin-right: -1rem;
5917
+ background: color-mix(in srgb, var(--color-background) 88%, transparent);
5918
+ backdrop-filter: blur(12px);
5919
+ -webkit-backdrop-filter: blur(12px);
5920
+ border: 1px solid var(--color-border);
5921
+ border-top: 1px solid var(--color-border);
5922
+ min-height: 40vh;
5923
+ }
5924
+ .qt-footer {
5925
+ border-top-width: 1px;
5926
+ border-top-style: solid;
5927
+ padding: 1rem;
5928
+ background: var(--qt-app-header-bg);
5929
+ border-color: var(--qt-footer-border);
5930
+ backdrop-filter: var(--qt-app-header-blur);
5931
+ -webkit-backdrop-filter: var(--qt-app-header-blur);
5932
+ position: relative;
5933
+ z-index: 20;
5934
+ }
5935
+ .qt-footer-container {
5936
+ display: flex;
5937
+ flex-wrap: wrap;
5938
+ align-items: center;
5939
+ justify-content: center;
5940
+ gap: 1rem;
5941
+ font-size: 0.875rem;
5942
+ line-height: 1.25rem;
5943
+ color: var(--qt-footer-fg);
5944
+ }
5945
+ .qt-footer-link {
5946
+ display: flex;
5947
+ align-items: center;
5948
+ gap: 0.25rem;
5949
+ transition-property:
5950
+ color,
5951
+ background-color,
5952
+ border-color,
5953
+ text-decoration-color,
5954
+ fill,
5955
+ stroke;
5956
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
5957
+ transition-duration: 150ms;
5958
+ color: var(--qt-footer-fg);
5959
+ }
5960
+ .qt-footer-link:hover {
5961
+ color: var(--qt-footer-link-hover);
5962
+ }
5963
+ .qt-footer-path {
5964
+ font-family: monospace;
5965
+ font-size: 0.75rem;
5966
+ line-height: 1rem;
5967
+ display: none;
5968
+ overflow: hidden;
5969
+ text-overflow: ellipsis;
5970
+ white-space: nowrap;
5971
+ max-width: 24rem;
5972
+ color: var(--qt-footer-fg);
5973
+ cursor: pointer;
5974
+ background: none;
5975
+ border: none;
5976
+ padding: 0;
5977
+ transition: color 0.15s ease;
5978
+ }
5979
+ .qt-footer-path:hover {
5980
+ color: var(--qt-footer-link-hover);
5981
+ text-decoration: underline;
5982
+ }
5983
+ .qt-footer-separator {
5984
+ display: none;
5985
+ }
5986
+ @media (min-width: 40rem) {
5987
+ .qt-footer-path,
5988
+ .qt-footer-separator {
5989
+ display: inline;
5990
+ }
5991
+ }
5992
+ .qt-settings-shell {
5993
+ padding: 1rem;
5994
+ border-width: 1px;
5995
+ border-style: solid;
5996
+ border-radius: 0.25rem;
5997
+ border-color: var(--qt-card-border);
5998
+ background: color-mix(in srgb, var(--color-card) 96%, transparent);
5999
+ }
6000
+ .qt-settings-shell-tight {
6001
+ padding: 0.75rem;
6002
+ border-width: 1px;
6003
+ border-style: solid;
6004
+ border-radius: 0.25rem;
6005
+ border-color: var(--qt-card-border);
6006
+ background: color-mix(in srgb, var(--color-card) 96%, transparent);
6007
+ }
6008
+ .qt-settings-section-heading {
6009
+ font-size: 0.875rem;
6010
+ line-height: 1.25rem;
6011
+ font-weight: 500;
6012
+ color: var(--qt-text-primary-fg, var(--color-foreground));
6013
+ }
6014
+ .qt-settings-field-group > :not(:last-child) {
6015
+ margin-bottom: 0.5rem;
6016
+ }
6017
+ .qt-settings-toggle-row {
6018
+ display: flex;
6019
+ align-items: flex-start;
6020
+ gap: 0.75rem;
6021
+ padding: 1rem;
6022
+ border-width: 1px;
6023
+ border-style: solid;
6024
+ border-radius: 0.25rem;
6025
+ cursor: pointer;
6026
+ border-color: var(--qt-card-border);
6027
+ transition: background-color 150ms ease;
6028
+ }
6029
+ .qt-settings-toggle-row:hover {
6030
+ background: var(--qt-card-hover-bg, var(--color-accent));
6031
+ color: var(--qt-card-hover-fg, var(--color-accent-foreground));
6032
+ }
6033
+ .qt-settings-toggle-row:hover :where(*) {
6034
+ color: var(--qt-card-hover-fg, var(--color-accent-foreground));
6035
+ }
5806
6036
  @media (prefers-reduced-motion: reduce) {
5807
6037
  *,
5808
6038
  *::before,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quilltap/theme-storybook",
3
- "version": "1.0.97",
3
+ "version": "1.0.98",
4
4
  "description": "Storybook preset and stories for developing Quilltap theme plugins",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1401,7 +1401,7 @@
1401
1401
 
1402
1402
  .qt-floating-dialog-close:hover {
1403
1403
  background: var(--color-accent);
1404
- color: var(--color-foreground);
1404
+ color: var(--color-accent-foreground);
1405
1405
  }
1406
1406
 
1407
1407
  .qt-floating-dialog-body {
@@ -2642,6 +2642,13 @@
2642
2642
  outline: none;
2643
2643
  }
2644
2644
 
2645
+ /* The tint alone was too faint to find; keyboard focus also gets the ring
2646
+ every other control wears (WCAG 2.4.7). */
2647
+ .qt-chat-system-bar:focus-visible {
2648
+ outline: 2px solid var(--color-ring);
2649
+ outline-offset: 2px;
2650
+ }
2651
+
2645
2652
  .qt-chat-system-bar-sender {
2646
2653
  color: var(--qt-chat-system-bar-sender-fg);
2647
2654
  font-weight: 600;
@@ -2672,9 +2679,9 @@
2672
2679
  white-space: nowrap;
2673
2680
  }
2674
2681
 
2682
+ /* Full strength: at 0.75 opacity the timestamp fell to ~3:1 on the bar. */
2675
2683
  .qt-chat-system-bar-time {
2676
2684
  color: var(--qt-chat-system-bar-fg);
2677
- opacity: 0.75;
2678
2685
  white-space: nowrap;
2679
2686
  }
2680
2687
 
@@ -2738,6 +2745,13 @@
2738
2745
  outline: none;
2739
2746
  }
2740
2747
 
2748
+ /* The tint alone was too faint to find; keyboard focus also gets the ring
2749
+ every other control wears (WCAG 2.4.7). */
2750
+ .qt-chat-announcement-chip:focus-visible {
2751
+ outline: 2px solid var(--color-ring);
2752
+ outline-offset: 2px;
2753
+ }
2754
+
2741
2755
  /* Inside a chip the kind must not greedily fill the row; cap it so a long kind
2742
2756
  doesn't dominate a packed row. */
2743
2757
  .qt-chat-announcement-chip .qt-chat-system-bar-kind {
@@ -4370,6 +4384,13 @@
4370
4384
  outline: none;
4371
4385
  }
4372
4386
 
4387
+ /* The tint alone was too faint to find; keyboard focus also gets the ring
4388
+ every other control wears (WCAG 2.4.7). */
4389
+ .qt-mention-chip:focus-visible {
4390
+ outline: 2px solid var(--color-ring);
4391
+ outline-offset: 2px;
4392
+ }
4393
+
4373
4394
  /* ==========================================================================
4374
4395
  TYPEAHEAD MENU
4375
4396
  ==========================================================================
@@ -6390,6 +6411,31 @@
6390
6411
  box-shadow: 0 3px 0 0 var(--qt-tab-active-border) inset;
6391
6412
  }
6392
6413
 
6414
+ /* The tab's selectable part: a bare button carrying the icon and label, so
6415
+ the tab is keyboard-operable without nesting the close button inside it.
6416
+ Its focus ring is drawn on the whole tab, which is what the eye reads. */
6417
+ .qt-tab-select {
6418
+ display: inline-flex;
6419
+ align-items: center;
6420
+ gap: inherit;
6421
+ min-width: 0;
6422
+ padding: 0;
6423
+ border: none;
6424
+ background: none;
6425
+ color: inherit;
6426
+ font: inherit;
6427
+ cursor: pointer;
6428
+ }
6429
+
6430
+ .qt-tab-select:focus-visible {
6431
+ outline: none;
6432
+ }
6433
+
6434
+ .qt-tab-strip .qt-tab:has(.qt-tab-select:focus-visible) {
6435
+ outline: 2px solid var(--color-ring);
6436
+ outline-offset: 2px;
6437
+ }
6438
+
6393
6439
  .qt-tab-label {
6394
6440
  max-width: 14rem;
6395
6441
  overflow: hidden;
@@ -6406,7 +6452,8 @@
6406
6452
  height: 1.5rem;
6407
6453
  margin: -0.175rem -0.25rem -0.175rem 0;
6408
6454
  border-radius: 0.25rem;
6409
- opacity: 0.55;
6455
+ /* 0.8, not 0.55: the dimmer cross fell under the 3:1 a control's icon needs. */
6456
+ opacity: 0.8;
6410
6457
  transition: opacity 0.15s ease, background 0.15s ease;
6411
6458
  }
6412
6459
 
@@ -6831,7 +6878,7 @@ li:is(.qt-chat-narration, .qt-chat-ooc, .qt-chat-inner-monologue) {
6831
6878
 
6832
6879
  .qt-storyteller-mode-option:hover {
6833
6880
  background: var(--qt-storyteller-mode-hover-bg, var(--color-accent));
6834
- color: var(--qt-storyteller-mode-hover-fg, var(--color-foreground));
6881
+ color: var(--qt-storyteller-mode-hover-fg, var(--color-accent-foreground));
6835
6882
  }
6836
6883
 
6837
6884
  .qt-storyteller-mode-option-active,
@@ -7092,6 +7139,7 @@ li:is(.qt-chat-narration, .qt-chat-ooc, .qt-chat-inner-monologue) {
7092
7139
 
7093
7140
  .qt-intervene-toggle:hover {
7094
7141
  background-color: var(--qt-intervene-toggle-hover-bg, var(--color-accent));
7142
+ color: var(--qt-intervene-toggle-hover-fg, var(--color-accent-foreground));
7095
7143
  }
7096
7144
 
7097
7145
  /* A field the author has hidden from the dialog. */
@@ -7109,6 +7157,271 @@ li:is(.qt-chat-narration, .qt-chat-ooc, .qt-chat-inner-monologue) {
7109
7157
  );
7110
7158
  }
7111
7159
 
7160
+ /* ============================================================================
7161
+ ALERTS
7162
+ ============================================================================ */
7163
+
7164
+ .qt-alert,
7165
+ .qt-alert-success,
7166
+ .qt-alert-warning,
7167
+ .qt-alert-error,
7168
+ .qt-alert-info {
7169
+ border-radius: 0.5rem;
7170
+ border-width: 1px;
7171
+ border-style: solid;
7172
+ padding: 0.75rem 1rem;
7173
+ font-size: 0.875rem;
7174
+ line-height: 1.25rem;
7175
+ }
7176
+
7177
+ .qt-alert-success {
7178
+ background-color: var(--qt-alert-success-bg);
7179
+ color: var(--qt-alert-success-fg);
7180
+ border-color: var(--qt-alert-success-border);
7181
+ }
7182
+
7183
+ .qt-alert-warning {
7184
+ background-color: var(--qt-alert-warning-bg);
7185
+ color: var(--qt-alert-warning-fg);
7186
+ border-color: var(--qt-alert-warning-border);
7187
+ }
7188
+
7189
+ .qt-alert-error {
7190
+ background-color: var(--qt-alert-error-bg);
7191
+ color: var(--qt-alert-error-fg);
7192
+ border-color: var(--qt-alert-error-border);
7193
+ }
7194
+
7195
+ .qt-alert-info {
7196
+ background-color: var(--qt-alert-info-bg);
7197
+ color: var(--qt-alert-info-fg);
7198
+ border-color: var(--qt-alert-info-border);
7199
+ }
7200
+
7201
+ /* Secondary-text helpers inside an alert take the alert's own foreground.
7202
+ qt-text-small and its kin paint the muted grey, which on an alert's tint
7203
+ fell to ~3.6:1 (Art Deco dark) and ~4.1:1 (default dark); the alert's
7204
+ foreground is the colour chosen to sit on that tint. Specificity is two
7205
+ classes — enough to outrank the helper, no more. */
7206
+ :is(.qt-alert, .qt-alert-success, .qt-alert-warning, .qt-alert-error, .qt-alert-info)
7207
+ :is(.qt-text-small, .qt-text-muted, .qt-text-secondary, .qt-text-xs) {
7208
+ color: inherit;
7209
+ }
7210
+
7211
+ /* A link inside an alert's running text takes the alert's colour (qt-link's
7212
+ muted grey fell to ~3.6:1 on the tint) and is underlined, so it is not
7213
+ told from the words around it by colour alone (WCAG 1.4.1). */
7214
+ :is(.qt-alert, .qt-alert-success, .qt-alert-warning, .qt-alert-error, .qt-alert-info) a {
7215
+ color: inherit;
7216
+ text-decoration: underline;
7217
+ text-underline-offset: 2px;
7218
+ }
7219
+
7220
+ /* ============================================================================
7221
+ SETTINGS PAGE - Background image readability
7222
+ When a subsystem background image is shown on the settings page,
7223
+ tabs and header text need opaque/contrasted treatments to remain legible.
7224
+ ============================================================================ */
7225
+
7226
+ /* Frosted header banner behind title and subtitle */
7227
+ .qt-page-container[style*="--story-background-url"] .qt-settings-header {
7228
+ border-radius: 0.5rem;
7229
+ padding: 1rem;
7230
+ margin-left: -1rem;
7231
+ margin-right: -1rem;
7232
+ background: color-mix(in srgb, var(--color-background) 80%, transparent);
7233
+ backdrop-filter: blur(8px);
7234
+ -webkit-backdrop-filter: blur(8px);
7235
+ }
7236
+
7237
+ /* Opaque inactive tab backgrounds. 90/10, not 85/15: the stronger tint left
7238
+ the muted tab label at 4.3:1 on the default and Rains light palettes. */
7239
+ .qt-page-container[style*="--story-background-url"] .qt-tab-group .qt-tab {
7240
+ background: color-mix(in srgb, var(--color-background) 90%, var(--color-muted-foreground) 10%);
7241
+ border-color: var(--color-border);
7242
+ }
7243
+
7244
+ .qt-page-container[style*="--story-background-url"] .qt-tab-group .qt-tab:hover:not(.qt-tab-active) {
7245
+ background: color-mix(in srgb, var(--color-background) 84%, var(--color-muted-foreground) 16%);
7246
+ }
7247
+
7248
+ /* Active tab matches the panel background so it merges into it */
7249
+ .qt-page-container[style*="--story-background-url"] .qt-tab-group .qt-tab.qt-tab-active {
7250
+ background: color-mix(in srgb, var(--color-background) 88%, transparent);
7251
+ border-color: var(--color-border);
7252
+ }
7253
+
7254
+ .qt-page-container[style*="--story-background-url"] .qt-tab-group .qt-tab.qt-tab-active::after {
7255
+ background: color-mix(in srgb, var(--color-background) 88%, transparent);
7256
+ }
7257
+
7258
+ /* Remove gap between tabs and panel so they connect as a folder */
7259
+ .qt-page-container[style*="--story-background-url"] .qt-tab-divider {
7260
+ display: none;
7261
+ }
7262
+
7263
+ /* Collapse the margin between tab nav wrapper and content panel */
7264
+ .qt-page-container[style*="--story-background-url"] :has(> .qt-tab-group) {
7265
+ margin-bottom: 0 !important;
7266
+ }
7267
+
7268
+ .qt-page-container[style*="--story-background-url"] .qt-tab-group {
7269
+ /* Nudge tabs down onto the panel border so the active tab overlaps it */
7270
+ position: relative;
7271
+ z-index: 1;
7272
+ margin-bottom: -1px;
7273
+ }
7274
+
7275
+ /* Settings content panel - the "folder" body below the tabs. */
7276
+ .qt-page-container[style*="--story-background-url"] .qt-settings-panel {
7277
+ border-bottom-left-radius: 0.5rem;
7278
+ border-bottom-right-radius: 0.5rem;
7279
+ padding: 1.5rem 1rem;
7280
+ margin-left: -1rem;
7281
+ margin-right: -1rem;
7282
+ background: color-mix(in srgb, var(--color-background) 88%, transparent);
7283
+ backdrop-filter: blur(12px);
7284
+ -webkit-backdrop-filter: blur(12px);
7285
+ border: 1px solid var(--color-border);
7286
+ border-top: 1px solid var(--color-border);
7287
+ min-height: 40vh;
7288
+ }
7289
+
7290
+ /* ============================================================================
7291
+ FOOTER
7292
+ ============================================================================ */
7293
+
7294
+ .qt-footer {
7295
+ border-top-width: 1px;
7296
+ border-top-style: solid;
7297
+ padding: 1rem;
7298
+ background: var(--qt-app-header-bg);
7299
+ border-color: var(--qt-footer-border);
7300
+ backdrop-filter: var(--qt-app-header-blur);
7301
+ -webkit-backdrop-filter: var(--qt-app-header-blur);
7302
+ position: relative;
7303
+ z-index: 20;
7304
+ }
7305
+
7306
+ .qt-footer-container {
7307
+ display: flex;
7308
+ flex-wrap: wrap;
7309
+ align-items: center;
7310
+ justify-content: center;
7311
+ gap: 1rem;
7312
+ font-size: 0.875rem;
7313
+ line-height: 1.25rem;
7314
+ color: var(--qt-footer-fg);
7315
+ }
7316
+
7317
+ .qt-footer-link {
7318
+ display: flex;
7319
+ align-items: center;
7320
+ gap: 0.25rem;
7321
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
7322
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
7323
+ transition-duration: 150ms;
7324
+ color: var(--qt-footer-fg);
7325
+ }
7326
+
7327
+ .qt-footer-link:hover {
7328
+ color: var(--qt-footer-link-hover);
7329
+ }
7330
+
7331
+ .qt-footer-path {
7332
+ font-family: monospace;
7333
+ font-size: 0.75rem;
7334
+ line-height: 1rem;
7335
+ display: none;
7336
+ overflow: hidden;
7337
+ text-overflow: ellipsis;
7338
+ white-space: nowrap;
7339
+ max-width: 24rem;
7340
+ color: var(--qt-footer-fg);
7341
+ cursor: pointer;
7342
+ background: none;
7343
+ border: none;
7344
+ padding: 0;
7345
+ transition: color 0.15s ease;
7346
+ }
7347
+
7348
+ /* Full strength at rest: the old 0.7 opacity left the path at ~2.9:1 on the
7349
+ footer. Hover marks itself by colour and underline instead. */
7350
+ .qt-footer-path:hover {
7351
+ color: var(--qt-footer-link-hover);
7352
+ text-decoration: underline;
7353
+ }
7354
+
7355
+ .qt-footer-separator {
7356
+ display: none;
7357
+ }
7358
+
7359
+ @media (min-width: 40rem) {
7360
+ .qt-footer-path,
7361
+ .qt-footer-separator {
7362
+ display: inline;
7363
+ }
7364
+ }
7365
+
7366
+ /* ============================================================================
7367
+ SETTINGS FORM SHELLS
7368
+ Shared semantic wrappers for settings cards and toggle rows.
7369
+ ============================================================================ */
7370
+
7371
+ .qt-settings-shell {
7372
+ padding: 1rem;
7373
+ border-width: 1px;
7374
+ border-style: solid;
7375
+ border-radius: 0.25rem;
7376
+ border-color: var(--qt-card-border);
7377
+ background: color-mix(in srgb, var(--color-card) 96%, transparent);
7378
+ }
7379
+
7380
+ .qt-settings-shell-tight {
7381
+ padding: 0.75rem;
7382
+ border-width: 1px;
7383
+ border-style: solid;
7384
+ border-radius: 0.25rem;
7385
+ border-color: var(--qt-card-border);
7386
+ background: color-mix(in srgb, var(--color-card) 96%, transparent);
7387
+ }
7388
+
7389
+ .qt-settings-section-heading {
7390
+ font-size: 0.875rem;
7391
+ line-height: 1.25rem;
7392
+ font-weight: 500;
7393
+ color: var(--qt-text-primary-fg, var(--color-foreground));
7394
+ }
7395
+
7396
+ .qt-settings-field-group > :not(:last-child) {
7397
+ margin-bottom: 0.5rem;
7398
+ }
7399
+
7400
+ .qt-settings-toggle-row {
7401
+ display: flex;
7402
+ align-items: flex-start;
7403
+ gap: 0.75rem;
7404
+ padding: 1rem;
7405
+ border-width: 1px;
7406
+ border-style: solid;
7407
+ border-radius: 0.25rem;
7408
+ cursor: pointer;
7409
+ border-color: var(--qt-card-border);
7410
+ transition: background-color 150ms ease;
7411
+ }
7412
+
7413
+ /* The accent fill carries its own foreground: on themes with a bold accent
7414
+ (Art Deco and Great Estate dark, Madman's Box) the row's ordinary text
7415
+ fell to ~1.4:1 on hover. */
7416
+ .qt-settings-toggle-row:hover {
7417
+ background: var(--qt-card-hover-bg, var(--color-accent));
7418
+ color: var(--qt-card-hover-fg, var(--color-accent-foreground));
7419
+ }
7420
+
7421
+ .qt-settings-toggle-row:hover :where(*) {
7422
+ color: var(--qt-card-hover-fg, var(--color-accent-foreground));
7423
+ }
7424
+
7112
7425
  /* ============================================================================
7113
7426
  REDUCED MOTION — every theme honours the OS setting
7114
7427
  ============================================================================ */