@jelinek/ui 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +492 -0
- package/dist/components/Alert.svelte +59 -0
- package/dist/components/Alert.svelte.d.ts +13 -0
- package/dist/components/Button.svelte +178 -0
- package/dist/components/Button.svelte.d.ts +19 -0
- package/dist/components/Card.svelte +68 -0
- package/dist/components/Card.svelte.d.ts +11 -0
- package/dist/components/ChapterNav.svelte +290 -0
- package/dist/components/ChapterNav.svelte.d.ts +18 -0
- package/dist/components/Checkbox.svelte +52 -0
- package/dist/components/Checkbox.svelte.d.ts +11 -0
- package/dist/components/CodeCopy.svelte +294 -0
- package/dist/components/CodeCopy.svelte.d.ts +51 -0
- package/dist/components/Container.svelte +34 -0
- package/dist/components/Container.svelte.d.ts +10 -0
- package/dist/components/ContentLogo.svelte +151 -0
- package/dist/components/ContentLogo.svelte.d.ts +37 -0
- package/dist/components/Demo.svelte +111 -0
- package/dist/components/Demo.svelte.d.ts +12 -0
- package/dist/components/Eyebrow.svelte +70 -0
- package/dist/components/Eyebrow.svelte.d.ts +12 -0
- package/dist/components/Glass.svelte +75 -0
- package/dist/components/Glass.svelte.d.ts +10 -0
- package/dist/components/Grid.svelte +87 -0
- package/dist/components/Grid.svelte.d.ts +11 -0
- package/dist/components/Label.svelte +37 -0
- package/dist/components/Label.svelte.d.ts +11 -0
- package/dist/components/PageHero.svelte +312 -0
- package/dist/components/PageHero.svelte.d.ts +55 -0
- package/dist/components/Pager.svelte +98 -0
- package/dist/components/Pager.svelte.d.ts +13 -0
- package/dist/components/Panel.svelte +89 -0
- package/dist/components/Panel.svelte.d.ts +12 -0
- package/dist/components/ProductCard.svelte +81 -0
- package/dist/components/ProductCard.svelte.d.ts +18 -0
- package/dist/components/Radio.svelte +54 -0
- package/dist/components/Radio.svelte.d.ts +11 -0
- package/dist/components/RadioGroup.svelte +42 -0
- package/dist/components/RadioGroup.svelte.d.ts +12 -0
- package/dist/components/Select.svelte +65 -0
- package/dist/components/Select.svelte.d.ts +20 -0
- package/dist/components/SiteFooter.svelte +121 -0
- package/dist/components/SiteFooter.svelte.d.ts +13 -0
- package/dist/components/SiteHeader.svelte +613 -0
- package/dist/components/SiteHeader.svelte.d.ts +80 -0
- package/dist/components/Slider.svelte +55 -0
- package/dist/components/Slider.svelte.d.ts +14 -0
- package/dist/components/Swatch.svelte +174 -0
- package/dist/components/Swatch.svelte.d.ts +58 -0
- package/dist/components/Tab.svelte +88 -0
- package/dist/components/Tab.svelte.d.ts +11 -0
- package/dist/components/Tabs.svelte +306 -0
- package/dist/components/Tabs.svelte.d.ts +20 -0
- package/dist/components/Tag.svelte +71 -0
- package/dist/components/Tag.svelte.d.ts +16 -0
- package/dist/components/TextField.svelte +100 -0
- package/dist/components/TextField.svelte.d.ts +18 -0
- package/dist/components/ThemeToggle.svelte +122 -0
- package/dist/components/ThemeToggle.svelte.d.ts +11 -0
- package/dist/components/Tile.svelte +115 -0
- package/dist/components/Tile.svelte.d.ts +14 -0
- package/dist/components/TileScroller.svelte +199 -0
- package/dist/components/TileScroller.svelte.d.ts +25 -0
- package/dist/components/container-context.d.ts +1 -0
- package/dist/components/container-context.js +6 -0
- package/dist/components/deer-mark-path.d.ts +16 -0
- package/dist/components/deer-mark-path.js +16 -0
- package/dist/components/nav.d.ts +25 -0
- package/dist/components/nav.js +17 -0
- package/dist/components/radio-context.d.ts +6 -0
- package/dist/components/radio-context.js +1 -0
- package/dist/components/tabs-context.d.ts +5 -0
- package/dist/components/tabs-context.js +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.js +37 -0
- package/dist/theme/base.css +439 -0
- package/dist/theme/extras.css +2 -0
- package/dist/theme/fonts.css +107 -0
- package/dist/theme/tokens.css +208 -0
- package/dist/utils/chapter-nav-dock.svelte.d.ts +23 -0
- package/dist/utils/chapter-nav-dock.svelte.js +65 -0
- package/dist/utils/cn.d.ts +2 -0
- package/dist/utils/cn.js +27 -0
- package/package.json +79 -0
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
/* Optional, but recommended. Reproduces the brand guide's global element
|
|
2
|
+
styles (assets/css/jelinek.css:274-339) — the layer between raw tokens
|
|
3
|
+
(theme.css) and components: headings, body copy, links, and a handful of
|
|
4
|
+
text-role utility classes. Without this file, a consuming app gets
|
|
5
|
+
JELÍNEK colours and components but plain markup (a bare <h2>, a <p>, an
|
|
6
|
+
<a>) that still looks generic, because nothing in theme.css touches
|
|
7
|
+
element defaults — it only defines custom properties and the Tailwind
|
|
8
|
+
`@theme inline` mapping.
|
|
9
|
+
|
|
10
|
+
Import after `tailwindcss` (see README for the exact order). The rules
|
|
11
|
+
below live in `@layer base` — the same cascade layer Tailwind's own
|
|
12
|
+
preflight populates — which matters for two reasons:
|
|
13
|
+
- Tailwind's preflight resets h1-h6 to `font-size: inherit; font-weight:
|
|
14
|
+
inherit`. Since this file is imported after `tailwindcss`, its
|
|
15
|
+
`@layer base` content is appended later in that layer's rule list;
|
|
16
|
+
for the equal-specificity type selectors here (h1, body, p, a…),
|
|
17
|
+
later wins, so these rules override preflight's reset.
|
|
18
|
+
- Every Tailwind utility class (`text-step2`, `font-bold`, a component's
|
|
19
|
+
own `[&_h3]:...` arbitrary variant, …) still wins over anything here,
|
|
20
|
+
unconditionally — `utilities` is a CSS layer declared after `base`,
|
|
21
|
+
and layer order beats specificity regardless of selector shape.
|
|
22
|
+
Verified from compiled output, not assumed: dumping the built CSS shows
|
|
23
|
+
`@layer base` here ordered after Tailwind's own preflight `@layer base`
|
|
24
|
+
content, and a plain `<h2 class="text-step0">` renders at --step0's size,
|
|
25
|
+
not h2's own --step5.
|
|
26
|
+
|
|
27
|
+
Page scaffolding IS reproduced here (revised from Task 17 — see below):
|
|
28
|
+
`html { height: 100% }` + `body { margin: 0; min-height: 100%; display:
|
|
29
|
+
flex; flex-direction: column }` + `main { flex: 1 0 auto }`
|
|
30
|
+
(jelinek.css:295-316) is the guide's sticky-footer trick, holding the
|
|
31
|
+
footer to the bottom of the viewport on short pages instead of leaving a
|
|
32
|
+
white gap below it. Task 17 excluded this as "page-scaffolding specific
|
|
33
|
+
to the guide site's own shell, not to a generic consuming app's page"
|
|
34
|
+
and backed that with a Playwright pass that only ever visited two long,
|
|
35
|
+
scroll-filling showcase pages — it never actually exercised the short
|
|
36
|
+
one (`src/routes/+page.svelte`), which is exactly the case this rule
|
|
37
|
+
exists for, and which is where a real visible regression (black footer
|
|
38
|
+
band ending mid-page, white canvas continuing below it) then showed up.
|
|
39
|
+
The package-level concern from Task 17 still stands and is answered by
|
|
40
|
+
documentation instead of omission: importing base.css means opting into
|
|
41
|
+
a page shell of header / one `<main>` / footer, each a direct flex
|
|
42
|
+
child of `<body>` — see svelte/README.md's base.css section for the
|
|
43
|
+
consumer-facing version of this note, including how to opt out (skip
|
|
44
|
+
this file, or override `body` after importing it) without losing
|
|
45
|
+
everything else base.css provides.
|
|
46
|
+
`body { margin: 0 }` (jelinek.css:303) is also newly included here —
|
|
47
|
+
previously dropped from both the Included and the Deliberately-excluded
|
|
48
|
+
lists in Task 17, an accidental gap rather than a considered exclusion.
|
|
49
|
+
Tailwind's own preflight already zeroes body's margin in the same layer,
|
|
50
|
+
which is exactly why the gap was invisible until now: a consumer who
|
|
51
|
+
imports base.css WITHOUT Tailwind preflight (or without Tailwind at all)
|
|
52
|
+
would have kept the browser's default body margin with no indication
|
|
53
|
+
anything was missing.
|
|
54
|
+
|
|
55
|
+
Task 20 audited the guide's whole "3) ZÁKLAD" section
|
|
56
|
+
(jelinek.css:274-339 as the section now numbers — from the section
|
|
57
|
+
heading down to the .container rule immediately before "4) TYPOGRAFIE"
|
|
58
|
+
begins) rule by rule, starting
|
|
59
|
+
from the guide rather than from this file, specifically because walking
|
|
60
|
+
this file only ever confirms what's already here and would never have
|
|
61
|
+
caught the previous two gaps (this file's own missing `body { margin: 0
|
|
62
|
+
}`, then `html`'s missing font-size/background-color) either. Three more
|
|
63
|
+
gaps were found and closed:
|
|
64
|
+
- `* { box-sizing: border-box }` (jelinek.css:277) — the identical
|
|
65
|
+
situation as `body { margin: 0 }` above: Tailwind's preflight
|
|
66
|
+
already sets this, in the same @layer base, so the gap was invisible
|
|
67
|
+
with preflight and real without it. Included, same resolution.
|
|
68
|
+
- `html`'s root `font-size` (jelinek.css:296). Every --stepN token
|
|
69
|
+
(tokens.css) is rem-based off this root, so it is a substantive
|
|
70
|
+
reproduction, not a cosmetic one. Task 20 added it as the guide's
|
|
71
|
+
then-current `clamp(13px, 8px + 1.4vw, 16px)`; Task 25 replaced that
|
|
72
|
+
in the guide with a flat `16px` and moved the fluidity onto the
|
|
73
|
+
individual step clamps, and this file follows. Included — see the
|
|
74
|
+
`html` rule's own comment below.
|
|
75
|
+
- `body`'s `transition` on background-color/color (jelinek.css:314) —
|
|
76
|
+
excluded twice before (Task 17, Task 18) as
|
|
77
|
+
cosmetic and tied to the guide's own ThemeToggle interaction.
|
|
78
|
+
Revisited per the Task 20 brief: the kit ships `ThemeToggle.svelte`,
|
|
79
|
+
so the theme DOES change at runtime in any consuming app that uses
|
|
80
|
+
it — exactly the condition that makes this transition meaningful
|
|
81
|
+
rather than decorative. Included.
|
|
82
|
+
`html`'s `background-color: var(--bg-white)` (jelinek.css:300) was also
|
|
83
|
+
added; see the `html` rule's own comment for why only the static default
|
|
84
|
+
belongs here, not the scroll-driven swap.
|
|
85
|
+
|
|
86
|
+
After Task 20, the "Still deliberately NOT reproduced" list immediately
|
|
87
|
+
below is exhaustive for the guide's ZÁKLAD section: every declaration in
|
|
88
|
+
jelinek.css:274-339 is now either reproduced in the @layer base block
|
|
89
|
+
further down, or named in that list with its reasoning. This is a
|
|
90
|
+
standing invariant, not a one-time snapshot — if the guide's ZÁKLAD
|
|
91
|
+
section changes, re-run this same audit rather than trusting this file's
|
|
92
|
+
own contents.
|
|
93
|
+
|
|
94
|
+
TASK 31 RE-RAN THAT AUDIT against the merged guide, which is what the
|
|
95
|
+
invariant above asks for, and it earned its keep: the section gained one
|
|
96
|
+
whole new rule that NOTHING in the kit was reviewing.
|
|
97
|
+
|
|
98
|
+
- `body`'s transition is now written in tokens —
|
|
99
|
+
`background-color var(--dur-slow) var(--ease), color var(--dur-slow)
|
|
100
|
+
var(--ease)` (jelinek.css:314) instead of the literal `0.2s ease`.
|
|
101
|
+
Same computed value today (--dur-slow IS 0.2s, --ease IS `ease`), but
|
|
102
|
+
reproduced as the token reference so a retune of --dur-slow follows
|
|
103
|
+
through instead of silently diverging. Updated below.
|
|
104
|
+
- `:where(a, button, input, select, textarea, summary,
|
|
105
|
+
[tabindex]):focus-visible { outline: var(--focus-width) solid
|
|
106
|
+
var(--focus-color); outline-offset: var(--focus-offset) }`
|
|
107
|
+
(jelinek.css:327-330) — NEW in the merge, and a genuine accessibility
|
|
108
|
+
default: a visible keyboard focus ring on every interactive element,
|
|
109
|
+
in the brand's own brown, lightening to --JELINEK-BROWN-HIGHLIGHT in
|
|
110
|
+
dark mode (tokens.css's --focus-color). Reproduced below. `:where()`
|
|
111
|
+
has zero specificity, so it can never fight a component's own
|
|
112
|
+
`focus-visible:` utilities or a consumer's override — which is
|
|
113
|
+
exactly why it is safe to ship globally, and the guide says so itself
|
|
114
|
+
in its own comment above the rule.
|
|
115
|
+
|
|
116
|
+
WARNING, and the reason this rule is worth a paragraph rather than a
|
|
117
|
+
line: `check-css-lock.js` CANNOT SEE IT. `groupsOf()` splits on
|
|
118
|
+
top-level commas only, so this selector is ONE part; that part has no
|
|
119
|
+
class token, so it falls through to the GUARDED_ELEMENTS branch,
|
|
120
|
+
whose leading-token regex (`^(\*|[a-z][a-z0-9]*)`) fails on a
|
|
121
|
+
selector starting with `:`. The rule therefore lands in no bucket at
|
|
122
|
+
all and the checker reported "no drift" for it — the documented
|
|
123
|
+
"brand-new bare type selector" blind spot in that file's own header
|
|
124
|
+
comment, hit for real. Reproducing it here closes the visual gap but
|
|
125
|
+
NOT the guard gap: future edits to the guide's focus ring will not
|
|
126
|
+
fail any gate. Closing it properly means teaching groupsOf() to scan
|
|
127
|
+
INSIDE `:is()`/`:where()` argument lists for bare element tokens —
|
|
128
|
+
but only when the part has no class anywhere, otherwise
|
|
129
|
+
`:is(h1,h2,h3):has(+ .rule)` (jelinek.css:407-414) would start
|
|
130
|
+
mis-attributing to the h1/h2/h3 buckets, which is the exact false
|
|
131
|
+
positive topLevelParts() was written to prevent. That is a change to
|
|
132
|
+
the lock tool with its own test surface, deliberately left out of
|
|
133
|
+
Task 31 and named in its report instead.
|
|
134
|
+
|
|
135
|
+
Still deliberately NOT reproduced from the ZÁKLAD section
|
|
136
|
+
(jelinek.css:274-339):
|
|
137
|
+
- `scroll-behavior: smooth` on `html` (jelinek.css:296) — a global
|
|
138
|
+
scroll *behaviour*, not a visual default, and not load-bearing for
|
|
139
|
+
anything the guide itself does: its own chapter navigation
|
|
140
|
+
(ChapterNav/Pager) is cross-page links to different documents, not
|
|
141
|
+
in-page anchors, and grepping brand/*.html and ui/*.html turns up no
|
|
142
|
+
in-page-anchor pattern that depends on it either. Forcing it
|
|
143
|
+
globally on a consuming app's `<html>` is a bigger commitment than
|
|
144
|
+
it looks: it can fight an app's own scroll management (virtualised
|
|
145
|
+
lists, scroll-linked animation, router-driven scroll restoration),
|
|
146
|
+
and the guide doesn't gate it behind `prefers-reduced-motion` (no
|
|
147
|
+
such media query exists anywhere in jelinek.css or jelinek.js), so
|
|
148
|
+
reproducing it here would also reproduce that accessibility gap for
|
|
149
|
+
every consumer. Trivial to opt into if wanted:
|
|
150
|
+
`html { scroll-behavior: smooth }` in the consumer's own CSS, after
|
|
151
|
+
this import.
|
|
152
|
+
- `.container` (jelinek.css:339: `width: 100%; max-width:
|
|
153
|
+
var(--page-max); margin: 0 auto; padding: 0 24px`) — not silently
|
|
154
|
+
dropped, reproduced instead as a component: `Container.svelte`
|
|
155
|
+
applies the equivalent Tailwind utilities (`mx-auto w-full
|
|
156
|
+
max-w-page px-6`) on its own root element (see that file's own
|
|
157
|
+
comment for the value-by-value mapping, including why no
|
|
158
|
+
my-0/py-0 is needed). Not duplicated here as a global class rule for
|
|
159
|
+
the same reason the font-role classes below aren't: it would collide
|
|
160
|
+
with any consumer app that reuses the class name `.container` for
|
|
161
|
+
something unrelated of its own.
|
|
162
|
+
|
|
163
|
+
Still deliberately NOT reproduced from the TYPOGRAFIE section
|
|
164
|
+
(jelinek.css:344-391) — out of Task 20's audit scope (that task covered
|
|
165
|
+
ZÁKLAD only), noted here because it predates Task 20 and the reasoning is
|
|
166
|
+
the same shape: component-specific font-role switching (.card, .panel,
|
|
167
|
+
.tile, .demo, .swatch on font-secondary/Light; .eyebrow; the
|
|
168
|
+
site-header/chapter-nav/pager font-secondary swaps) is also NOT
|
|
169
|
+
reproduced: every component that needs one of these already carries the
|
|
170
|
+
equivalent Tailwind utility classes on its own root element (see e.g.
|
|
171
|
+
Tile.svelte's BASE constant reproducing jelinek.css:382-385 and :337
|
|
172
|
+
directly), so duplicating the underlying element/class rule here would be
|
|
173
|
+
redundant — and, being global, would actively fight component internals
|
|
174
|
+
for any plain (non-component) markup a consumer writes with those same
|
|
175
|
+
class names for unrelated reasons. */
|
|
176
|
+
|
|
177
|
+
@layer base {
|
|
178
|
+
/* jelinek.css:277. Tailwind's preflight already sets this identically
|
|
179
|
+
(`*, ::before, ::after, ::backdrop, ::file-selector-button {
|
|
180
|
+
box-sizing: border-box; ... }`, verified in
|
|
181
|
+
node_modules/tailwindcss/preflight.css) in this same @layer base —
|
|
182
|
+
the same situation as body's margin below: invisible with preflight,
|
|
183
|
+
real without it (or without Tailwind at all). Included. */
|
|
184
|
+
* {
|
|
185
|
+
box-sizing: border-box;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/* jelinek.css:295-301. `height: 100%` is required for body's
|
|
189
|
+
`min-height: 100%` below to mean anything at all: a percentage height
|
|
190
|
+
on a non-root element resolves against its containing block's height,
|
|
191
|
+
and the root element's own height is otherwise 'auto' (sized to
|
|
192
|
+
content) — `html { height: 100% }` is what gives `<html>` a used
|
|
193
|
+
height (the viewport, via the CSS root-element special case) for
|
|
194
|
+
`<body>` to then take 100% of.
|
|
195
|
+
`font-size` is the guide's root size (see the file header comment above
|
|
196
|
+
for the full rationale) — the one property in this rule that's
|
|
197
|
+
substantive rather than cosmetic, since every --stepN TYPE token is
|
|
198
|
+
rem-based off it. It is a flat 16px as of Task 25, NOT the
|
|
199
|
+
`clamp(13px, 8px + 1.4vw, 16px)` this file carried before: that clamp
|
|
200
|
+
made the root — and with it every rem in the system — shrink to 13px on
|
|
201
|
+
the narrowest phones. The guide states the intent itself, above its own
|
|
202
|
+
`html` rule at jelinek.css:278-282: "Základ škály = 16px na každé šířce
|
|
203
|
+
okna… Velikosti teď mění jednotlivé stupně škály (--step1…--step6), ne
|
|
204
|
+
kořen; tělo textu proto zůstává 16px všude." The fluidity did not
|
|
205
|
+
disappear, it moved: each --stepN is now its own clamp() interpolating
|
|
206
|
+
over 320-1024px viewport width (tokens.css), so headings still grow with
|
|
207
|
+
the viewport while body copy no longer shrinks with it. Guide SPACING
|
|
208
|
+
deliberately does not move with this root either way; that's theme.css's
|
|
209
|
+
`--spacing: 4px` pin (gen-tokens.js), a separate fix, not this file's
|
|
210
|
+
concern.
|
|
211
|
+
`background-color` is the static canvas colour revealed by elastic
|
|
212
|
+
overscroll (Safari's rubber-band past the top/bottom of the page).
|
|
213
|
+
The guide swaps this by scroll position at runtime via a `<script>`
|
|
214
|
+
in assets/js/jelinek.js (page colour at the top, black to match the
|
|
215
|
+
footer at the bottom) — that JS behaviour is out of scope for a
|
|
216
|
+
CSS-only kit, but the static default it starts from is a real visual
|
|
217
|
+
default worth keeping on its own.
|
|
218
|
+
`scroll-behavior: smooth` is deliberately NOT included here — see the
|
|
219
|
+
file header comment above for why. */
|
|
220
|
+
html {
|
|
221
|
+
font-size: 16px;
|
|
222
|
+
height: 100%;
|
|
223
|
+
background-color: var(--bg-white);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/* jelinek.css:302-315. `min-height: 100%` + the flex column is the
|
|
227
|
+
sticky-footer trick: SiteHeader/ChapterNav/main/SiteFooter, each a
|
|
228
|
+
direct flex child of body, stretch to fill at least the viewport
|
|
229
|
+
height so the footer never ends before the bottom of a short page.
|
|
230
|
+
`transition` is included as of Task 20 — see the file header comment
|
|
231
|
+
above for why the earlier "cosmetic, tied to the guide's own
|
|
232
|
+
ThemeToggle" exclusion no longer holds now that the kit ships that
|
|
233
|
+
same component. */
|
|
234
|
+
body {
|
|
235
|
+
margin: 0;
|
|
236
|
+
min-height: 100%;
|
|
237
|
+
display: flex;
|
|
238
|
+
flex-direction: column;
|
|
239
|
+
background: var(--bg-white);
|
|
240
|
+
color: var(--text-black);
|
|
241
|
+
font-family: var(--font-serif); /* Archer Book — paragraphs and body text */
|
|
242
|
+
font-weight: 400;
|
|
243
|
+
font-size: 1rem;
|
|
244
|
+
line-height: 1.6;
|
|
245
|
+
-webkit-font-smoothing: antialiased;
|
|
246
|
+
/* Token references, not the literal `0.2s ease` this used to carry —
|
|
247
|
+
the guide moved its own durations onto --dur-fast/base/slow + --ease
|
|
248
|
+
in the Task 31 merge (jelinek.css:126-130). Identical computed value
|
|
249
|
+
today; the point is that a retune of --dur-slow reaches this rule
|
|
250
|
+
instead of leaving it behind. */
|
|
251
|
+
transition:
|
|
252
|
+
background-color var(--dur-slow) var(--ease),
|
|
253
|
+
color var(--dur-slow) var(--ease);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/* jelinek.css:316. The one flex child that should actually grow — header,
|
|
257
|
+
chapter-nav and footer keep their natural (content) height; whatever
|
|
258
|
+
space is left over goes to <main>, pushing the footer down to the
|
|
259
|
+
bottom of the viewport on short pages instead of leaving it stranded
|
|
260
|
+
right after the content. */
|
|
261
|
+
main {
|
|
262
|
+
flex: 1 0 auto;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/* Headings — modular scale (see --stepN in theme.css); only size/line-height
|
|
266
|
+
change per level, the typeface (GT Walsheim Bold) stays constant. */
|
|
267
|
+
h1,
|
|
268
|
+
h2,
|
|
269
|
+
h3,
|
|
270
|
+
h4,
|
|
271
|
+
h5,
|
|
272
|
+
h6 {
|
|
273
|
+
font-family: var(--font-primary);
|
|
274
|
+
font-weight: 700;
|
|
275
|
+
margin: 0 0 0.4em;
|
|
276
|
+
}
|
|
277
|
+
h1 {
|
|
278
|
+
font-size: var(--step6);
|
|
279
|
+
line-height: 1.1;
|
|
280
|
+
letter-spacing: -0.01em;
|
|
281
|
+
}
|
|
282
|
+
h2 {
|
|
283
|
+
font-size: var(--step5);
|
|
284
|
+
line-height: 1.1;
|
|
285
|
+
}
|
|
286
|
+
h3 {
|
|
287
|
+
font-size: var(--step4);
|
|
288
|
+
line-height: 1.2;
|
|
289
|
+
}
|
|
290
|
+
h4 {
|
|
291
|
+
font-size: var(--step3);
|
|
292
|
+
line-height: 1.2;
|
|
293
|
+
}
|
|
294
|
+
h5 {
|
|
295
|
+
font-size: var(--step2);
|
|
296
|
+
line-height: 1.3;
|
|
297
|
+
}
|
|
298
|
+
h6 {
|
|
299
|
+
font-size: var(--step1);
|
|
300
|
+
line-height: 1.3;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
p {
|
|
304
|
+
font-size: var(--step0);
|
|
305
|
+
line-height: 1.4;
|
|
306
|
+
margin: 0 0 1em;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/* Links are always bold — in text and as a button (see Button.svelte). */
|
|
310
|
+
a {
|
|
311
|
+
color: var(--JELINEK-BROWN);
|
|
312
|
+
text-decoration: none;
|
|
313
|
+
font-weight: 700;
|
|
314
|
+
}
|
|
315
|
+
a:hover {
|
|
316
|
+
text-decoration: underline;
|
|
317
|
+
}
|
|
318
|
+
/* "Block" links (tiles, pagers) keep the surrounding content's normal
|
|
319
|
+
weight — their own headings/<strong> carry the bold, not the whole link. */
|
|
320
|
+
.tile,
|
|
321
|
+
.pager a {
|
|
322
|
+
font-weight: 400;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
img {
|
|
326
|
+
max-width: 100%;
|
|
327
|
+
display: block;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/* Inline unformatted text — small monospace in a dashed grey box.
|
|
331
|
+
|
|
332
|
+
Task 33 — THE COLOUR IS A TOKEN NOW, and darker. The designer's b45c536
|
|
333
|
+
replaced the hardcoded `#ccc` on both the text and the dashed border with
|
|
334
|
+
`var(--text-muted2)`. That is a real value change, not the notation sweep
|
|
335
|
+
the rest of that commit is: #ccc is hsl(0,0%,80%), --text-muted2 is
|
|
336
|
+
hsl(0,0%,62%) in light mode — noticeably darker and a real contrast
|
|
337
|
+
improvement — and it now flips in dark mode (hsl(0,0%,38%)), which #ccc
|
|
338
|
+
never did. Written as the mapped Tailwind token here (--color-fg-muted2 is
|
|
339
|
+
`var(--text-muted2)` via @theme inline) so the flip is inherited rather
|
|
340
|
+
than frozen. */
|
|
341
|
+
code {
|
|
342
|
+
font-family: ui-monospace, Menlo, Consolas, monospace;
|
|
343
|
+
font-size: 12px;
|
|
344
|
+
color: var(--color-fg-muted2);
|
|
345
|
+
border: 1px dashed var(--color-fg-muted2);
|
|
346
|
+
border-radius: 4px;
|
|
347
|
+
padding: 1px 6px;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/* jelinek.css:325-330 — the global keyboard focus ring, NEW in the Task 31
|
|
351
|
+
merge. `:focus-visible`, not `:focus`, so a mouse click does not draw it;
|
|
352
|
+
`:where()` keeps the whole selector at ZERO specificity, so any component
|
|
353
|
+
in this kit (and any consumer rule) overrides it with a plain class —
|
|
354
|
+
which is what makes shipping it globally safe rather than presumptuous.
|
|
355
|
+
--focus-color is --JELINEK-BROWN in light and the lighter
|
|
356
|
+
--JELINEK-BROWN-HIGHLIGHT in dark (tokens.css), so the ring stays visible
|
|
357
|
+
against both canvases without a dark: variant here.
|
|
358
|
+
Kept as a raw rule rather than Tailwind utilities for the same reason as
|
|
359
|
+
everything else in this file: there is no element to hang a class on. See
|
|
360
|
+
the file header for why check-css-lock.js cannot guard this rule, and
|
|
361
|
+
what closing that would take. */
|
|
362
|
+
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
|
|
363
|
+
outline: var(--focus-width) solid var(--focus-color);
|
|
364
|
+
outline-offset: var(--focus-offset);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
.muted {
|
|
368
|
+
color: var(--text-muted1);
|
|
369
|
+
}
|
|
370
|
+
.muted2 {
|
|
371
|
+
color: var(--text-muted2);
|
|
372
|
+
}
|
|
373
|
+
.serif {
|
|
374
|
+
font-family: var(--font-serif);
|
|
375
|
+
}
|
|
376
|
+
.small {
|
|
377
|
+
font-size: var(--step-down1);
|
|
378
|
+
line-height: 1.1;
|
|
379
|
+
font-weight: 300;
|
|
380
|
+
}
|
|
381
|
+
.tiny {
|
|
382
|
+
font-size: var(--step-down2);
|
|
383
|
+
line-height: 1.1;
|
|
384
|
+
}
|
|
385
|
+
.sub {
|
|
386
|
+
font-size: var(--step2);
|
|
387
|
+
line-height: 1.3;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/* Task 38 — THE HEADING UNDERLINE, jelinek.css:415-425 verbatim.
|
|
391
|
+
The guide's pattern is literal markup: a heading followed by
|
|
392
|
+
`<hr class="rule">`. The hr itself is display:none — it exists only so
|
|
393
|
+
`:has(+ .rule)` can see it — and the visible bar is the heading's own
|
|
394
|
+
::after, 3px tall and 75% of the heading's FITTED width (width:
|
|
395
|
+
fit-content is what makes 75% mean "of the text", not "of the page").
|
|
396
|
+
Colour variants ride on the hr's class, default follows the division
|
|
397
|
+
through --JELINEK-BROWN.
|
|
398
|
+
|
|
399
|
+
Until now only PageHero carried this (as Tailwind classes on its own
|
|
400
|
+
heading), so a chapter page could not underline its section <h2>s the
|
|
401
|
+
way every hand-written page does — the pattern the guide uses most was
|
|
402
|
+
the one thing base.css didn't reproduce. PageHero keeps its own copy on
|
|
403
|
+
purpose (it must not depend on this optional stylesheet); these rules
|
|
404
|
+
are for page content written in the guide's own markup.
|
|
405
|
+
|
|
406
|
+
The margin shorthand is the guide's: 16px above the bar, 24px below
|
|
407
|
+
(var(--space-2) / var(--space-3)). `:has(+ .rule)` also zeroes the
|
|
408
|
+
heading's own margin-bottom, so the bar's margins are the only spacing
|
|
409
|
+
in play. */
|
|
410
|
+
.rule,
|
|
411
|
+
.rule--magenta,
|
|
412
|
+
.rule--black,
|
|
413
|
+
.rule--white {
|
|
414
|
+
display: none;
|
|
415
|
+
}
|
|
416
|
+
:is(h1, h2, h3):has(+ .rule) {
|
|
417
|
+
width: fit-content;
|
|
418
|
+
max-width: 100%;
|
|
419
|
+
margin-bottom: 0;
|
|
420
|
+
}
|
|
421
|
+
:is(h1, h2, h3):has(+ .rule)::after {
|
|
422
|
+
content: '';
|
|
423
|
+
display: block;
|
|
424
|
+
height: 3px;
|
|
425
|
+
width: 75%;
|
|
426
|
+
border-radius: 2px;
|
|
427
|
+
margin: var(--space-2) 0 var(--space-3);
|
|
428
|
+
background: var(--JELINEK-BROWN);
|
|
429
|
+
}
|
|
430
|
+
:is(h1, h2, h3):has(+ .rule--magenta)::after {
|
|
431
|
+
background: var(--JELINEK-MAGENTA);
|
|
432
|
+
}
|
|
433
|
+
:is(h1, h2, h3):has(+ .rule--black)::after {
|
|
434
|
+
background: var(--JELINEK-BLACK);
|
|
435
|
+
}
|
|
436
|
+
:is(h1, h2, h3):has(+ .rule--white)::after {
|
|
437
|
+
background: var(--text-white);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/* Optional. Assumes the .woff2 files are served from /assets/fonts/ — the
|
|
2
|
+
same absolute path the brand guide itself uses (assets/fonts/*.woff2 at
|
|
3
|
+
the repo root). That is not a coincidence: when this showcase is deployed
|
|
4
|
+
behind the `brand` Worker at /ui/, /assets/fonts/... already
|
|
5
|
+
resolves on the same origin for free (wrangler.jsonc serves the whole
|
|
6
|
+
repo root as static assets), so this file needs no change to work there.
|
|
7
|
+
For standalone `pnpm dev` / `vite preview`, vite.config.ts adds a small
|
|
8
|
+
dev-only middleware that serves the same /assets/fonts/* path straight
|
|
9
|
+
from the repo root's assets/fonts/ — see that file's comment for why a
|
|
10
|
+
static/ copy or symlink can't do this (this project's `paths.base:
|
|
11
|
+
'/ui'` prefixes everything under static/, including symlinks, so it
|
|
12
|
+
can never be reached at the unprefixed path fonts.css actually requests).
|
|
13
|
+
Either way the licensed files themselves are never copied into svelte/.
|
|
14
|
+
Apps that host fonts elsewhere skip this import and declare their own
|
|
15
|
+
@font-face — the kit only relies on --font-primary/--font-secondary/
|
|
16
|
+
--font-serif, which all have fallbacks.
|
|
17
|
+
|
|
18
|
+
font-display: block, matching jelinek.css (the designer flagged swap's
|
|
19
|
+
visible fallback flash on load; block hides the text for the few ms the
|
|
20
|
+
same-origin files take instead of flashing Arial/Georgia).
|
|
21
|
+
|
|
22
|
+
Reconciled against assets/css/jelinek.css's @font-face block (the
|
|
23
|
+
authority for which faces exist): every face declared there is declared
|
|
24
|
+
here too, with the same family name, weight and filename. That now
|
|
25
|
+
includes Archer Medium (500) — the file had been in assets/fonts/ and in
|
|
26
|
+
its README since 03ee9de, but with no @font-face anywhere, so any request
|
|
27
|
+
for a 500-weight Archer silently fell back to Book. Declaring it makes
|
|
28
|
+
the README true and gives the designer the option of Medium emphasis in
|
|
29
|
+
prose; nothing requests it yet (prose <strong> is plain Bold, his
|
|
30
|
+
7cd378c). */
|
|
31
|
+
@font-face {
|
|
32
|
+
font-family: 'GT Walsheim Pro';
|
|
33
|
+
src: url('/assets/fonts/GT-Walsheim-Pro-Light.woff2') format('woff2');
|
|
34
|
+
font-weight: 300;
|
|
35
|
+
font-style: normal;
|
|
36
|
+
font-display: block;
|
|
37
|
+
}
|
|
38
|
+
@font-face {
|
|
39
|
+
font-family: 'GT Walsheim Pro';
|
|
40
|
+
src: url('/assets/fonts/GT-Walsheim-Pro-Regular.woff2') format('woff2');
|
|
41
|
+
font-weight: 400;
|
|
42
|
+
font-style: normal;
|
|
43
|
+
font-display: block;
|
|
44
|
+
}
|
|
45
|
+
@font-face {
|
|
46
|
+
font-family: 'GT Walsheim Pro';
|
|
47
|
+
src: url('/assets/fonts/GT-Walsheim-Pro-Medium.woff2') format('woff2');
|
|
48
|
+
font-weight: 500;
|
|
49
|
+
font-style: normal;
|
|
50
|
+
font-display: block;
|
|
51
|
+
}
|
|
52
|
+
@font-face {
|
|
53
|
+
font-family: 'GT Walsheim Pro';
|
|
54
|
+
src: url('/assets/fonts/GT-Walsheim-Pro-Bold.woff2') format('woff2');
|
|
55
|
+
font-weight: 700;
|
|
56
|
+
font-style: normal;
|
|
57
|
+
font-display: block;
|
|
58
|
+
}
|
|
59
|
+
@font-face {
|
|
60
|
+
font-family: 'GT Walsheim Pro';
|
|
61
|
+
src: url('/assets/fonts/GT-Walsheim-Pro-Black.woff2') format('woff2');
|
|
62
|
+
font-weight: 900;
|
|
63
|
+
font-style: normal;
|
|
64
|
+
font-display: block;
|
|
65
|
+
}
|
|
66
|
+
@font-face {
|
|
67
|
+
font-family: 'Avenir Next LT Pro';
|
|
68
|
+
src: url('/assets/fonts/AvenirNextLTPro-Regular.woff2') format('woff2');
|
|
69
|
+
font-weight: 400;
|
|
70
|
+
font-style: normal;
|
|
71
|
+
font-display: block;
|
|
72
|
+
}
|
|
73
|
+
@font-face {
|
|
74
|
+
font-family: 'Avenir Next LT Pro';
|
|
75
|
+
src: url('/assets/fonts/AvenirNextLTPro-Demi.woff2') format('woff2');
|
|
76
|
+
font-weight: 600;
|
|
77
|
+
font-style: normal;
|
|
78
|
+
font-display: block;
|
|
79
|
+
}
|
|
80
|
+
@font-face {
|
|
81
|
+
font-family: 'Avenir Next LT Pro';
|
|
82
|
+
src: url('/assets/fonts/AvenirNextLTPro-Bold.woff2') format('woff2');
|
|
83
|
+
font-weight: 700;
|
|
84
|
+
font-style: normal;
|
|
85
|
+
font-display: block;
|
|
86
|
+
}
|
|
87
|
+
@font-face {
|
|
88
|
+
font-family: 'Archer';
|
|
89
|
+
src: url('/assets/fonts/Archer-Book.woff2') format('woff2');
|
|
90
|
+
font-weight: 400;
|
|
91
|
+
font-style: normal;
|
|
92
|
+
font-display: block;
|
|
93
|
+
}
|
|
94
|
+
@font-face {
|
|
95
|
+
font-family: 'Archer';
|
|
96
|
+
src: url('/assets/fonts/Archer-Medium.woff2') format('woff2');
|
|
97
|
+
font-weight: 500;
|
|
98
|
+
font-style: normal;
|
|
99
|
+
font-display: block;
|
|
100
|
+
}
|
|
101
|
+
@font-face {
|
|
102
|
+
font-family: 'Archer';
|
|
103
|
+
src: url('/assets/fonts/Archer-Bold.woff2') format('woff2');
|
|
104
|
+
font-weight: 700;
|
|
105
|
+
font-style: normal;
|
|
106
|
+
font-display: block;
|
|
107
|
+
}
|