Files
action a97651184f
marry-jell / merge (push) Canceled after 0s
update 2026-11-01 11:53:54
2026-11-01 11:53:54 +08:00

108 lines
4.7 KiB
CSS

@layer theme {
/* Pins inherited-only props on [data-fs-chrome], closing what the fence cannot: inheritance
* from html/body. ROOT-only selector and text-align: start (never left) are load-bearing —
* third-party-apps.md, "Rule 7. The chrome is fenced off, in three places that must agree". */
:where([data-fs-chrome]:not([data-fs-chrome] *)) {
font-style: normal;
font-variant: normal;
letter-spacing: normal;
word-spacing: normal;
text-transform: none;
text-indent: 0;
text-align: start;
cursor: auto;
}
/* Brand/logo/wordmark/logout/indicators: one look for every layout — a layout file sets only
* PLACEMENT (flex, order, rail collapse), never look. */
.fs-brand {
display: flex; align-items: center; gap: var(--fs-space-2-5);
color: var(--fs-text); font-weight: var(--fs-weight-bold);
}
.fs-logo {
width: var(--fs-btn-size); height: var(--fs-btn-size); border-radius: var(--fs-radius);
border: var(--fs-hairline); /* glyph is baked-colour (header.ut), no currentColor use */
display: flex; align-items: center; justify-content: center;
flex: 0 0 auto;
}
.fs-logo svg { width: 20px; height: 20px; }
.fs-logo-ring { fill: #002b49; } /* flips with mode like the favicon SVG; cyan arcs stay baked */
:root[data-darkmode="true"] .fs-logo-ring { fill: #e6f4fb; }
.fs-wordmark { font-size: var(--fs-type-lg); font-weight: var(--fs-weight-bold); letter-spacing: -.01em; }
/* First tab stop — never display:none/visibility:hidden, that drops it from the tab order. */
.fs-skip {
position: fixed; top: 8px; inset-inline-start: 8px; z-index: var(--fs-z-dropdown);
padding: var(--fs-space-2-5) var(--fs-space-4); border-radius: var(--fs-radius);
background: var(--fs-accent); color: var(--fs-on-accent);
font-weight: var(--fs-weight-bold); font-size: var(--fs-type); text-decoration: none;
box-shadow: var(--fs-shadow-pop);
}
/* clip-path, not a -68px translate: the translate still bled ~16px of drop shadow into the
* viewport (--fs-shadow-pop is offset 12px/blur 34px); clip-path clips the shadow too. */
.fs-skip:not(:focus), .fs-sr {
clip-path: inset(50%);
width: 1px; height: 1px;
padding: 0; overflow: hidden; white-space: nowrap;
}
.fs-skip:focus {
outline: 2px solid var(--fs-panel); outline-offset: 2px;
}
/* Clipped, not display:none/visibility:hidden — both take the <h1> out of the a11y tree too. */
.fs-sr { position: absolute; margin: -1px; }
/* tabindex="-1" on <main> makes Safari/Chrome move focus here rather than just scroll to it. */
#maincontent:focus { outline: none; }
/* box and base colour: 20-shell.css (shared with .fs-themerow) */
.fs-logout:hover { color: var(--fs-danger); }
/* fitTabStrips (fs-chrome.js) adds .fs-dense1/2 when the horizontal menu row would wrap, and
* strips them in the vertical sidebar — no media guard needed. */
.fs-sidebar ul.nav.fs-dense1 > li > a { padding: var(--fs-space-1) var(--fs-space-2); }
.fs-sidebar ul.nav.fs-dense2 > li > a { padding: var(--fs-space-1) var(--fs-space-1-5); }
/* One markup (`ul.nav > li > a`) for both layouts, so these three run once. */
ul.nav { position: relative; margin: 0; list-style: none; }
ul.nav > li { display: block; }
ul.nav a { line-height: 19px; text-decoration: none; }
/* No emitter here, stays styled under the coverage contract — conventions.md, "Coverage is a
* contract". */
.dropdown-menu li { display: block; position: relative; }
ul.nav .dropdown-menu a, .dropdown-menu a { line-height: 18px; } /* denser than ul.nav a above */
.fs-sidebar ul.nav > li > a:hover,
.fs-sidebar ul.nav ul a:hover,
.fs-themerow:hover {
background: var(--fs-panel2); color: var(--fs-text); opacity: 1;
}
.fs-sidebar ul.nav > li > a.active,
.fs-sidebar ul.nav ul a.active,
.fs-themerow[aria-expanded="true"],
.fs-modemenu li.active a {
background: var(--fs-accent-soft); color: var(--fs-accent);
}
/* Plate on the PAGE only; the open ANCESTOR keeps the ink alone — issue #37 (two identical
* plates stacked on System -> System otherwise). chrome.md, "fs-chrome.js". */
.fs-sidebar ul.nav > li.active > a:not(.active) { color: var(--fs-accent); }
/* --fs-focus-ring-solo: none of these flips a border on focus, so the ring alone must clear
* 3:1 — the tinted ring reads only 1.15-1.29:1 (two-ring contract, 02-tokens.css). */
.fs-railtoggle:focus-visible,
.fs-themerow:focus-visible,
.fs-logout:focus-visible,
.fs-sidebar ul.nav a:focus-visible {
outline: none;
box-shadow: var(--fs-focus-ring-solo);
}
/* accent-color reaches a foreign app's native checkbox/radio/progress — the theme's own are
* appearance:none and never see it. */
::selection { background: var(--fs-accent); color: var(--fs-on-accent); }
:root { caret-color: var(--fs-accent); accent-color: var(--fs-accent); }
}