Repository navigation
Expand file tree
/
Copy pathdeck.css
More file actions
200 lines (183 loc) · 11.1 KB
/
Copy pathdeck.css
File metadata and controls
200 lines (183 loc) · 11.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/* @robertblust/design — deck.css, assembled from the shared blocks: link v1 · lockup v1 ·
transport v11 · rests v1.
Editing this file in a site does nothing: the next npm run design overwrites it. */
:where(a){color:inherit}
:where(a:not([class])){color:var(--c-mid); text-decoration:none; border-bottom:1px solid transparent}
:where(a:not([class]):hover, a:not([class]):focus-visible){border-bottom-color:var(--c-mid)}
.name{grid-column:1; justify-self:start;
font-family:"Instrument Sans", ui-sans-serif, system-ui, sans-serif; font-size:.72rem;
display:flex; align-items:center; gap:.5em}
.name .lockup{display:flex; align-items:center; gap:.6em}
.name .namemark{display:flex}
.name .namemark svg{width:16px; height:16px; display:block}
.name .lockup:hover b em, .name .lockup:focus-visible b em{color:var(--ink)}
.name .plate{fill:var(--raise); stroke:var(--rule); stroke-width:1.5}
.name .rb{fill:var(--c-mid)}
.name b{color:var(--ink); font-weight:600; letter-spacing:.01em; text-transform:none}
.name b em{font-style:normal; color:var(--c-mid)}
/* "Talks" is a nav item, so it takes the nav treatment the pages use — dim until
pointed at. The separators are not links and must not read as one. */
.name .nsep{color:var(--dim)}
.name .nlink{color:var(--dim)}
.name a{text-decoration:none; color:inherit; pointer-events:auto}
.name a:hover, .name a:focus-visible{color:var(--ink)}
.transport{
grid-column:2; justify-self:center;
display:flex; align-items:center; gap:.45rem;
background:var(--slab); border:1px solid var(--rule); border-radius:14px;
padding:.45rem .55rem;
box-shadow:inset 0 1px 0 var(--deck-lift), 0 12px 34px var(--deck-drop);
}
/* the display window. The hairline under the number is the position of the clip that
is speaking — how much of this slide is left — and is empty when nothing speaks. */
.lcd{
display:flex; flex-direction:column; align-items:center; gap:5px;
background:var(--lcd); border-radius:8px; padding:.44rem .62rem .38rem;
box-shadow:inset 0 1px 3px var(--lcd-inset), inset 0 0 0 1px var(--lcd-glow);
font-family:"Plex Mono", ui-monospace, monospace; line-height:1;
margin-right:.2rem;
}
.lcd .n{font-size:.76rem; font-weight:600; letter-spacing:.09em; color:var(--lcd-ink); white-space:nowrap}
.lcd .n .sep, .lcd .n #tot{color:var(--lcd-faint)}
.lcd .clip{width:100%; height:2px; background:var(--lcd-track); border-radius:2px; overflow:hidden}
.lcd .clip i{display:block; height:100%; width:0; background:var(--lcd-ink); transition:width .25s linear}
.tmain, .tside{display:flex; align-items:center; gap:.45rem}
.tbtn{
display:grid; place-items:center; width:34px; height:34px; flex:0 0 auto;
background:none; border:0; border-radius:9px; color:var(--dim); cursor:pointer;
transition:color .15s ease, background-color .15s ease, border-color .15s ease;
}
.tbtn svg{width:18px; height:18px; fill:currentColor; display:block}
.tbtn svg.stroked{fill:none; stroke:currentColor; stroke-width:2; stroke-linecap:round; stroke-linejoin:round}
.tbtn:hover{color:var(--ink); background:var(--deck-hover)}
/* aria-disabled, not :disabled — the runtime keeps the control focusable and returns
early from its own handler instead of removing it from the tab order; see
`deck runtime`'s render() for why a real `disabled` moves focus under the user. */
.tbtn[aria-disabled="true"]{opacity:.35; cursor:default}
.tbtn[aria-disabled="true"]:hover{color:inherit; background:none}
.tbtn:focus-visible{outline:2px solid var(--c-mid); outline-offset:2px; color:var(--ink)}
.tbtn[aria-pressed="true"]{color:var(--c-mid); background:var(--press)}
.tbtn.play{width:44px; height:44px; border-radius:50%; border:1.5px solid var(--deck-ring); color:var(--c-mid)}
.tbtn.play svg{width:17px; height:17px}
.tbtn.play:hover{background:var(--press); border-color:var(--c-mid); color:var(--c-mid)}
.tbtn .icontract{display:none}
.tbtn[aria-pressed="true"] .icontract{display:block}
.tbtn[aria-pressed="true"] .iexpand{display:none}
.tbtn.play .ipause{display:none}
.tbtn.play.on{background:var(--c-mid); border-color:var(--c-mid); color:var(--ground)}
.tbtn.play.on .iplay{display:none}
.tbtn.play.on .ipause{display:block}
/* the exit is an <a>, so it works with no JS and the browser treats it as
navigation — history, middle-click and "open in new tab" all behave. */
a.tbtn{text-decoration:none}
.tdiv{width:1px; align-self:stretch; margin:.3rem .25rem; background:var(--deck-divider); flex:0 0 auto}
.seg{display:flex; border:1px solid var(--rule); border-radius:8px; overflow:hidden; flex:0 0 auto}
.seg button{
background:none; border:0; cursor:pointer; padding:.44rem .48rem;
font-family:"Plex Mono", ui-monospace, monospace; font-size:.63rem; letter-spacing:.12em;
color:var(--dim); transition:color .15s ease, background-color .15s ease;
min-height:calc(1lh + .88rem);
}
.seg button:hover{color:var(--ink)}
.seg button[aria-pressed="true"]{color:var(--c-mid); background:var(--press); font-weight:600}
.seg button:focus-visible{outline:2px solid var(--c-mid); outline-offset:-2px}
/* The theme control rides in the transport beside the language one, so it takes the
transport's touch sizing rather than the header's — the same 44px minimum the seg buttons
already meet at the mobile breakpoints. Above them it used to carry a height of its own:
23.3px against the language control's 29.1px, tops 2.9px apart, in a row whose whole point
is one line. The language control sets the height here, as it does in the header, and the
theme control matches it rather than being handed a number.
It matches two ways, because one of them has to hold in a browser with no `lh`. The
vertical padding is the language button's own .44rem, so an icon the size of a line box
lands on that height with no calc involved at all; and `.seg button` above carries one
line box plus that padding as a floor, so an icon *smaller* than a line box is lifted to
the height instead of shrinking the control. The header writes an `em` fallback beside its
`lh` and there is deliberately none here: these buttons inherit `line-height:normal`, and
no `em` value is honestly equal to a normal line box — a fallback guessed at one would be
this same misalignment again, in exactly the browsers it was added to serve.
The floor sits on `.seg button` and not on `.seg.theme button`, which is not a matter of
taste. The three mobile tiers below restate `min-height` on `.seg button`; a floor written
one class more specific would outrank all three and silently undo the 44/40/36px touch
sizing at every width this bar was tuned for. */
.seg.theme button{display:grid; place-items:center; padding:.44rem .42rem}
.seg.theme svg{width:13px; height:13px; display:block; fill:none; stroke:currentColor;
stroke-width:2; stroke-linecap:round; stroke-linejoin:round}
@media (prefers-reduced-motion: reduce){
.tbtn, .seg button, .lcd .clip i{transition:none}
}
/* the transport becomes the bottom edge itself: full width, flush, clear of the
home indicator. The lockup does not fit a collapsed single-column bar, so this is
the one `.name` rule that lives here rather than in `deck lockup` — it is not the
lockup's identity, it is the bar's own statement that the lockup drops out at this
width, and it is byte-identical on all four decks like the rest of this block.
This tier stays at the 44px touch-target floor all the way to 860px. Even with
every gap cut and both dividers dropped it cannot be tuned below about 487px —
that is what a row of 44px controls plus the LCD costs — so nothing this block
is asked to fit (414px, 430px) is asked of this tier either: both land in the
430px tier below, which drops to 40px controls to make the room this one can't.
A width between 431px and 486px is not one of the widths this fix was measured
against, and this tier alone cannot promise it; it is narrower than every phone
in the required set and wider than the ones this fix was written for. */
@media (max-width: 860px), (max-aspect-ratio: 4/5){
.name{display:none}
.transport{
grid-column:1; justify-self:stretch; width:100%;
background:none; border:0; border-radius:0; box-shadow:none;
padding:.3rem .25rem; gap:.1rem; justify-content:space-between;
}
.tmain{gap:.05rem}
.tside{gap:.05rem}
.tbtn{width:44px; height:44px}
.tbtn svg{width:20px; height:20px}
.tbtn.play{width:46px; height:46px}
.tdiv{display:none}
.seg button{padding:0 .16rem; min-width:22px; min-height:44px}
.lcd{padding:.32rem .34rem .28rem; margin-right:0}
/* The chat's button sits bottom right on every page of the family, beside the transport on
a desk. Here the transport spans the whole bottom edge and leaves the button no place:
over the transport it hides the controls, and above it it hides the slide. So a deck
shows no chat button on a phone. The chat itself stays, and `?chat=open`, the address a
PDF page links, still opens it. `body` outranks chat.css's own rule, which a deck
links after this file. */
body .rbchat-open{display:none}
}
/* the theme control's two buttons moved this threshold up from 400px: at 40px
buttons this tier's own floor is under 360px, so 390, 393, 414 and 430 all fit
it comfortably where they could not fit the 44px tier above. */
@media (max-width: 430px){
.lcd{display:none}
.transport{padding:.28rem .15rem; gap:.04rem}
.tbtn{width:40px; height:40px}
.tbtn.play{width:42px; height:42px}
.tmain{gap:0}
.tside{gap:.02rem}
.tdiv{display:none}
.seg button{padding:0 .06rem; min-width:14px; min-height:40px; font-size:.53rem; letter-spacing:0}
.seg.theme button{padding:.13rem .14rem}
.seg.theme svg{width:10px; height:10px}
}
/* the smallest phones still in use. body{overflow:hidden} hides a transport that is
wider than the screen instead of scrolling it, so this has to be measured, not assumed.
Every value here is smaller than the tier above's, not larger — the 430px tier's own
rules still apply underneath and the one written later in the file wins, so a value left
unset here would fall back to a size meant for a wider phone, not shrink further. */
@media (max-width: 350px){
.transport{padding:.22rem .1rem; gap:.02rem}
.tbtn{width:36px; height:36px}
.tbtn svg{width:18px; height:18px}
.tbtn.play{width:38px; height:38px}
.tmain{gap:0}
.tside{gap:0}
.tdiv{display:none}
.seg button{min-width:12px; min-height:36px; padding:0 .04rem; font-size:.5rem}
.seg.theme button{padding:.1rem .1rem}
.seg.theme svg{width:8px; height:8px}
}
.rests{display:flex; flex-wrap:wrap; align-items:center; gap:1cqmin; margin-top:3.4cqmin}
.rests b{font-weight:400; font-size:clamp(.78rem,1.45cqmin,1.05rem); letter-spacing:.16em; text-transform:uppercase; color:var(--dim); margin-right:.6cqmin}
.rests a{font-family:"Plex Mono", ui-monospace, monospace; font-size:clamp(.78rem,1.45cqmin,1.05rem);
border:1px solid var(--rule); background:var(--raise); border-radius:6px; padding:.3em .65em;
color:var(--c-mid); text-decoration:none; transition:border-color .15s ease}
.rests a:hover{border-color:var(--c-mid)}
.rests a:focus-visible{outline:2px solid var(--c-mid); outline-offset:2px}
.rests a i{font-style:normal; color:var(--dim)}