/* chrome/chrome.css: the suite's top bar, account menu, app switcher and
sign-in pages. Link it after menu.css (its panels are [estilo-menu]).
Two custom properties are PUBLIC contract, read by apps and never
copied as numbers: the bar's block size and its stacking level. */
:root {
--estilo-bar-block-size: 3.25rem; /* 52px. PUBLIC */
--estilo-z-bar: 45; /* PUBLIC: the bar's stacking level, and the ceiling for in-page layers */
--estilo-trigger-size: 2rem; /* 32px targets, above the 24px floor */
}
[estilo-bar] {
position: relative;
z-index: var(--estilo-z-bar);
box-sizing: border-box;
display: flex;
flex-wrap: nowrap;
align-items: center;
gap: var(--rst-sp-3);
block-size: var(--estilo-bar-block-size); /* fixed, not min: nothing may grow it */
padding-inline: var(--rst-sp-4);
background: var(--rst-surface);
color: var(--rst-text);
border-block-end: 1px solid var(--rst-line);
}
[estilo-bar~="sticky"] { position: sticky; inset-block-start: 0; }
[estilo-bar-brand] {
display: inline-flex;
align-items: center;
gap: 0.5rem;
flex: none;
color: var(--rst-text);
font-weight: 650;
text-decoration: none;
white-space: nowrap;
}
[estilo-bar-brand] img { flex: none; inline-size: 1.75rem; block-size: 1.75rem; border-radius: 21%; }
[estilo-bar-context] {
flex: 0 1 auto;
min-inline-size: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
padding-inline-start: var(--rst-sp-3);
border-inline-start: 1px solid var(--rst-line);
color: var(--rst-text);
font-weight: 550;
}
[estilo-bar-nav] { display: flex; align-self: stretch; gap: var(--rst-sp-4); }
[estilo-bar-nav] a {
display: flex;
align-items: center;
border-block: 2px solid transparent; /* square current marker, in-flow */
color: var(--rst-text-muted);
font-size: var(--rst-fs-sm);
text-decoration: none;
white-space: nowrap;
}
[estilo-bar-nav] a:hover { color: var(--rst-text); }
[estilo-bar-nav] a[aria-current] { border-block-end-color: var(--rst-accent); color: var(--rst-text); font-weight: 550; }
[estilo-bar-end] { display: flex; align-items: center; gap: var(--rst-sp-2); flex: none; margin-inline-start: auto; }
[estilo-bar-actions] { display: flex; align-items: center; gap: var(--rst-sp-2); }
[estilo-bar-actions] form { display: contents; } /* a POST action lays out as its button */
[estilo-bar-trigger] {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.3rem;
box-sizing: border-box;
min-inline-size: var(--estilo-trigger-size);
block-size: var(--estilo-trigger-size);
padding-inline: 0.4rem;
border-radius: 0; /* in-flow: square */
color: var(--rst-text-muted);
font-size: var(--rst-fs-sm);
cursor: pointer;
list-style: none;
user-select: none;
}
[estilo-bar-trigger]::-webkit-details-marker { display: none; }
[estilo-bar-trigger]::marker { content: ""; }
[estilo-bar-trigger] svg { flex: none; inline-size: 1.125rem; block-size: 1.125rem; }
[estilo-bar-trigger]:hover,
[open] > [estilo-bar-trigger] { color: var(--rst-text); background: var(--rst-surface-2); }
[estilo-bar-trigger]:focus-visible { outline: 2px solid var(--rst-accent); outline-offset: -2px; }
[estilo-bar-more] { display: none; }
@media (max-width: 799.98px) { /* rastrillo's shell breakpoint */
[estilo-bar-nav], [estilo-bar-actions] { display: none; }
[estilo-bar-more] { display: block; }
[estilo-bar]:has([estilo-bar-context], [estilo-bar-title]) [estilo-bar-name] { display: none; } /* the icon stays; the title gets the room */
}
/* The shell.
wraps the skip link, the bar and
on every page and has no styling of its own. estilo-shell="fill" is the
full-height layout for the one kind of page that must fill the viewport
(Sheets' grid): the shell is exactly the viewport, the bar keeps its
52px, and takes the rest, so the working area is the viewport
less the bar without any app re-deriving that sum. The document never
scrolls there, so the root drops its reserved scrollbar gutter, which
would otherwise leave a dead strip down the inline end. must be
the shell's direct child. */
[estilo-shell~="fill"] {
display: flex;
flex-direction: column;
block-size: 100dvh;
}
[estilo-shell~="fill"] > [estilo-bar] { flex: none; }
[estilo-shell~="fill"] > main { flex: 1 1 auto; min-block-size: 0; }
:root:has([estilo-shell~="fill"]) { scrollbar-gutter: auto; }
/* The editable title slot: the open object's title, renamed in place. The
input is a bordered control, so it keeps the theme's radius; its block size is
fixed so an input in the bar can never grow the bar. */
[estilo-bar-title] {
display: flex;
align-items: center;
gap: var(--rst-sp-2);
flex: 0 1 22rem;
min-inline-size: 0;
margin: 0;
padding-inline-start: var(--rst-sp-3);
border-inline-start: 1px solid var(--rst-line);
}
[estilo-bar-title-input] {
box-sizing: border-box;
block-size: 2rem;
inline-size: 100%;
min-inline-size: 6rem;
padding-inline: 0.4rem;
border: 1px solid transparent;
border-radius: var(--rst-radius-sm);
background: transparent;
color: var(--rst-text);
font: inherit;
font-weight: 550;
text-overflow: ellipsis;
}
[estilo-bar-title-input]:hover { border-color: var(--rst-line); }
[estilo-bar-title-input]:focus { border-color: var(--rst-accent); outline: none; background: var(--rst-surface); }
/* iOS zooms the page into a text field under 16px. tokens.css lifts fields
to 16px on a coarse pointer, but with a bare `input` selector, which
font: inherit above outweighs. Same rule, restated at this weight. */
@media (pointer: coarse) {
[estilo-bar-title-input] {
font-size: max(1rem, 1em);
}
}
[estilo-bar-title-submit] { position: absolute; clip-path: inset(50%); inline-size: 1px; block-size: 1px; overflow: hidden; white-space: nowrap; }
[estilo-bar-title]:focus-within [estilo-bar-title-submit] { position: static; clip-path: none; inline-size: auto; block-size: 2rem; overflow: visible; flex: none; }
/* Below the shell breakpoint the row has no room for the button beside the
field: it would sit under Menu or the switcher, and a click at its centre
would open them instead (found in the first review, at 390px and 320px).
So the field takes whatever width is left, down to nothing but its own
padding, and on focus the button floats just under it, over the page,
where nothing in the bar competes for it. Enter renames at every width. */
@media (max-width: 799.98px) {
[estilo-bar-title] { position: relative; }
[estilo-bar-title-input] { min-inline-size: 0; }
[estilo-bar-title]:focus-within [estilo-bar-title-submit] {
position: absolute;
inset-block-start: calc(100% + 0.5rem);
inset-inline-start: var(--rst-sp-3);
border: 1px solid var(--rst-line);
border-radius: var(--estilo-float-radius, 9px); /* a float */
background: var(--rst-surface);
box-shadow: var(--rst-shadow-pop);
}
}
/* The app switcher: a float, so its tiles may be rounded. */
[estilo-switcher] { position: relative; }
[estilo-switcher-panel] { position: absolute; inset-inline-end: 0; inset-block-start: calc(100% + 4px); }
[estilo-switcher-grid] { display: grid; grid-template-columns: repeat(3, 5.5rem); gap: 0.25rem; }
[estilo-switcher-app] {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.35rem;
padding: 0.6rem 0.25rem;
border-radius: var(--rst-radius-sm); /* inside a float: rounded is allowed */
color: var(--rst-text);
font-size: var(--rst-fs-xs);
text-decoration: none;
}
[estilo-switcher-app]:hover,
[estilo-switcher-app]:focus-visible { background: var(--rst-accent-soft); }
[estilo-switcher-app][aria-current] { background: var(--rst-accent-soft); font-weight: 600; }
[estilo-switcher-app] img { border-radius: 21%; }
/* The account menu. The account is always the last thing at the inline
end of the bar: the "same corner" rule. */
[estilo-account] { position: relative; }
[estilo-account-panel] { position: absolute; inset-inline-end: 0; inset-block-start: calc(100% + 4px); min-inline-size: 15rem; }
[estilo-avatar] {
display: inline-flex;
align-items: center;
justify-content: center;
inline-size: 1.75rem;
block-size: 1.75rem;
border-radius: 50%; /* an identity mark, not a highlight */
background: var(--rst-accent-soft);
color: var(--rst-accent);
font-size: var(--rst-fs-xs);
font-weight: 650;
}
[estilo-menu-identity] { display: grid; gap: 0.1rem; padding: 0.5rem var(--estilo-item-padding-inline, 0.65rem); }
[estilo-menu-identity-label] { color: var(--rst-text-muted); font-size: var(--rst-fs-xs); }
[estilo-menu-identity-name] { font-weight: 600; overflow-wrap: anywhere; }
[estilo-menu-identity-address] { color: var(--rst-text-muted); overflow-wrap: anywhere; }
[estilo-menu-identity-name] + [estilo-menu-identity-address] { font-size: var(--rst-fs-xs); }
[estilo-bar-signin] { flex: none; }
/* The account at a sidebar rail's foot (Account.Rail), for an app whose
chrome is a rail rather than the bar. The trigger is a row the rail's
width: the avatar, then who is signed in, cut short with an ellipsis.
It stays in the page flow, so its highlight stays square. The panel is
the foot's own width, edge to edge with the trigger: hung from the
inline end of a foot narrower than the bar's 15rem panel it ran off
the window's start edge, and from the inline start it ran past the
rail, whose overflow-y: auto clips it (Fichas' first screenshot). */
[estilo-account~="rail"] > [estilo-bar-trigger] {
justify-content: flex-start;
gap: var(--rst-sp-2);
inline-size: 100%;
block-size: auto;
min-block-size: 2.5rem;
color: var(--rst-text);
}
[estilo-account-who] { min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
[estilo-account~="rail"] > [estilo-account-panel] { inset-inline: 0; inline-size: auto; min-inline-size: 0; max-inline-size: none; }
/* A drop-up where the rail is the viewport's height (rastrillo's shell
breakpoint): below the foot there is only the window's edge. Below
800px the rail is a disclosure at the top of the page, with the page
under it and too little above, so the panel opens downward there. */
@media (min-width: 800px) {
[estilo-account~="rail"] > [estilo-account-panel] {
inset-block-start: auto;
inset-block-end: calc(100% + 4px);
max-block-size: max(calc(100dvh - 5rem), 8rem);
}
}
/* Visually hidden, still announced. */
[estilo-visually-hidden] { position: absolute; clip-path: inset(50%); inline-size: 1px; block-size: 1px; overflow: hidden; white-space: nowrap; }
/* Sign-in, check-your-email and signed-out pages: the Oficina door. The
suite's sky behind (estilo sky.css places and animates it), one card on
it with the app's mark and name at its head — the same door Home draws
at id.oficina.works, in the app's own colour. The door spans the page
whatever the app's layout gives it, so the sky is never boxed in. */
:root:has([estilo-door]) { overflow-x: clip; --rst-scrollbar-gutter: auto; scrollbar-gutter: auto; }
[estilo-door] {
box-sizing: border-box;
margin-inline: calc(50% - 50vw);
padding: max(40px, 9vh) var(--rst-sp-4) var(--rst-sp-6);
min-block-size: 680px;
/* The whole sky lies inside the door, fading in and out, so the door's
edges never cut it: under an app's bar there is no page top to hide
an edge behind, as there is on Home. A sky's layers overhang its box
by 12% above and below (sky.css), and fade in over their first 22%
and out from 58% to 92% — so a 560px sky placed 67px down starts
transparent at the door's top and has faded out by 640px. */
--estilo-sky-top: 67px;
--estilo-sky-height: 560px;
}
[estilo-signin] {
box-sizing: border-box;
max-inline-size: 460px;
margin: 0 auto;
padding: 34px 40px 32px;
background: var(--rst-surface);
border-radius: 20px;
box-shadow: 0 0 0 1px light-dark(transparent, var(--rst-line)), var(--rst-shadow-lift);
}
[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; }
[estilo-signin] > [estilo-brand] [estilo-brand-icon] { inline-size: 36px; block-size: 36px; }
[estilo-signin] h1 { margin: 0; font-size: 1.75rem; font-weight: 620; letter-spacing: -0.02em; line-height: 1.15; }
[estilo-signin-lede] { margin: 0.5rem 0 var(--rst-sp-4); color: var(--rst-text-muted); }
[estilo-signin] > h1 + :not([estilo-signin-lede]) { margin-block-start: var(--rst-sp-4); }
[estilo-signin-form] { max-inline-size: none; margin-block-start: var(--rst-sp-4); }
[estilo-signin-body] { margin: var(--rst-sp-4) 0; }
@media (max-width: 520px) {
[estilo-door] { padding-inline: 14px; padding-block-start: 28px; }
[estilo-signin] { padding: 26px 22px 24px; }
}
[estilo-signin-foot] { margin-block-start: var(--rst-sp-6); font-size: var(--rst-fs-xs); color: var(--rst-text-muted); }
/* The door's links are drawn here, not left to the app: an app that does
not link base.css (Calendar, Memoria, Calls, Fichas) showed the browser's
blue on the card. As base.css does, a link in the card is the app's
colour at the lowest specificity, so a link drawn as a button keeps the
button's; the foot's is quiet, like its text. */
:where([estilo-signin]) a { color: var(--rst-accent); text-underline-offset: 0.15em; }
[estilo-signin-foot] a { color: inherit; }
[estilo-signin-foot] a:hover, [estilo-signin-foot] a:focus-visible { color: var(--rst-text); }