rastrillo / fiesta Public

Clone
git clone https://amadan.net/rastrillo/fiesta

Plain git — no account needed to clone.

Download

Download this file

1/* gallery.css: the gallery's own chrome, and nothing an application
2 receives. The section rhythm, the routes, the previous and next
3 pair, the token and icon grids, the rail and its filter, the pinned
4 bar, the phone index and the display settings menu. Every value is a
5 token, so the page's own furniture changes theme with everything
6 else. The preview widget, the code block and the highlight colours
7 are view.css's; the two are served joined as one gallery.css.
8
9 It is Rastrillo's gallery.css for the same chrome, with the scheme
10 toggle's rules gone (Fiesta's scheme control is the system's own
11 dropdown, lifted from the scheme-menu example) and data-gallery-js
12 where Rastrillo's reads data-rst-js: the marker gallery.js sets on
13 <html>, which is the whole of the scriptless story for the filter
14 below. */
15
16.ds-head { border-top: 1px solid var(--rst-line); margin: var(--rst-sp-6) 0 var(--rst-sp-3); padding-top: var(--rst-sp-5); }
17.ds-head h2 { font-size: 1.35rem; letter-spacing: -0.01em; margin: 0; }
18.ds-lead { color: var(--rst-text-muted); margin: 0 0 var(--rst-sp-4); max-width: 62ch; }
19.ds-sub { font-size: var(--rst-fs-base); margin: var(--rst-sp-5) 0 var(--rst-sp-2); }
20/* A heading is one word on the index, the tokens and the icons pages,
21 and a word has to be able to break at 320px: the page may not scroll
22 sideways for anything. */
23[rst-page] h1, [rst-page] h2 { overflow-wrap: anywhere; }
24/* An example page's family, under its heading: the family's name and
25 its sentence, as a kicker back to the page that files it. Then the
26 example's own sentence and the two every example page says. All
27 three read as Rastrillo's page head reads its leads: one size, one
28 colour, one step between them, so the head is a column of sentences
29 rather than three type sizes stacked. */
30.ds-kicker, [rst-page] > [rst-page-header-sub] { color: var(--rst-text-muted); font-size: inherit; margin: 0 0 var(--rst-sp-4); max-width: 62ch; }
31.ds-kicker b { color: var(--rst-text); font-weight: 600; }
32/* One state: a card, its label, the note on it, the widget view.css
33 draws, and the routes it stands for. The label is styled by class,
34 not by level: the outline moved once when the pages got real titles,
35 and a rule keyed to h2 would silently unstyle the label the next
36 time it moves. */
37.ds-sample { background: var(--rst-surface-2); border: 1px solid var(--rst-line); border-radius: var(--rst-radius); margin: var(--rst-sp-3) 0; padding: var(--rst-sp-4); }
38.ds-state { color: var(--rst-text-faint); font-size: var(--rst-fs-xs); font-weight: 650; letter-spacing: 0.06em; margin: 0 0 var(--rst-sp-3); text-transform: uppercase; }
39.ds-note { border-inline-start: 2px solid var(--rst-line-strong); color: var(--rst-text-muted); font-size: var(--rst-fs-sm); margin: var(--rst-sp-3) 0 0; max-width: 62ch; padding-inline-start: var(--rst-sp-3); }
40/* A grouped widget's note names its state on a line of its own, so no
41 joining punctuation has to be written, and translated, between the
42 two. */
43.ds-note__state { display: block; font-weight: 600; }
44.ds-routes-note { color: var(--rst-text-muted); font-size: var(--rst-fs-sm); margin: var(--rst-sp-3) 0 0; max-width: 62ch; }
45/* The Overview's link to the demo is the whole sentence, not a link in
46 running text, so it takes the floor. inline-block, because an inline
47 box's padding is added to its font's content area, not its line, so
48 the same padding came out 28px. */
49.ds-demo > .ds-note > a { display: inline-block; padding-block: max(0px, (var(--rst-target) - 1lh) / 2); }
50/* The token grid, and the icon grid that reuses it: one chip per
51 token, its name and value beside it. The icon sits inside its chip
52 at the 1em tokens.css gives it, which is the size a component draws
53 it at rather than a poster of it. The call under an icon's name is
54 long enough to overrun a 13rem column on a 320px screen, so that is
55 the one place in the grid that breaks inside a word. */
56.ds-toks { display: grid; gap: var(--rst-sp-3); grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr)); list-style: none; margin: 0 0 var(--rst-sp-5); padding: 0; }
57.ds-tok { align-items: center; display: flex; gap: var(--rst-sp-3); min-inline-size: 0; }
58.ds-tok__text { min-inline-size: 0; }
59.ds-tok__name { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
60.ds-tok__value { color: var(--rst-text-muted); display: block; overflow-wrap: anywhere; }
61.ds-chip { background: var(--rst-surface); border: 1px solid var(--rst-line-strong); border-radius: var(--rst-radius-sm); block-size: 2.25rem; flex: none; inline-size: 2.25rem; }
62.ds-chip--fill { background: var(--rst-accent); border-color: var(--rst-accent); }
63.ds-chip--icon { align-items: center; color: var(--rst-text); display: flex; justify-content: center; }
64.ds-bar { background: var(--rst-accent); block-size: 1.25rem; border-radius: 2px; flex: none; }
65.ds-type { display: block; flex: none; inline-size: 3.25rem; line-height: 1.15; text-align: center; }
66.ds-swatch-note { color: var(--rst-text-muted); font-size: var(--rst-fs-sm); margin: 0 0 var(--rst-sp-4); max-width: 62ch; }
67/* The Overview's opening paragraph and the routes under it, which a
68 family page reuses for its examples. .ds-files is the same row, a
69 name, a sentence and a number, on the Getting started page. The
70 paragraph is the one piece of copy on this site somebody wrote by
71 hand rather than derived from the code, so it is set a step larger
72 than body text and given the same 62ch measure everything else here
73 reads at. A route's link takes the target floor like any control. */
74.ds-intro { font-size: 1.05rem; margin: 0 0 var(--rst-sp-5); max-width: 62ch; }
75.ds-routes, .ds-files { display: grid; gap: var(--rst-sp-4); list-style: none; margin: 0 0 var(--rst-sp-5); padding: 0; }
76.ds-routes > li, .ds-files > li { border-inline-start: 2px solid var(--rst-line-strong); padding-inline-start: var(--rst-sp-3); }
77.ds-routes a, .ds-files a { align-items: center; display: inline-flex; font-weight: 600; min-block-size: var(--rst-target); }
78.ds-routes span, .ds-files span { color: var(--rst-text-muted); display: block; font-size: var(--rst-fs-sm); max-width: 62ch; }
79/* Prev/next at the foot. Two grid columns rather than a flex row with
80 space-between, because the ends of the sequence are missing a link
81 and not missing a column: the Overview's Next has to stay on the
82 inline end rather than sliding across to where Previous would have
83 been. */
84.ds-updown { border-block-start: 1px solid var(--rst-line); display: grid; gap: var(--rst-sp-3); grid-template-columns: 1fr 1fr; margin-block-start: var(--rst-sp-6); padding-block-start: var(--rst-sp-4); }
85/* A grid of one so the floor's height centres the text; the links
86 were their 21px line, 24px on a phone. */
87.ds-updown__prev, .ds-updown__next { align-content: center; display: grid; min-block-size: var(--rst-target); }
88.ds-updown__prev { grid-column: 1; justify-self: start; }
89.ds-updown__next { grid-column: 2; justify-self: end; text-align: end; }
90.ds-shell { margin: var(--rst-sp-5) 0; }
91.ds-shell__name { font-size: 1.05rem; margin: 0 0 var(--rst-sp-1); }
92
93/* The rail is the shipped sidebar layout's, below 800px the phone
94 index on the Overview and hidden on every other page, all by
95 tokens.css's own rules. What is left here is what a rail of links
96 has no attribute for: a collapsible section per group, and the
97 filter over them. */
98.ds-rail { gap: var(--rst-sp-2); }
99/* border-box: on the content box the floor came on top of the padding,
100 and the headings grew from 28 to 43px. */
101.ds-nav > details > summary { align-items: center; box-sizing: border-box; color: var(--rst-text-faint); cursor: pointer; display: flex; font-size: var(--rst-fs-xs); font-weight: 650; gap: 0.35rem; letter-spacing: 0.06em; list-style: none; min-block-size: var(--rst-target); padding-block: 0.35rem; text-transform: uppercase; }
102.ds-nav > details > summary::-webkit-details-marker { display: none; }
103/* The disclosure glyph is the icon set's own chevron inside an
104 [rst-caret], which tokens.css already flips 180 degrees on [open]
105 and already stills under prefers-reduced-motion. It is aria-hidden
106 because it sits beside the section's own name. */
107.ds-nav > details > summary > [rst-caret] { flex: none; }
108.ds-nav > details[aria-current] > summary { color: var(--rst-accent); }
109/* A section with nothing to list is a link to its page rather than a
110 disclosure over an empty box. It wears the summary's typography so
111 the rail still reads as one list. */
112.ds-nav__page { color: var(--rst-text-faint); font-size: var(--rst-fs-xs); font-weight: 650; letter-spacing: 0.06em; padding-block: 0.35rem; text-transform: uppercase; }
113.ds-nav__page[aria-current] { color: var(--rst-accent); }
114.ds-nav__page:hover { color: var(--rst-text); }
115.ds-nav > details > summary:hover { color: var(--rst-text); }
116.ds-nav > details > summary:focus-visible { outline: 2px solid var(--rst-accent); outline-offset: 2px; }
117/* The filter hides a link by setting [hidden] on it, and the shell
118 paints every rail link display: block, which the browser's own
119 [hidden] rule loses to. This selector outranks it rather than
120 shouting !important at it. */
121[rst-shell-sidebar] .ds-nav a[hidden], .ds-nav details[hidden] { display: none; }
122/* No script, no filter, and no box sitting there looking like one. The
123 nav under it is a complete list of every page either way. */
124.ds-search { display: none; }
125:root[data-gallery-js] .ds-search { display: block; }
126/* The magnifier sits inside the field at its inline start, over the
127 field's padding, and lets a tap through to the field under it. It is
128 the icon set's own search glyph, aria-hidden, because the field's
129 label already names it. */
130:root[data-gallery-js] .ds-search { position: relative; }
131/* 16px like the system's search box's icon: tokens.css sizes an icon
132 that way only inside its own controls, and this box is the gallery's. */
133.ds-search > .icon { block-size: 1rem; color: var(--rst-text-faint); inline-size: 1rem; inset-block-start: 50%; inset-inline-start: 0.55rem; pointer-events: none; position: absolute; transform: translateY(-50%); }
134.ds-search input { background: var(--rst-bg); border: 1px solid var(--rst-line-strong); border-radius: var(--rst-radius-sm); box-sizing: border-box; color: var(--rst-text); font: inherit; font-size: var(--rst-fs-sm); inline-size: 100%; min-block-size: var(--rst-target); padding-block: 0.35rem; padding-inline: 1.9rem 0.5rem; }
135.ds-search input:focus-visible { border-color: var(--rst-accent); outline: 2px solid var(--rst-accent); outline-offset: -1px; }
136.ds-nav__empty { color: var(--rst-text-muted); font-size: var(--rst-fs-sm); margin: var(--rst-sp-3) 0 0; }
137/* The rail's filter box is 12.5px like everything else in here, and a
138 sub-16px field is exactly what makes mobile Safari zoom the whole
139 page when it takes focus. tokens.css lifts the app's own controls on
140 a coarse pointer; this one carries a ds- class of its own, so it
141 outranks that rule and has to say the same thing again. */
142@media (pointer: coarse) {
143 .ds-search input { font-size: max(1rem, 1em); }
144}
145
146/* The frame. At 800px and up the bar is pinned over main. A grid
147 item's containing block is its grid area and a sticky box cannot
148 leave it, so a bar in a one-row area has no room to stick; it gets
149 the rail's shape instead, an area spanning every row, with the first
150 row reserving its height. Lines are numbered, not sided, so in
151 Arabic the rail is on the right and the bar over main on the left
152 with no rule here.
153
154 --ds-bar-h is the bar's border-box height per band, the measured
155 tallest over every theme and language. From 1024px the no-wrap rule
156 below keeps the bar to one row everywhere, so the reservation is
157 that one line's height. Below 1024px the controls can still wrap to
158 a second line, and the reservation is the measured two-row maximum.
159 TestThePinnedBarFitsItsReservation measures what is inside the bar
160 against it. */
161:root { --ds-bar-h: 3.25rem; }
162@media (min-width: 800px) and (max-width: 1023.98px) { :root { --ds-bar-h: 6rem; } }
163.ds-top { align-items: center; border-block-end: 1px solid var(--rst-line); display: flex; flex-wrap: wrap; gap: var(--rst-sp-2) var(--rst-sp-3); justify-content: space-between; padding: var(--rst-sp-2) var(--rst-sp-4); }
164/* Padding rather than a min-block-size, because from 1024px the brand
165 elides its text, which a flex or grid box cannot do: the link grows
166 to the floor round its one line, and the bar centres it. */
167.ds-top__brand { color: var(--rst-text); font-weight: 650; padding-block: max(0px, (var(--rst-target) - 1lh) / 2); text-decoration: none; }
168.ds-top__controls { align-items: center; display: flex; flex-wrap: wrap; gap: var(--rst-sp-3); justify-content: flex-end; }
169.ds-top__controls [rst-dropdown] { position: relative; }
170/* The theme switcher is the system's seg-tabs, which leaves a block's
171 gap under itself. Here it sits in a row and in a column that space
172 their own items: in the bar's centred row the margin lifted the tabs
173 above the menus beside them, and in the phone card it more than
174 doubled the gap under them. */
175.ds-top__controls [rst-seg-tabs], .ds-prefs [rst-seg-tabs] { margin: 0; }
176.ds-top__controls [rst-dropdown] > summary { padding-block: 0.25rem; }
177/* The bar's own box is fixed at --ds-bar-h and cannot grow to a second
178 row without overflowing its grid area (above), so from 1024px it
179 must not wrap at all. The brand is what yields: eliding its text
180 leaves its accessible name untouched, while every control has to
181 stay whole for its hit target and its label to both still work. */
182@media (min-width: 1024px) {
183 .ds-top { flex-wrap: nowrap; }
184 .ds-top__controls { flex-shrink: 0; }
185 .ds-top__brand { min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
186}
187@media (min-width: 800px) {
188 body > [rst-shell-sidebar] { grid-template-rows: var(--ds-bar-h) 1fr; }
189 body > [rst-shell-sidebar] > [rst-shell-rail] { grid-column: 1; grid-row: 1 / -1; }
190 /* Opaque, and above page content (auto, the positioned preview boxes
191 and transformed frames included) but below the skip link's 60. */
192 .ds-top { align-self: start; background: var(--rst-bg); block-size: var(--ds-bar-h); box-sizing: border-box; grid-column: 2; grid-row: 1 / -1; inset-block-start: 0; position: sticky; z-index: 10; }
193 body > [rst-shell-sidebar] > [rst-shell-main] { grid-column: 2; grid-row: 2; }
194 /* Fragments and focus stop below the pinned bar (WCAG technique C43).
195 Only here: below 800px what is pinned is the shell's back strip,
196 and its clearance is tokens.css's to set; a rule on html at every
197 width would override that. */
198 html { scroll-padding-block-start: calc(var(--ds-bar-h) + var(--rst-sp-2)); }
199}
200/* Pieces only the phone index shows, written on the Overview alone. At
201 800px and up the Overview is a page with the rail beside it, as the
202 shell's index is, and these would be a second list under the tree
203 and a second set of controls beside the bar's. */
204.ds-index-lead, .ds-rail > .ds-index { display: none; }
205@media (max-width: 799.98px) {
206 /* On a phone a section page is the way back and the content, and the
207 controls are in the display settings menu at the top of every page
208 (below). */
209 .ds-top { display: none; }
210 [rst-shell-sidebar~="index"] .ds-index-lead { color: var(--rst-text-muted); display: block; margin: 0 0 var(--rst-sp-4); padding-inline: 0.25rem; }
211 [rst-shell-sidebar~="index"] > .ds-rail > .ds-index { display: flex; }
212 /* The rail on the index has no gap of its own (the rows sit flush
213 under the heading), so the field would touch the first row. */
214 [rst-shell-sidebar~="index"] .ds-search { margin-block-end: var(--rst-sp-3); }
215 /* A query swaps the rows for the tree it filters. Two rules, so an
216 engine without :has() drops both and shows rows and tree one after
217 the other: long, but with no route missing. */
218 [rst-shell-sidebar~="index"]:not(:has(#ds-filter:not(:placeholder-shown))) > .ds-rail > .ds-nav { display: none; }
219 [rst-shell-sidebar~="index"]:has(#ds-filter:not(:placeholder-shown)) > .ds-rail > .ds-index { display: none; }
220}
221@media (max-width: 799.98px) {
222 /* On a phone the stage is the screen's width. The bleed is what sits
223 between the widget and the screen's edge: the page's padding, and
224 inside a sample card its padding and border as well. Written per
225 context rather than measured, so a change to either shows up as a
226 sideways scroll in the reflow and phone drives instead of a quietly
227 narrower stage. The tabs and the code stay in the text column. */
228 .ds-view { --ds-bleed: var(--rst-sp-4); margin-inline: calc(-1 * var(--ds-bleed)); }
229 .ds-sample .ds-view { --ds-bleed: calc(2 * var(--rst-sp-4) + 1px); }
230 .ds-view__tabs, .ds-view__code { margin-inline: var(--ds-bleed); }
231 /* Content-box sizing under max-inline-size: 100%: a border here
232 would make a full-width box 2px wider than the screen. */
233 .ds-view__box, .ds-view__stage { border-inline-width: 0; border-radius: 0; }
234}
235
236/* Display settings, on a phone. Below 800px the pinned bar is gone,
237 and the theme, scheme and language controls are one menu at the top
238 of every page: in the index's header row beside the heading, where
239 the shell's own profile menu sits, and at the inline end of a content
240 page's back strip. It is an rst-dropdown, so fiesta.js closes it on
241 an outside click and on Escape, and its card is the system's
242 anchored panel. At 800px and up the bar has the controls and the
243 menu is not drawn. */
244.ds-prefs { display: none; }
245/* border-box, so the system's target floor is the whole button rather
246 than 44px of icon inside its padding. */
247.ds-prefs > summary { border-radius: var(--rst-radius-sm); box-sizing: border-box; color: var(--rst-text); justify-content: center; padding: 0.4rem; }
248.ds-prefs > summary:hover, .ds-prefs[open] > summary { background: var(--rst-accent-soft); }
249.ds-prefs > summary:focus-visible { outline: 2px solid var(--rst-accent); outline-offset: -2px; }
250/* Scripts off, a tap outside the card still closes it: the open
251 summary grows a layer over the viewport, under the card, so the tap
252 is a click on the summary. The system's menu cards do the same. */
253.ds-prefs[open] > summary::before { content: ""; cursor: default; inset: 0; position: fixed; z-index: 1; }
254/* Taller than a menu's usual 20rem cap: with the language list open in
255 place the card holds twelve 44px rows, and the screen is the room it
256 has, not a row of a toolbar. */
257.ds-prefs > [rst-dropdown-menu] { align-items: flex-start; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--rst-sp-3); inline-size: max-content; max-block-size: calc(100dvh - 6rem); max-inline-size: calc(100vw - 1.5rem); padding: var(--rst-sp-3); }
258/* The scheme menu and the language menu inside the card open in place:
259 a popover inside a popover has nowhere to go on a phone. Each is the
260 card's full width so its rows read as rows. */
261.ds-prefs :is([rst-locale], [rst-scheme]) { align-self: stretch; }
262.ds-prefs :is([rst-locale], [rst-scheme])[open] > [rst-dropdown-menu] { border: 0; box-shadow: none; inset: auto; margin: 0; max-block-size: none; min-width: 0; padding-block: 0; padding-inline: 0.5rem 0; position: static; }
263@media (max-width: 799.98px) {
264 .ds-prefs { display: block; }
265 /* Lifted into the index's header row, the place and size of the
266 shell's profile menu: the rail is positioned on the index, and the
267 heading keeps that corner clear. */
268 [rst-shell-sidebar~="index"] > .ds-rail > .ds-prefs { align-items: center; block-size: var(--rst-shell-strip); display: flex; inset-block-start: 0; inset-inline-end: var(--rst-sp-4); position: absolute; }
269 [rst-shell-back] > .ds-prefs { margin-inline-start: auto; }
270}
271