oficina / estilo Public

Clone
git clone https://amadan.net/oficina/estilo

Plain git — no account needed to clone.

Download

Download this file

1/* chrome/chrome.css: the suite's top bar, account menu, app switcher and
2 sign-in pages. Link it after menu.css (its panels are [estilo-menu]).
3 Two custom properties are PUBLIC contract, read by apps and never
4 copied as numbers: the bar's block size and its stacking level. */
5:root {
6 --estilo-bar-block-size: 3.25rem; /* 52px. PUBLIC */
7 --estilo-z-bar: 45; /* PUBLIC: the bar's stacking level, and the ceiling for in-page layers */
8 --estilo-trigger-size: 2rem; /* 32px targets, above the 24px floor */
9}
10[estilo-bar] {
11 position: relative;
12 z-index: var(--estilo-z-bar);
13 box-sizing: border-box;
14 display: flex;
15 flex-wrap: nowrap;
16 align-items: center;
17 gap: var(--rst-sp-3);
18 block-size: var(--estilo-bar-block-size); /* fixed, not min: nothing may grow it */
19 padding-inline: var(--rst-sp-4);
20 background: var(--rst-surface);
21 color: var(--rst-text);
22 border-block-end: 1px solid var(--rst-line);
23}
24[estilo-bar~="sticky"] { position: sticky; inset-block-start: 0; }
25[estilo-bar-brand] {
26 display: inline-flex;
27 align-items: center;
28 gap: 0.5rem;
29 flex: none;
30 color: var(--rst-text);
31 font-weight: 650;
32 text-decoration: none;
33 white-space: nowrap;
34}
35[estilo-bar-brand] img { flex: none; inline-size: 1.75rem; block-size: 1.75rem; border-radius: 21%; }
36[estilo-bar-context] {
37 flex: 0 1 auto;
38 min-inline-size: 0;
39 overflow: hidden;
40 text-overflow: ellipsis;
41 white-space: nowrap;
42 padding-inline-start: var(--rst-sp-3);
43 border-inline-start: 1px solid var(--rst-line);
44 color: var(--rst-text);
45 font-weight: 550;
46}
47[estilo-bar-nav] { display: flex; align-self: stretch; gap: var(--rst-sp-4); }
48[estilo-bar-nav] a {
49 display: flex;
50 align-items: center;
51 border-block: 2px solid transparent; /* square current marker, in-flow */
52 color: var(--rst-text-muted);
53 font-size: var(--rst-fs-sm);
54 text-decoration: none;
55 white-space: nowrap;
56}
57[estilo-bar-nav] a:hover { color: var(--rst-text); }
58[estilo-bar-nav] a[aria-current] { border-block-end-color: var(--rst-accent); color: var(--rst-text); font-weight: 550; }
59[estilo-bar-end] { display: flex; align-items: center; gap: var(--rst-sp-2); flex: none; margin-inline-start: auto; }
60[estilo-bar-actions] { display: flex; align-items: center; gap: var(--rst-sp-2); }
61[estilo-bar-actions] form { display: contents; } /* a POST action lays out as its button */
62[estilo-bar-trigger] {
63 display: inline-flex;
64 align-items: center;
65 justify-content: center;
66 gap: 0.3rem;
67 box-sizing: border-box;
68 min-inline-size: var(--estilo-trigger-size);
69 block-size: var(--estilo-trigger-size);
70 padding-inline: 0.4rem;
71 border-radius: 0; /* in-flow: square */
72 color: var(--rst-text-muted);
73 font-size: var(--rst-fs-sm);
74 cursor: pointer;
75 list-style: none;
76 user-select: none;
77}
78[estilo-bar-trigger]::-webkit-details-marker { display: none; }
79[estilo-bar-trigger]::marker { content: ""; }
80[estilo-bar-trigger] svg { flex: none; inline-size: 1.125rem; block-size: 1.125rem; }
81[estilo-bar-trigger]:hover,
82[open] > [estilo-bar-trigger] { color: var(--rst-text); background: var(--rst-surface-2); }
83[estilo-bar-trigger]:focus-visible { outline: 2px solid var(--rst-accent); outline-offset: -2px; }
84[estilo-bar-more] { display: none; }
85@media (max-width: 799.98px) { /* rastrillo's shell breakpoint */
86 [estilo-bar-nav], [estilo-bar-actions] { display: none; }
87 [estilo-bar-more] { display: block; }
88 [estilo-bar]:has([estilo-bar-context], [estilo-bar-title]) [estilo-bar-name] { display: none; } /* the icon stays; the title gets the room */
89}
90
91/* The shell. <div estilo-shell> wraps the skip link, the bar and <main>
92 on every page and has no styling of its own. estilo-shell="fill" is the
93 full-height layout for the one kind of page that must fill the viewport
94 (Sheets' grid): the shell is exactly the viewport, the bar keeps its
95 52px, and <main> takes the rest, so the working area is the viewport
96 less the bar without any app re-deriving that sum. The document never
97 scrolls there, so the root drops its reserved scrollbar gutter, which
98 would otherwise leave a dead strip down the inline end. <main> must be
99 the shell's direct child. */
100[estilo-shell~="fill"] {
101 display: flex;
102 flex-direction: column;
103 block-size: 100dvh;
104}
105[estilo-shell~="fill"] > [estilo-bar] { flex: none; }
106[estilo-shell~="fill"] > main { flex: 1 1 auto; min-block-size: 0; }
107:root:has([estilo-shell~="fill"]) { scrollbar-gutter: auto; }
108
109/* The editable title slot: the open object's title, renamed in place. The
110 input is a bordered control, so it keeps the theme's radius; its block size is
111 fixed so an input in the bar can never grow the bar. */
112[estilo-bar-title] {
113 display: flex;
114 align-items: center;
115 gap: var(--rst-sp-2);
116 flex: 0 1 22rem;
117 min-inline-size: 0;
118 margin: 0;
119 padding-inline-start: var(--rst-sp-3);
120 border-inline-start: 1px solid var(--rst-line);
121}
122[estilo-bar-title-input] {
123 box-sizing: border-box;
124 block-size: 2rem;
125 inline-size: 100%;
126 min-inline-size: 6rem;
127 padding-inline: 0.4rem;
128 border: 1px solid transparent;
129 border-radius: var(--rst-radius-sm);
130 background: transparent;
131 color: var(--rst-text);
132 font: inherit;
133 font-weight: 550;
134 text-overflow: ellipsis;
135}
136[estilo-bar-title-input]:hover { border-color: var(--rst-line); }
137[estilo-bar-title-input]:focus { border-color: var(--rst-accent); outline: none; background: var(--rst-surface); }
138/* iOS zooms the page into a text field under 16px. tokens.css lifts fields
139 to 16px on a coarse pointer, but with a bare `input` selector, which
140 font: inherit above outweighs. Same rule, restated at this weight. */
141@media (pointer: coarse) {
142 [estilo-bar-title-input] {
143 font-size: max(1rem, 1em);
144 }
145}
146[estilo-bar-title-submit] { position: absolute; clip-path: inset(50%); inline-size: 1px; block-size: 1px; overflow: hidden; white-space: nowrap; }
147[estilo-bar-title]:focus-within [estilo-bar-title-submit] { position: static; clip-path: none; inline-size: auto; block-size: 2rem; overflow: visible; flex: none; }
148/* Below the shell breakpoint the row has no room for the button beside the
149 field: it would sit under Menu or the switcher, and a click at its centre
150 would open them instead (found in the first review, at 390px and 320px).
151 So the field takes whatever width is left, down to nothing but its own
152 padding, and on focus the button floats just under it, over the page,
153 where nothing in the bar competes for it. Enter renames at every width. */
154@media (max-width: 799.98px) {
155 [estilo-bar-title] { position: relative; }
156 [estilo-bar-title-input] { min-inline-size: 0; }
157 [estilo-bar-title]:focus-within [estilo-bar-title-submit] {
158 position: absolute;
159 inset-block-start: calc(100% + 0.5rem);
160 inset-inline-start: var(--rst-sp-3);
161 border: 1px solid var(--rst-line);
162 border-radius: var(--estilo-float-radius, 9px); /* a float */
163 background: var(--rst-surface);
164 box-shadow: var(--rst-shadow-pop);
165 }
166}
167
168/* The app switcher: a float, so its tiles may be rounded. */
169[estilo-switcher] { position: relative; }
170[estilo-switcher-panel] { position: absolute; inset-inline-end: 0; inset-block-start: calc(100% + 4px); }
171[estilo-switcher-grid] { display: grid; grid-template-columns: repeat(3, 5.5rem); gap: 0.25rem; }
172[estilo-switcher-app] {
173 display: flex;
174 flex-direction: column;
175 align-items: center;
176 gap: 0.35rem;
177 padding: 0.6rem 0.25rem;
178 border-radius: var(--rst-radius-sm); /* inside a float: rounded is allowed */
179 color: var(--rst-text);
180 font-size: var(--rst-fs-xs);
181 text-decoration: none;
182}
183[estilo-switcher-app]:hover,
184[estilo-switcher-app]:focus-visible { background: var(--rst-accent-soft); }
185[estilo-switcher-app][aria-current] { background: var(--rst-accent-soft); font-weight: 600; }
186[estilo-switcher-app] img { border-radius: 21%; }
187
188/* The account menu. The account is always the last thing at the inline
189 end of the bar: the "same corner" rule. */
190[estilo-account] { position: relative; }
191[estilo-account-panel] { position: absolute; inset-inline-end: 0; inset-block-start: calc(100% + 4px); min-inline-size: 15rem; }
192[estilo-avatar] {
193 display: inline-flex;
194 align-items: center;
195 justify-content: center;
196 inline-size: 1.75rem;
197 block-size: 1.75rem;
198 border-radius: 50%; /* an identity mark, not a highlight */
199 background: var(--rst-accent-soft);
200 color: var(--rst-accent);
201 font-size: var(--rst-fs-xs);
202 font-weight: 650;
203}
204[estilo-menu-identity] { display: grid; gap: 0.1rem; padding: 0.5rem var(--estilo-item-padding-inline, 0.65rem); }
205[estilo-menu-identity-label] { color: var(--rst-text-muted); font-size: var(--rst-fs-xs); }
206[estilo-menu-identity-name] { font-weight: 600; overflow-wrap: anywhere; }
207[estilo-menu-identity-address] { color: var(--rst-text-muted); overflow-wrap: anywhere; }
208[estilo-menu-identity-name] + [estilo-menu-identity-address] { font-size: var(--rst-fs-xs); }
209[estilo-bar-signin] { flex: none; }
210
211/* The account at a sidebar rail's foot (Account.Rail), for an app whose
212 chrome is a rail rather than the bar. The trigger is a row the rail's
213 width: the avatar, then who is signed in, cut short with an ellipsis.
214 It stays in the page flow, so its highlight stays square. The panel is
215 the foot's own width, edge to edge with the trigger: hung from the
216 inline end of a foot narrower than the bar's 15rem panel it ran off
217 the window's start edge, and from the inline start it ran past the
218 rail, whose overflow-y: auto clips it (Fichas' first screenshot). */
219[estilo-account~="rail"] > [estilo-bar-trigger] {
220 justify-content: flex-start;
221 gap: var(--rst-sp-2);
222 inline-size: 100%;
223 block-size: auto;
224 min-block-size: 2.5rem;
225 color: var(--rst-text);
226}
227[estilo-account-who] { min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
228[estilo-account~="rail"] > [estilo-account-panel] { inset-inline: 0; inline-size: auto; min-inline-size: 0; max-inline-size: none; }
229/* A drop-up where the rail is the viewport's height (rastrillo's shell
230 breakpoint): below the foot there is only the window's edge. Below
231 800px the rail is a disclosure at the top of the page, with the page
232 under it and too little above, so the panel opens downward there. */
233@media (min-width: 800px) {
234 [estilo-account~="rail"] > [estilo-account-panel] {
235 inset-block-start: auto;
236 inset-block-end: calc(100% + 4px);
237 max-block-size: max(calc(100dvh - 5rem), 8rem);
238 }
239}
240
241/* Visually hidden, still announced. */
242[estilo-visually-hidden] { position: absolute; clip-path: inset(50%); inline-size: 1px; block-size: 1px; overflow: hidden; white-space: nowrap; }
243
244/* Sign-in, check-your-email and signed-out pages: the Oficina door. The
245 suite's sky behind (estilo sky.css places and animates it), one card on
246 it with the app's mark and name at its head — the same door Home draws
247 at id.oficina.works, in the app's own colour. The door spans the page
248 whatever the app's layout gives it, so the sky is never boxed in. */
249:root:has([estilo-door]) { overflow-x: clip; --rst-scrollbar-gutter: auto; scrollbar-gutter: auto; }
250[estilo-door] {
251 box-sizing: border-box;
252 margin-inline: calc(50% - 50vw);
253 padding: max(40px, 9vh) var(--rst-sp-4) var(--rst-sp-6);
254 min-block-size: 680px;
255 /* The whole sky lies inside the door, fading in and out, so the door's
256 edges never cut it: under an app's bar there is no page top to hide
257 an edge behind, as there is on Home. A sky's layers overhang its box
258 by 12% above and below (sky.css), and fade in over their first 22%
259 and out from 58% to 92% — so a 560px sky placed 67px down starts
260 transparent at the door's top and has faded out by 640px. */
261 --estilo-sky-top: 67px;
262 --estilo-sky-height: 560px;
263}
264[estilo-signin] {
265 box-sizing: border-box;
266 max-inline-size: 460px;
267 margin: 0 auto;
268 padding: 34px 40px 32px;
269 background: var(--rst-surface);
270 border-radius: 20px;
271 box-shadow: 0 0 0 1px light-dark(transparent, var(--rst-line)), var(--rst-shadow-lift);
272}
273[estilo-signin] > [estilo-brand] { display: flex; align-items: center; gap: 10px; margin: 0 0 22px; font-size: 1.2rem; font-weight: 650; letter-spacing: -0.01em; }
274[estilo-signin] > [estilo-brand] [estilo-brand-icon] { inline-size: 36px; block-size: 36px; }
275[estilo-signin] h1 { margin: 0; font-size: 1.75rem; font-weight: 620; letter-spacing: -0.02em; line-height: 1.15; }
276[estilo-signin-lede] { margin: 0.5rem 0 var(--rst-sp-4); color: var(--rst-text-muted); }
277[estilo-signin] > h1 + :not([estilo-signin-lede]) { margin-block-start: var(--rst-sp-4); }
278[estilo-signin-form] { max-inline-size: none; margin-block-start: var(--rst-sp-4); }
279[estilo-signin-body] { margin: var(--rst-sp-4) 0; }
280@media (max-width: 520px) {
281 [estilo-door] { padding-inline: 14px; padding-block-start: 28px; }
282 [estilo-signin] { padding: 26px 22px 24px; }
283}
284[estilo-signin-foot] { margin-block-start: var(--rst-sp-6); font-size: var(--rst-fs-xs); color: var(--rst-text-muted); }
285/* The door's links are drawn here, not left to the app: an app that does
286 not link base.css (Calendar, Memoria, Calls, Fichas) showed the browser's
287 blue on the card. As base.css does, a link in the card is the app's
288 colour at the lowest specificity, so a link drawn as a button keeps the
289 button's; the foot's is quiet, like its text. */
290:where([estilo-signin]) a { color: var(--rst-accent); text-underline-offset: 0.15em; }
291[estilo-signin-foot] a { color: inherit; }
292[estilo-signin-foot] a:hover, [estilo-signin-foot] a:focus-visible { color: var(--rst-text); }
293