@quillmark/svelte 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/NOTICE +6 -6
  2. package/README.md +3 -3
  3. package/THEMING.md +12 -8
  4. package/dist/core/address.d.ts +7 -7
  5. package/dist/core/address.js +6 -6
  6. package/dist/core/bloom.d.ts +3 -32
  7. package/dist/core/bloom.js +19 -51
  8. package/dist/core/codec/anchor.d.ts +1 -1
  9. package/dist/core/codec/anchor.js +1 -1
  10. package/dist/core/codec/atoms.d.ts +10 -0
  11. package/dist/core/codec/atoms.js +78 -0
  12. package/dist/core/codec/clipboard.d.ts +59 -0
  13. package/dist/core/codec/clipboard.js +202 -0
  14. package/dist/core/codec/code.d.ts +1 -1
  15. package/dist/core/codec/code.js +4 -4
  16. package/dist/core/codec/decode.d.ts +1 -1
  17. package/dist/core/codec/decode.js +8 -8
  18. package/dist/core/codec/encode.d.ts +4 -4
  19. package/dist/core/codec/encode.js +10 -10
  20. package/dist/core/codec/field.d.ts +21 -26
  21. package/dist/core/codec/field.js +33 -32
  22. package/dist/core/codec/index.js +5 -8
  23. package/dist/core/codec/inputrules.js +56 -18
  24. package/dist/core/codec/islands.d.ts +11 -7
  25. package/dist/core/codec/islands.js +16 -10
  26. package/dist/core/codec/keymap.d.ts +5 -6
  27. package/dist/core/codec/keymap.js +8 -7
  28. package/dist/core/codec/lists.d.ts +3 -3
  29. package/dist/core/codec/lists.js +32 -13
  30. package/dist/core/codec/marks.d.ts +1 -1
  31. package/dist/core/codec/marks.js +1 -1
  32. package/dist/core/codec/positions.js +1 -1
  33. package/dist/core/codec/prose.css +235 -221
  34. package/dist/core/codec/schema.js +4 -4
  35. package/dist/core/codec/slash.d.ts +39 -41
  36. package/dist/core/codec/slash.js +0 -0
  37. package/dist/core/codec/table-view.d.ts +12 -16
  38. package/dist/core/codec/table-view.js +488 -292
  39. package/dist/core/codec/table.d.ts +42 -15
  40. package/dist/core/codec/table.js +70 -26
  41. package/dist/core/errors.d.ts +5 -5
  42. package/dist/core/index.js +2 -2
  43. package/dist/core/lifecycle.js +1 -1
  44. package/dist/core/rebind.svelte.d.ts +2 -2
  45. package/dist/core/rebind.svelte.js +4 -4
  46. package/dist/core/teardown.d.ts +1 -1
  47. package/dist/core/teardown.js +1 -1
  48. package/dist/core/theme.css +170 -64
  49. package/dist/preset/index.css +1 -1
  50. package/dist/preset/recipes.css +31 -29
  51. package/dist/preset/scale.css +37 -26
  52. package/dist/preview/Preview.svelte +17 -27
  53. package/dist/preview/Preview.svelte.d.ts +4 -5
  54. package/dist/preview/bridge.js +6 -6
  55. package/dist/preview/controller.d.ts +8 -10
  56. package/dist/preview/controller.js +19 -44
  57. package/dist/preview/geometry.d.ts +8 -10
  58. package/dist/preview/geometry.js +8 -10
  59. package/dist/preview/index.js +4 -4
  60. package/dist/preview/paint.d.ts +1 -1
  61. package/dist/preview/paint.js +17 -19
  62. package/dist/visual/ArrayField.svelte +80 -66
  63. package/dist/visual/ArrayField.svelte.d.ts +1 -1
  64. package/dist/visual/BooleanField.svelte +8 -6
  65. package/dist/visual/BooleanField.svelte.d.ts +2 -2
  66. package/dist/visual/Card.svelte +160 -329
  67. package/dist/visual/Card.svelte.d.ts +2 -7
  68. package/dist/visual/CardControls.svelte +1 -1
  69. package/dist/visual/DateField.svelte +19 -19
  70. package/dist/visual/DateField.svelte.d.ts +3 -3
  71. package/dist/visual/DiagnosticList.svelte +1 -1
  72. package/dist/visual/EnumField.svelte +16 -16
  73. package/dist/visual/EnumField.svelte.d.ts +2 -2
  74. package/dist/visual/Field.svelte +128 -115
  75. package/dist/visual/Field.svelte.d.ts +1 -1
  76. package/dist/visual/FieldHint.svelte +24 -42
  77. package/dist/visual/FieldHint.svelte.d.ts +1 -1
  78. package/dist/visual/FieldLabel.svelte +8 -8
  79. package/dist/visual/FormatPopover.svelte +80 -35
  80. package/dist/visual/NumberField.svelte +5 -5
  81. package/dist/visual/NumberField.svelte.d.ts +1 -1
  82. package/dist/visual/ObjectField.svelte +9 -9
  83. package/dist/visual/ObjectField.svelte.d.ts +1 -1
  84. package/dist/visual/ProseArrayElement.svelte +11 -13
  85. package/dist/visual/ProseArrayElement.svelte.d.ts +1 -1
  86. package/dist/visual/ProseField.svelte +53 -87
  87. package/dist/visual/ProseField.svelte.d.ts +13 -19
  88. package/dist/visual/SlashMenu.svelte +42 -16
  89. package/dist/visual/TextField.svelte +5 -5
  90. package/dist/visual/TextField.svelte.d.ts +1 -1
  91. package/dist/visual/TipsCard.svelte +68 -56
  92. package/dist/visual/VisualEditor.svelte +6 -6
  93. package/dist/visual/VisualEditorInner.svelte +203 -290
  94. package/dist/visual/controls.css +74 -30
  95. package/dist/visual/diagnostics.d.ts +5 -5
  96. package/dist/visual/diagnostics.js +3 -3
  97. package/dist/visual/domid.js +3 -3
  98. package/dist/visual/ext.d.ts +1 -1
  99. package/dist/visual/ext.js +1 -1
  100. package/dist/visual/icons/nodes.d.ts +19 -0
  101. package/dist/visual/icons/nodes.js +13 -1
  102. package/dist/visual/index.js +4 -4
  103. package/dist/visual/leaves.d.ts +3 -3
  104. package/dist/visual/leaves.js +1 -1
  105. package/dist/visual/links.d.ts +24 -0
  106. package/dist/visual/links.js +67 -0
  107. package/dist/visual/props.d.ts +8 -8
  108. package/dist/visual/signals.d.ts +6 -6
  109. package/dist/visual/strings.d.ts +14 -19
  110. package/dist/visual/strings.js +5 -7
  111. package/dist/visual/structure.d.ts +24 -17
  112. package/dist/visual/structure.js +8 -8
  113. package/dist/visual/synced.svelte.d.ts +1 -1
  114. package/dist/visual/synced.svelte.js +4 -4
  115. package/dist/visual/tips.d.ts +2 -2
  116. package/dist/visual/tips.js +3 -3
  117. package/package.json +2 -2
  118. package/dist/preview/overlay.d.ts +0 -11
  119. package/dist/preview/overlay.js +0 -97
@@ -1,10 +1,10 @@
1
1
  /* The one derivation: public dials in, a closed private scale out (THEMING.md).
2
2
  Everything below reads a rung rather than minting a value, which is this file's
3
3
  whole reason for existing and what `check:style` holds everywhere else. Colour,
4
- geometry, type and motion are all derived here, so each is minted in ONE place
4
+ geometry, type and motion are all derived here, so each is minted in one place
5
5
  instead of once per detached root.
6
6
 
7
- TRANSPORT: a stylesheet, side-effect imported by `core/index.ts` and applied to
7
+ Transport: a stylesheet, side-effect imported by `core/index.ts` and applied to
8
8
  every element marked `data-qm-root`. The package imports it itself, so there is
9
9
  no `import './theme.css'` for a consumer to forget. A stylesheet rather than an
10
10
  inline `style` attribute is what buys the three things an attribute cannot
@@ -19,21 +19,21 @@
19
19
  chrome that still reads as intact. `check:bundle` holds both ends, the claim and
20
20
  the built bytes.
21
21
 
22
- Every value stays a `var()` reference, so the dials resolve against the CASCADE
22
+ Every value stays a `var()` reference, so the dials resolve against the cascade
23
23
  at each root: a consumer's `[data-theme="dark"]` ancestor rule flows in
24
24
  unchanged, the light/dark default follows the `color-scheme` the host declares
25
25
  with no JS and no media query, and `color-mix` runs at paint time. The rungs are
26
- declared ON the root, so they are reachable only by a rule targeting it:
26
+ declared on the root, so they are reachable only by a rule targeting it:
27
27
  THEMING.md §"What is deliberately not public" states the terms.
28
28
 
29
- LAYERS: `qm` is the top-level layer name, and it is contract — a consumer
29
+ Layers: `qm` is the top-level layer name, and it is contract — a consumer
30
30
  pins the order against it with `@layer qm, app;` in their own CSS, which wins
31
31
  in both bundler orders (THEMING §"Your CSS beats ours"). Unlayered consumer
32
32
  CSS beats every layer here for free.
33
33
 
34
- `@property` registers the three ENTRY rungs, the ones reading a dial, and
34
+ `@property` registers the three entry rungs, the ones reading a dial, and
35
35
  nothing below them. An `initial-value` must be computationally independent,
36
- which `rem` is not, so the DIALS cannot be registered: their defaults are
36
+ which `rem` is not, so the dials cannot be registered: their defaults are
37
37
  `rem`. A rung can, because registration reads the initial value and never the
38
38
  declared one, so a `px` initial sits under a `calc()` chain over a `rem` dial
39
39
  without contradiction. What it buys is the poison case: `--qm-space: 4` is a
@@ -69,41 +69,86 @@
69
69
  @layer qm.scale {
70
70
  :where([data-qm-root]) {
71
71
  /* ── Poles ───────────────────────────────────────────────────────────────
72
- Each dial's default, stated ONCE. Every rung below reads a pole, never a
72
+ Each dial's default, stated once. Every rung below reads a pole, never a
73
73
  dial, so both schemes cost two declarations rather than fifteen; and the
74
- dial sits in FRONT of the default, so a consumer's ancestor value wins in
74
+ dial sits in front of the default, so a consumer's ancestor value wins in
75
75
  either scheme, which it would not if a scheme rule set `--qm-bg` instead.
76
76
 
77
- `light-dark()` keys the default off the `color-scheme` this root INHERITS,
77
+ `light-dark()` keys the default off the `color-scheme` this root inherits,
78
78
  which is the host's: an app that declares `dark` gets a dark surface
79
79
  whatever the OS says, and one that declares nothing gets light, matching
80
80
  its own unstyled text. So the package owns no mode logic at all: light or
81
81
  dark is the mounting site's, like every other value here (THEMING.md
82
- §"The surface follows your colour scheme"). */
83
- --_qm-bg: var(--qm-bg, light-dark(#fff, #14171c));
84
- --_qm-fg: var(--qm-fg, light-dark(#1a1a1a, #e8eaed));
85
- --_qm-accent: var(--qm-accent, #2563eb);
82
+ §"The surface follows your colour scheme").
83
+
84
+ `--qm-bg` is the card, not the column behind it: the plane content is
85
+ written on, which is also the preview's paper. Everything else is a step
86
+ off it, and the column is a step down. */
87
+ --_qm-bg: var(--qm-bg, light-dark(#fff, #272729));
88
+ --_qm-fg: var(--qm-fg, light-dark(#1c1c1c, #d7dadc));
89
+ /* Neutral: the surface spends no hue on a state it can draw in grey. The pair
90
+ clears WCAG 2.4.11's 3:1 against the card at both poles, at 4.8:1 and 5.8:1. */
91
+ --_qm-accent: var(--qm-accent, light-dark(#71717a, #a1a1aa));
86
92
  --_qm-danger: var(--qm-danger, #c5221f);
87
93
  --_qm-warning: var(--qm-warning, #b25000);
88
94
  --_qm-font: var(--qm-font, ui-sans-serif, system-ui, sans-serif);
89
95
  --_qm-font-mono: var(--qm-font-mono, ui-monospace, monospace);
90
96
 
91
97
  /* ── Colour ──────────────────────────────────────────────────────────────
92
- Surfaces step bg → fg, ink steps fg → bg, mixed in oklab; sRGB muddies
93
- the mid-tones and the label/meta/border rungs are exactly mid-tone. So
94
- inverting the poles inverts the scale. The percentages are calibrated to
95
- the light-mode literals they stand in for (17% ≈ #d4d4d4, 35% ≈ #555).
98
+ Ink steps fg → bg, the border and hover rungs step bg → fg, all mixed in
99
+ oklab; sRGB muddies the mid-tones and the label/meta/border rungs are
100
+ exactly mid-tone. So inverting the poles inverts that half of the scale.
101
+ The percentages are calibrated to the light-mode literals they stand in
102
+ for (17% ≈ #d4d4d4, 35% ≈ #555).
103
+
104
+ Planes are the half that does not read the ink pole, because what makes a
105
+ card read as a card is that it is the brighter plane, in both schemes
106
+ alike (ARCHITECTURE §Styling). A plane stepped toward the ink is right in
107
+ dark and inverted in light, where it darkens the card below the page it
108
+ floats on. So `sunken` and `well` step toward shadow and `raised` toward
109
+ light, and the base plane — a card, the preview's paper — is the pole
110
+ itself.
111
+
112
+ Two planes sink. `sunken` is the ground — the column behind the cards, the
113
+ desk behind the sheets — and lifting the plane above it takes very little
114
+ at the light pole. `well` is the hole cut into a card: a field, a table's
115
+ header band, the one native select, none of which draw an edge, so the
116
+ step is the whole of what says a value is typed there. The order at the
117
+ light pole is card, ground, well; at the dark pole the two sink to within
118
+ a channel of each other, which is where a card with little light left to
119
+ give up leaves them.
120
+
121
+ Each takes two arms, because one figure cannot serve both poles: a dark
122
+ surface has to spend more of what little it has before the card above it
123
+ reads as lifted. Pinning a dark palette under a light `color-scheme` takes
124
+ the light arm with it
125
+ (THEMING §"The surface follows your colour scheme"), which is a step you
126
+ can barely see, so a host that pins declares the scheme with it.
96
127
 
97
- The three surface rungs sit EVENLY 4pp apart, which is what keeps them three
98
- distinguishable steps: uneven spacing spends one rung to buy another:
99
- widening `raised` alone would leave `hover` 1pp above it. `raised` steps
100
- toward the INK pole rather than away from it, so a card is darker than the
101
- page in light and lighter in dark. */
128
+ The ground steps by subtraction where every other rung mixes: a mix toward
129
+ black is a ratio, so it scales what it takes and pulls the result toward
130
+ neutral, and a ground is a fixed distance that keeps the pole's hue. Its
131
+ arms are 0.0214 of oklab L in light and 0.0553 in dark, with a/b terms
132
+ carrying a cool cast a mix toward black would strip, so the default lands
133
+ on `#f7f8f9` and `#1a1a1b` exactly and a turned `--qm-bg` tints the plane
134
+ under it.
135
+
136
+ `raised` is a no-op at the light pole, where the card is already white
137
+ and there is nowhere further to go, so a floating surface separates on
138
+ its hairline in light and on the step in dark. */
102
139
  --_qm-surface: var(--_qm-bg);
103
- --_qm-surface-raised: color-mix(in oklab, var(--_qm-bg), var(--_qm-fg) 4%);
140
+ --_qm-surface-sunken: light-dark(
141
+ oklab(from var(--_qm-bg) calc(l - 0.0214) calc(a - 0.00065) calc(b - 0.00158)),
142
+ oklab(from var(--_qm-bg) calc(l - 0.0553) calc(a - 0.00048) calc(b + 0.00165))
143
+ );
144
+ --_qm-surface-well: light-dark(
145
+ color-mix(in oklab, var(--_qm-bg), #000 4%),
146
+ color-mix(in oklab, var(--_qm-bg), #000 20%)
147
+ );
148
+ --_qm-surface-raised: color-mix(in oklab, var(--_qm-bg), #fff 8%);
104
149
  --_qm-surface-hover: color-mix(in oklab, var(--_qm-bg), var(--_qm-fg) 8%);
105
150
  --_qm-border: color-mix(in oklab, var(--_qm-bg), var(--_qm-fg) 17%);
106
- /* A rule that separates without structuring: the lines BETWEEN a table's cells,
151
+ /* A rule that separates without structuring: the lines between a table's cells,
107
152
  where the frame around them is the structure. Half the border's mix rather
108
153
  than a surface rung of its own, because it is a stroke and reads against the
109
154
  surface behind it, not a fill stacked on one. */
@@ -113,10 +158,50 @@
113
158
  --_qm-ink: var(--_qm-fg);
114
159
  --_qm-ink-label: color-mix(in oklab, var(--_qm-fg), var(--_qm-bg) 35%);
115
160
  --_qm-ink-ghost: color-mix(in oklab, var(--_qm-fg), var(--_qm-bg) 60%);
116
- /* The correlation wash (`core/bloom.ts`). Its alpha is a PEAK, not a tint: the
117
- wash animates from and back to zero, never held, so it reads at pane scale
118
- over the preview's paper while the paper rests clean. */
161
+ /* The arrival wash (`core/bloom.ts`). Its alpha is a peak, not a tint: the
162
+ wash animates from and back to zero, never held, so it reads over the leaf it
163
+ lands on while the leaf rests clean. */
119
164
  --_qm-accent-wash: color-mix(in oklab, var(--_qm-accent) 18%, transparent);
165
+ /* The accent held: what a selected line of a table is tinted with, and what its
166
+ grip is filled with, so the two ends of one gesture are one colour. A second
167
+ name rather than the wash reused, because the two answer different questions
168
+ and the numbers follow: a peak passes over paper and can be strong, where a
169
+ tint is held under body text and cannot. Translucent, so it
170
+ stacks over whichever surface rung the cell already draws instead of replacing
171
+ it. */
172
+ --_qm-accent-tint: color-mix(in oklab, var(--_qm-accent) 12%, transparent);
173
+ /* The danger hue held: what a destructive control fills with where the family's
174
+ neutral hover rung would read as one more button. Mixed at the accent tint's
175
+ strength, so a held tint is a held tint whichever hue it carries. */
176
+ --_qm-danger-tint: color-mix(in oklab, var(--_qm-danger) 12%, transparent);
177
+ /* The label ink held: what a trigger fills with whose own ink never steps, so
178
+ the fill arriving under it is that tone at a strength a surface reads
179
+ through. */
180
+ --_qm-add-fill: color-mix(in oklab, var(--_qm-ink-label) 15%, transparent);
181
+
182
+ /* The tips card'S hue: the surface's one exit from the greyscale that is not
183
+ a status, and what the amber and the typewriter face say together is
184
+ draft (VISUAL_EDITOR §"Card operations"). A literal rather than a dial
185
+ because there is nothing left to turn: the rungs under it mix over
186
+ the surface and the ink a consumer already tuned, so the card follows a
187
+ brand untold. The mixes are faint on purpose: a warmth, not a badge. */
188
+ --_qm-tips: #e88c0a;
189
+ --_qm-tips-surface: color-mix(in oklab, var(--_qm-surface), var(--_qm-tips) 4%);
190
+ --_qm-tips-ink: color-mix(in oklab, var(--_qm-ink), var(--_qm-tips) 24%);
191
+ /* The ink and the amber stepped up, and the pair is spent on the two runs that
192
+ are not the sentence: a token in a tip, and the foot's control under the
193
+ pointer. One rung each rather than one per run, a chip and a hover four
194
+ percent apart being a number with no second decision under it. */
195
+ --_qm-tips-ink-warm: color-mix(in oklab, var(--_qm-ink), var(--_qm-tips) 45%);
196
+ --_qm-tips-fill: color-mix(in oklab, var(--_qm-tips) 12%, transparent);
197
+ /* The typewriter, the half of the slip the amber cannot carry: a modern mono
198
+ reads as code where a Courier reads as typed. Its own rung rather than
199
+ `--_qm-font-mono`, the chrome's readout face, which a consumer turns for
200
+ tabular figures and not to dress this card. Courier Prime leads and is nobody's
201
+ system font, so a host that loads it lands on it and every other host falls to
202
+ the Courier the platform already carries; the package fetches nothing, a preset
203
+ costing a network request being one a consumer cannot decline. */
204
+ --_qm-tips-font: 'Courier Prime', 'Courier New', Courier, ui-monospace, monospace;
120
205
 
121
206
  /* ── Ratios and effects ──────────────────────────────────────────────────
122
207
  No palette fixes these, so they are their own rungs. There is no shadow
@@ -136,19 +221,22 @@
136
221
  --_qm-opacity-muted: 0.5;
137
222
 
138
223
  /* ── Focus ───────────────────────────────────────────────────────────────
139
- These fix the ring's VALUE, so no control mints it. Which properties draw a
224
+ These fix the ring's value, so no control mints it. Which properties draw a
140
225
  ring, and on what state, is the other half: a rule, `.qm-focus-ring` in
141
226
  `visual/controls.css`, since a rung each control reassembles is a scale
142
- only up to the point where it is assembled. ONE width: focus is the only
143
- state that draws a ring anywhere, so there is no held-back tier under it. */
144
- --_qm-ring-width: 2px;
145
- /* Every ring the surface draws, whatever the state under it: focus and selection
146
- alike, which is why the name carries neither. Assembled here because the parts
147
- spelled out at a use site pass every axis — each reads a rung — while drawing a
148
- ring nothing else agrees with. The width stays separately reachable: a drop
149
- indicator is the ring's thickness without being a ring. */
227
+ only up to the point where it is assembled. One width: focus is the only
228
+ state that draws a ring anywhere, so there is no held-back tier under it.
229
+ Sub-pixel, because at two it reads as a second border on a card whose every
230
+ other edge is a hairline. */
231
+ --_qm-ring-width: 1.5px;
232
+ /* Every ring the surface draws, focus and selection alike, which is why the name
233
+ carries neither. Assembled here because the parts spelled out at a use site pass
234
+ every axis — each reads a rung — while drawing a ring nothing else agrees with. */
150
235
  --_qm-ring: var(--_qm-ring-width) solid var(--_qm-accent);
151
236
  --_qm-ring-offset: 1px;
237
+ /* What a clip box carries past its content for a focused control inside it to
238
+ keep the whole mark. */
239
+ --_qm-ring-reach: calc(var(--_qm-ring-width) + var(--_qm-ring-offset));
152
240
 
153
241
  /* ── Motion ──────────────────────────────────────────────────────────────
154
242
  Two rungs, by what the trip disturbs: `fast` stays inside the element's own
@@ -160,14 +248,18 @@
160
248
  animates over WAAPI and reads it from here. */
161
249
  --_qm-bloom-dwell: 1100ms;
162
250
 
163
- /* ONE curve, symmetric because an interruption turns these trips around: a hover
164
- leaves before it arrives, a card collapses mid-expand. The one-way pair a scale
165
- like this often carries is minted when a trip long enough to read one arrives;
166
- the popover's pop is the nearest and at `fast` it is under that threshold. */
251
+ /* One curve, symmetric because an interruption turns these trips around: a hover
252
+ leaves before it arrives, a card collapses mid-expand. Every trip at `fast` or
253
+ `slow` takes it; a one-way shape is legible only over a longer one. */
167
254
  --_qm-ease-reverse: cubic-bezier(0.4, 0, 0.6, 1);
255
+ /* A trip rather than a rung, duration and curve composed the way `--_qm-ring`
256
+ composes its three: neither half is reachable alone. Weighted to its end, so an
257
+ arrival settles into its rest instead of stopping at it, and long enough that a
258
+ control resting at nothing reads as arriving rather than as switching. */
259
+ --_qm-reveal: 500ms cubic-bezier(0.4, 0, 0.2, 1);
168
260
 
169
261
  /* ── Geometry ──────────────────────────────────────────────────────────*/
170
- /* ONE stroke width for every edge the chrome draws: a card's, a control's,
262
+ /* One stroke width for every edge the chrome draws: a card's, a control's,
171
263
  and the metadata bracket's three rules alike. A threshold rather than a
172
264
  rhythm choice, like the tap floor: a hairline is a hairline at any
173
265
  `--qm-space`, so it does not derive from a dial. It exists as a rung because
@@ -176,7 +268,7 @@
176
268
  against a token. */
177
269
  --_qm-border-width: 1px;
178
270
  --_qm-radius: var(--qm-radius, 8px);
179
- /* The INTERIOR corner, and HALF is the relationship rather than the number: a
271
+ /* The interior corner, and half is the relationship rather than the number: a
180
272
  corner inside a corner reads as nested only while it is visibly tighter, and
181
273
  halving holds that at every setting of the dial, zero included. */
182
274
  --_qm-radius-inner: calc(var(--_qm-radius) / 2);
@@ -188,15 +280,16 @@
188
280
  --_qm-space-2: calc(var(--_qm-space) * 2);
189
281
  --_qm-space-3: calc(var(--_qm-space) * 3);
190
282
  --_qm-space-4: calc(var(--_qm-space) * 4);
283
+ --_qm-space-5: calc(var(--_qm-space) * 5);
191
284
  /* A rung because the two axes are two decisions and the ladder alone cannot hold
192
285
  them together: `check:style`'s rhythm axis sees each box read a rung, never that
193
- they read the SAME one, which is the drift `visual/controls.css` already names
286
+ they read the same one, which is the drift `visual/controls.css` already names
194
287
  for the type half. Asymmetric because the vertical is what leading leaves once
195
288
  it has taken the line box, and the horizontal is how far in the text starts,
196
289
  which nothing else fixes. */
197
290
  --_qm-inset-control: var(--_qm-space) var(--_qm-space-3);
198
- /* The scroll TAIL: dead space under the last card, so it can be read at the
199
- middle of a pane rather than at its bottom edge. A fraction of the VIEWPORT
291
+ /* The scroll tail: dead space under the last card, so it can be read at the
292
+ middle of a pane rather than at its bottom edge. A fraction of the viewport
200
293
  rather than a step on the ramp, because what it answers is how far the eye
201
294
  sits from the bottom of the screen, which no spacing dial knows. Spent by
202
295
  the editor alone (`.qm-pane`): a stack of cards is what has a last one to
@@ -208,7 +301,7 @@
208
301
  floor is one number instead of one expression per control. */
209
302
  --_qm-tap-min: 24px;
210
303
  /* The reorder/delete glyph. A rung because the card header's
211
- right hang is HALF the difference between this and the tap floor: the glyph
304
+ right hang is half the difference between this and the tap floor: the glyph
212
305
  centres in a target sized by the floor, so what stands between it and the
213
306
  card's gutter is an arithmetic of the two, and a literal on either side is a
214
307
  balance that silently breaks when the glyph moves. Sized in CSS rather than
@@ -218,35 +311,48 @@
218
311
  --_qm-glyph-control: 14px;
219
312
 
220
313
  /* ── Type ────────────────────────────────────────────────────────────────
221
- `--qm-font-size` anchors the CHROME rung; 1.125 is the ratio between adjacent
314
+ `--qm-font-size` anchors the chrome rung; 1.125 is the ratio between adjacent
222
315
  rungs: a step up (title) and one down (label). The ratio and the
223
316
  weight are fixed conventions, not dials: no consumer tunes a typographic
224
- ratio, and a dial nobody turns is a name every reader still holds. THREE chrome
317
+ ratio, and a dial nobody turns is a name every reader still holds. Three chrome
225
318
  rungs: a second step below `label` lands near 11px, under a size anything here
226
319
  wants to be read at, and the supporting text that would take it is what `label`
227
320
  already is. */
228
321
  --_qm-text-body: var(--qm-font-size, 0.875rem);
229
322
  --_qm-text-title: calc(var(--_qm-text-body) * 1.125);
230
323
  --_qm-text-label: calc(var(--_qm-text-body) / 1.125);
231
- /* PAPER: the document body answers to the preview's paper where every other
324
+ /* Paper: the document body answers to the preview's paper where every other
232
325
  surface here answers to the control beside it, so a rung shared with the chrome
233
326
  makes a consumer asking for larger prose take larger inputs with it. 16/15 where
234
- the ramp steps at 9/8: small enough to read as a change of REGISTER rather than
327
+ the ramp steps at 9/8: small enough to read as a change of register rather than
235
328
  a rung of hierarchy, and clear of the title rung, which one 9/8 step lands on
236
329
  exactly. */
237
330
  --_qm-text-paper: calc(var(--_qm-text-body) * 16 / 15);
238
- /* ONE weight over the regular: every heading here is a name over the value under
239
- it, so a second is a rung with no register beneath it. Hierarchy is the size
240
- ramp's. */
241
- --_qm-weight-label: 600;
331
+ /* Two weights over the regular, and only one of them is chrome. `mid` names
332
+ everything the surface names — a card title, a section header, a field
333
+ label, a nested property — so a stack of them reads as one register and
334
+ hierarchy stays the size ramp's, which is the axis that can carry it.
335
+ 500 rather than 600 because the family dial resolves to the platform UI
336
+ face, whose 600 is heavier at the same number than the webfont a surface
337
+ is usually drawn against: at the label rung it goes smudgy, and one
338
+ number across three sizes does not read as one weight.
339
+
340
+ `strong` is not a rung of that ramp. It is the mark a run wears where
341
+ weight is the only signal it has: a heading inside a prose leaf, drawn at
342
+ no size step of its own because the quill sets the paper's; a table
343
+ island's header row; the stored value in an enum listbox. Reaching for it
344
+ where a size or a tone could speak is the drift the split exists to
345
+ stop. */
346
+ --_qm-weight-strong: 600;
347
+ --_qm-weight-mid: 500;
242
348
  /* Leading: the ramp's third axis, and it does not track the sizes one for one:
243
349
  two rungs, because a wrapped label and a wrapped paragraph want different
244
350
  rhythms and nothing wants four. `body` is reading rhythm (both prose leaves,
245
351
  every control beside them, the tips card's guidance); `tight` is a line that is
246
- a label rather than a passage. Unitless, so a rung inherits MULTIPLICATIVELY
352
+ a label rather than a passage. Unitless, so a rung inherits multiplicatively
247
353
  and holds against whichever size rung the surface reads: a `rem` leading
248
354
  would freeze at one size and disagree with the rest of the ramp. It is the
249
- axis paper and chrome SHARE: both read `body`, and the size rung is what
355
+ axis paper and chrome share: both read `body`, and the size rung is what
250
356
  separates them. `line-height: 1` is outside the axis: it collapses the
251
357
  line box onto its content, a glyph or a button's one-line label. */
252
358
  --_qm-leading-body: 1.5;
@@ -260,12 +366,12 @@
260
366
  picker, the caret) lands on the same pole the poles above resolve to.
261
367
  Declaring it here would break that lockstep in the one direction that
262
368
  matters: a host that declares `dark` would get light native chrome under
263
- a dark surface. A consumer that PINS a palette against its own scheme
369
+ a dark surface. A consumer that pins a palette against its own scheme
264
370
  declares `color-scheme` with it, on the root (THEMING.md).
265
371
 
266
- Face, ink and LEADING are the three axes a root carries this way. Leading
372
+ Face, ink and leading are the three axes a root carries this way. Leading
267
373
  belongs with the other two because a unitless ratio inherits
268
- MULTIPLICATIVELY: it holds against whatever size rung each surface reads, so
374
+ multiplicatively: it holds against whatever size rung each surface reads, so
269
375
  it imposes less than the ink beside it, and the reason `font-size` stays off
270
376
  does not transfer: a ratio has no size to sweep a consumer's content with.
271
377
  What it buys is that `normal` (the UA figure near 1.14, varying by font) is
@@ -273,13 +379,13 @@
273
379
  whether or not it remembers to say so, and a per-surface
274
380
  `--_qm-leading-tight` reads as the deliberate override it is.
275
381
 
276
- Deliberately NOT `font-size`, and the reason is about the ROOT rule rather
382
+ Deliberately not `font-size`, and the reason is about the root rule rather
277
383
  than about size: a root-level body size sweeps every descendant a consumer
278
384
  may have put inside the marker, which is a reach the derivation does not
279
385
  have. The rung is not withheld from the surfaces: every control and every
280
386
  prose leaf reads `--_qm-text-body` in its own recipe, which is
281
387
  what closes the ramp and makes `--qm-font-size` move an input. What would
282
- break a mounted leaf is a size that CHANGES under it; a rung is fixed at
388
+ break a mounted leaf is a size that changes under it; a rung is fixed at
283
389
  mount unless the consumer turns the dial, and a consumer turning a dial is
284
390
  entitled to the reflow. So: the root imposes no size, each surface reads the
285
391
  rung it wants. */
@@ -288,10 +394,10 @@
288
394
  line-height: var(--_qm-leading-body);
289
395
  }
290
396
 
291
- /* Reduced motion collapses the SCALE, never a list of selectors.
397
+ /* Reduced motion collapses the scale, never a list of selectors.
292
398
  Two values here are not the rung they look like:
293
399
 
294
- `1ms` rather than `none`, because a collapsed transition still FIRES: a surface
400
+ `1ms` rather than `none`, because a collapsed transition still fires: a surface
295
401
  waiting on `transitionend` keeps its event, where `transition: none` would strand
296
402
  it. The beat is under perception either way.
297
403
 
@@ -1,7 +1,7 @@
1
1
  /* `@quillmark/svelte/preset`, the package's one CSS entry point: the endorsed look for
2
2
  the page a surface is mounted on. Opt-in and side-effect free until imported:
3
3
  `core/index.ts` pulls `core/theme.css` for the surfaces and never this, because this
4
- styles the DOCUMENT and nothing may put that in a consumer's page uninvited.
4
+ styles the document and nothing may put that in a consumer's page uninvited.
5
5
 
6
6
  Two files because one of them is exempt: `scale.css` is where the literals are
7
7
  minted, `recipes.css` is held to reading them. */
@@ -1,14 +1,14 @@
1
- /* THE ENDORSED LOOK: the rules a host draws around a mounted surface AND the shell it
1
+ /* The endorsed look: the rules a host draws around a mounted surface and the shell it
2
2
  mounts one in, as classes it puts on its own elements. The rungs beside this in
3
3
  `scale.css` are the invisible half (a scale alone still leaves a consumer writing
4
4
  every declaration before anything on the page looks like anything), so the recipes
5
5
  are what the preset is for. This file mints nothing; `check:style` runs its axes here.
6
6
 
7
- These are HOST classes. They land on the consumer's DOM, never on a mounted root, so
7
+ These are host classes. They land on the consumer's DOM, never on a mounted root, so
8
8
  they freeze nothing about the surfaces' interior: the reason the package withholds
9
9
  its own internal classes does not reach them.
10
10
 
11
- UNLAYERED, deliberately. `@layer qm` exists so consumer CSS beats the surfaces
11
+ Unlayered, deliberately. `@layer qm` exists so consumer CSS beats the surfaces
12
12
  without `!important`, and the same has to be true here; a layer of the preset's own
13
13
  would put a second name in the contract and change what `revert-layer` at the foot
14
14
  of this file resolves against. Unlayered, a consumer's own rules win by ordinary
@@ -16,12 +16,12 @@
16
16
 
17
17
  /* ── The page ──────────────────────────────────────────────────────────────── */
18
18
 
19
- /* The baseline, on a CLASS rather than `body`: a preset that restyled the document
19
+ /* The baseline, on a class rather than `body`: a preset that restyled the document
20
20
  root would land on an app that already has a page and change it out from under
21
21
  whatever was there. The host puts this where its own layout starts: `body`, or the
22
22
  element the app mounts into.
23
23
 
24
- `color-scheme` is declared HERE and not by the package: light or dark is the
24
+ `color-scheme` is declared here and not by the package: light or dark is the
25
25
  mounting site's, and this file is the mounting site. `light dark` follows the OS;
26
26
  a host pinning one declares it on the same element and wins by source order. */
27
27
  .qm-page {
@@ -43,11 +43,11 @@
43
43
 
44
44
  /* ── The workspace ─────────────────────────────────────────────────────────── */
45
45
 
46
- /* The rules above dress the page a surface sits ON; these four are the SHELL it is
46
+ /* The rules above dress the page a surface sits on; these four are the shell it is
47
47
  mounted in, a tool where `.qm-page` is a document: the screen an app that mounts two
48
48
  surfaces over one session is, drawn once (ARCHITECTURE §Styling).
49
49
 
50
- PINNED to the viewport rather than sized to it: a page-height box still leaves the
50
+ Pinned to the viewport rather than sized to it: a page-height box still leaves the
51
51
  root scroller counting the overflow its panes clip, and a wheel over the chrome drags
52
52
  the whole app off the top. Three bands (a head, the body, an optional foot), and the
53
53
  body takes what is left and may shrink below its content, so the panes in it own
@@ -67,8 +67,8 @@ html:has(.qm-workspace) {
67
67
  overscroll-behavior: none;
68
68
  }
69
69
 
70
- /* A band's LINE: the row a head or a foot puts its parts on, wrapping, centred. That is
71
- the whole of it. What a band is made OF is the host's: the rule under it, the gutter
70
+ /* A band's line: the row a head or a foot puts its parts on, wrapping, centred. That is
71
+ the whole of it. What a band is made of is the host's: the rule under it, the gutter
72
72
  beside it, and the depth of it, because where a band ends and how tall it stands are
73
73
  page-shell decisions: a site holding its content to a maximum runs the rule past it at
74
74
  its own rhythm, and a one-screen tool has no maximum to hold to. */
@@ -79,11 +79,11 @@ html:has(.qm-workspace) {
79
79
  gap: var(--qmh-space-2) var(--qmh-space-4);
80
80
  }
81
81
 
82
- /* TWO EVEN TRACKS for two surfaces, and no resizer, since a divider that can be dragged
82
+ /* Two even tracks for two surfaces, and no resizer, since a divider that can be dragged
83
83
  is a control competing with what it divides. Each track may shrink below its content,
84
84
  which is what lets the frame in it clip rather than grow.
85
85
 
86
- The GAP is the endorsed default and not a fact about splitting: two surfaces standing
86
+ The gap is the endorsed default and not a fact about splitting: two surfaces standing
87
87
  apart on a page read as two things, which is what a host showing its instruments wants.
88
88
  A host that spends the whole screen on the mounts closes it to nothing and carries a
89
89
  hairline on one pane instead: one property, and the tracks are untouched. */
@@ -95,32 +95,32 @@ html:has(.qm-workspace) {
95
95
  min-height: 0;
96
96
  }
97
97
 
98
- /* THE BAND THAT SWITCHES THEM, and nothing at the widths where both tracks are showing
98
+ /* The band that switches them, and nothing at the widths where both tracks are showing
99
99
  and there is nothing to switch. Where it stands is the host's, like any other band; what
100
100
  goes in it is a pair of `.qm-control`s, which already carry the on-state a pressed
101
- control takes. Its visibility is the PRESET's because the threshold is: a host hiding
101
+ control takes. Its visibility is the preset's because the threshold is: a host hiding
102
102
  its own tab row writes this file's number a second time, which is the one thing the
103
103
  single source is for. */
104
104
  .qm-switch {
105
105
  display: none;
106
106
  }
107
107
 
108
- /* ONE MOUNT AT A TIME under the threshold, rather than two of them abreast. Half a narrow
108
+ /* One mount at A time under the threshold, rather than two of them abreast. Half a narrow
109
109
  viewport is under the width either surface reads at, so the split stops being one and
110
110
  the tracks become views of the same room: the host says which with `data-qm-show`, and
111
- the attribute names the TRACK rather than what is in it, so nothing here knows an editor
111
+ the attribute names the track rather than what is in it, so nothing here knows an editor
112
112
  from a preview. No attribute is the first track.
113
113
 
114
114
  The other track is `display: none` and not a clip, which is the whole of the hiding: it
115
115
  leaves the tab order, hit-testing and the accessibility tree in one property, so the
116
- pane needs no `inert` and the host needs no breakpoint in JS. Both stay MOUNTED (a
116
+ pane needs no `inert` and the host needs no breakpoint in JS. Both stay mounted (a
117
117
  preview binds its handle once, an editor holds a caret, a history and a scroll), so
118
118
  the switch is presentational, never conditional. A pane hidden this way keeps the
119
119
  pixels it had (the paint loop's band sweep no-ops on an empty visible set) and repaints
120
120
  from its live box when it comes back, which its resize observer sees as a width moving
121
121
  off zero.
122
122
 
123
- HEIGHT is the second clause because a landscape phone passes the first one: it clears
123
+ Height is the second clause because a landscape phone passes the first one: it clears
124
124
  the width with room for two tracks and has no body left to put them in. A desktop window
125
125
  that short wants one mount for the same reason. */
126
126
  @media (width < 50rem), (height < 30rem) {
@@ -129,7 +129,7 @@ html:has(.qm-workspace) {
129
129
  gap: var(--qmh-space);
130
130
  }
131
131
 
132
- /* Even halves of the band, at the height a THUMB needs. The floor is the recipe's and
132
+ /* Even halves of the band, at the height a thumb needs. The floor is the recipe's and
133
133
  not the host's, because the band exists only at the sizes where the pointer is a
134
134
  finger: a host is free to stand the band deeper, and has nothing to gain from
135
135
  standing it shallower than the thing it is tapping. */
@@ -154,18 +154,18 @@ html:has(.qm-workspace) {
154
154
  }
155
155
  }
156
156
 
157
- /* THE MOUNTING SITE: an edge, a corner, and the clip that holds a surface to them, which
157
+ /* The mounting site: an edge, a corner, and the clip that holds a surface to them, which
158
158
  is all a surface painting its own column needs. No tone and no gutter: those are the
159
159
  surface's own (THEMING §"Drop it in"). `border-box`, so a stated height is the height
160
160
  it draws.
161
161
 
162
- POSITIONED, because a clip reaches only what it is the containing block for: a
162
+ Positioned, because a clip reaches only what it is the containing block for: a
163
163
  surface's out-of-flow parts (a parked description, an overlay) resolve against the
164
164
  nearest positioned ancestor, and with none between them and the document they land at
165
- their static position UNCLIPPED, leaving the page to scroll past its own foot by
165
+ their static position unclipped, leaving the page to scroll past its own foot by
166
166
  however far the frame's contents run over.
167
167
 
168
- The two minimums are what let a frame in a track CLIP rather than push: a grid or flex
168
+ The two minimums are what let a frame in a track clip rather than push: a grid or flex
169
169
  item floors at its content, so a mount that paints wider than its column widens the
170
170
  column instead. They ride the frame rather than the split's children, which keeps every
171
171
  rule in this file landing where the host put a class. Outside a track they are the
@@ -208,7 +208,7 @@ html:has(.qm-workspace) {
208
208
  }
209
209
 
210
210
  /* The block form: a dump, or a snippet. `pre` keeps the wrapping the value came with;
211
- the plate is the page's own, one rung under whatever it sits in. How TALL such a
211
+ the plate is the page's own, one rung under whatever it sits in. How tall such a
212
212
  block may grow before it scrolls is the host's policy rather than the look, so no
213
213
  height is stated here. */
214
214
  pre.qm-readout {
@@ -253,10 +253,12 @@ pre.qm-readout {
253
253
 
254
254
  /* ── Surfaces ──────────────────────────────────────────────────────────────── */
255
255
 
256
- /* The instrument plate: what a host puts its controls and readouts on. One rung off the
257
- page and a hairline, which is the same way a card steps off the base surface, so a
258
- panel beside a mounted editor reads as the same material. `border-box`, so a height
259
- from the caller is the height it draws. */
256
+ /* The instrument plate: what a host puts its controls and readouts on. The same plane a
257
+ card is, so a panel beside a mounted editor reads as the same material. It keeps a
258
+ hairline where a card drops one: a card sits in a column the surface itself paints and
259
+ a plate sits wherever the host put it, which is the floating case's argument on a
260
+ block that happens to be in flow. `border-box`, so a height from the caller is the
261
+ height it draws. */
260
262
  .qm-panel {
261
263
  box-sizing: border-box;
262
264
  background: var(--qmh-surface);
@@ -267,7 +269,7 @@ pre.qm-readout {
267
269
 
268
270
  /* ── Controls ──────────────────────────────────────────────────────────────── */
269
271
 
270
- /* A host's controls ARE boxed, where the package's buttons are not: inside a card a
272
+ /* A host's controls are boxed, where the package's buttons are not: inside a card a
271
273
  button sits beside typing and a box would read as a field, and out here there is no
272
274
  typing to be confused with, so the box is what says "this is a control".
273
275
  `font: inherit` first, since the shorthand resets whatever precedes it. */
@@ -309,7 +311,7 @@ pre.qm-readout {
309
311
  /* ── Focus ─────────────────────────────────────────────────────────────────── */
310
312
 
311
313
  /* One visible indicator for the whole host, since none of these controls draws a ring
312
- of its own. It reads the INK rung rather than a hue: the page is monochrome, and a
314
+ of its own. It reads the ink rung rather than a hue: the page is monochrome, and a
313
315
  focus ring is a position, not a destination. */
314
316
  :focus-visible {
315
317
  outline: var(--qmh-ring-width) solid var(--qmh-ink);