Cut duplicated and speculative code across the package

An over-engineering audit of the whole tree, applied in five reviewed
batches. Behaviour stays the same except where UPGRADE.md says otherwise.

PHP: the showcase and error-page stylesheets are prebuilt into
resources/dist by bin/stylesheets.mjs, through Vite's own postcss-import
(first occurrence kept, the order an application's build gives), instead
of Stylesheets::bundle() inlining imports on every request; only the
import walk DesignGuard needs stays. SchemeStylesheet::withProfiles()
replaces three copies of the scheme-plus-profiles loop, material:scheme
leaves spec and contrast checks to the node script that already made
them, and the error page's scheme cache, the hashed view namespace, the
translations path with no lang/ folder and DesignGuard's 1.x-name hints
are gone.

JS: the androidx shape port progress.js and both bin scripts each carried
lives once in resources/js/shapes.js (the generated SVGs are unchanged);
util.js holds ringIndex(), ms(), reopenGuard() and remember(), which
were written out several times; listeners are released through
AbortController; tooltip.js's hoverPopover() serves the rich tooltip too.

CSS: every rule for an element inside the navigation rail queries
`--md-navigation-rail-value` instead of repeating the seven collapsed
conditions under five media branches; badge, alert, progress, slider and
button read one non-inheriting colour-role table (components/color.css);
the dialog chrome, the submenu's popover chrome, the chip's state layer
and touch target, and the visually-hidden inputs use the shared rules
they copied; foundation/tokens.css is folded into foundation.css.

Views: Support\Field and Support\Link replace the error-key, bound-value
and link-attribute blocks copied into the fields and link components;
the timepicker period group, the menu filter and the showcase head are
partials; the datepicker's steppers and entry fields are loops; component
docblocks no longer restate SKILL.md.

Tests and tooling: one dataset-driven ComponentStylesheetsTest replaces
four per-group files, DesignGuardTest and the layout-component tests use
datasets, browser tests share one ready() helper, CSS parsing lives in
ComponentStylesheet alone. docs/audits and the finding IDs citing it are
removed, as are pestphp/pest-plugin-laravel, the unused composer scripts
and check:font; the lint job runs in the feature job, which now installs
node packages so the prebuilt-stylesheet staleness test runs in CI.

Feature suite 1177 passed, Chrome browser suite 299 passed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Andreas Reinhold / reini
2026-09-17 19:29:21 +02:00
co-authored by Claude Opus 5
parent 471d927e64
commit 247c596c3a
233 changed files with 16635 additions and 10579 deletions
+19 -464
View File
@@ -19,8 +19,8 @@
* [data-md-navigation-rail-item] navigation-rail-item.css
* [data-md-navigation-rail-footer] never scrolls
*
* **Collapsed**: a rail (and anything in it) is drawn collapsed while any of these hold, each its
* own rule below wherever a property differs by shape — a fixed `collapsed` mode; a `collapsible` rail the visitor collapsed
* **Collapsed**: a rail (and anything in it) is drawn collapsed while any of these hold, which the
* rail's own two rules below publish as `--md-navigation-rail-value` for everything inside it — a fixed `collapsed` mode; a `collapsible` rail the visitor collapsed
* (`<html data-rail="collapsed">`, set before the first paint by `<x-theme-script>`) and not
* currently open over the page; a `modal` rail not open; below `medium` (600px) a `collapsible`
* rail regardless of choice, M3's floor ("compact → use a navigation bar, not a standard rail");
@@ -56,14 +56,14 @@
*
* `data-md-divider` and `data-md-fill="false"` are both Missing until this rewrite: an optional
* vertical divider on the page's edge, M3's own answer to a page scrolling under a fixed rail, and
* a transparent container as long as the items keep 3:1 contrast (N-22). `data-md-align="center"`
* a transparent container as long as the items keep 3:1 contrast. `data-md-align="center"`
* is M3's other alignment, preferred on a tablet for reach — only the destinations move; the
* header, footer and menu button stay at their ends, and `safe` gives the top back once there are
* more destinations than fit.
*
* The rail-header FAB rules at the end draw M3's nested-FAB elevation (level 0, not a standalone
* FAB's 3 — N-03) and morph it into an extended FAB as the rail opens, rather than swapping two by
* `display` (N-23). Both sit in this file's own `material.components` layer and win by specificity
* FAB's 3) and morph it into an extended FAB as the rail opens, rather than swapping two by
* `display`. Both sit in this file's own `material.components` layer and win by specificity
* alone, whichever copy of fab.css a build places last: the flat shadow outranks fab.css's resting
* and hover shadows, and the collapsed FAB's `gap` and minimum width outrank fab.css's extended-size
* and collapse-on-scroll rules, which would otherwise tie with them.
@@ -187,14 +187,7 @@
alone; the label is taken out of the drawing, not out of the page (navigation-rail-item.css
renders it always — it is what names the destination). */
[data-md-navigation-rail][data-md-width='narrow'] [data-md-navigation-rail-item] [data-md-navigation-label] {
&:where(
[data-md-navigation-rail='collapsed'],
[data-md-navigation-rail='collapsed'] *,
[data-rail='collapsed'] [data-md-navigation-rail='collapsible']:not([data-md-open]),
[data-rail='collapsed'] [data-md-navigation-rail='collapsible']:not([data-md-open]) *,
[data-md-navigation-rail='modal']:not([data-md-open]),
[data-md-navigation-rail='modal']:not([data-md-open]) *
) {
@container style(--md-navigation-rail-value: collapsed) {
position: absolute;
width: 1px;
height: 1px;
@@ -204,64 +197,6 @@
clip-path: inset(50%);
white-space: nowrap;
}
@media (width < 600px) {
&:where([data-md-navigation-rail='collapsible']:not([data-md-open]), [data-md-navigation-rail='collapsible']:not([data-md-open]) *) {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
}
@media (width < 840px) {
&:where([data-md-navigation-rail='adaptive']:not([data-md-open]), [data-md-navigation-rail='adaptive']:not([data-md-open]) *) {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
}
@media (840px <= width < 1200px) {
&:where(
:is([data-rail='collapsed'], [data-rail-auto]) [data-md-navigation-rail='adaptive']:not([data-md-open]),
:is([data-rail='collapsed'], [data-rail-auto]) [data-md-navigation-rail='adaptive']:not([data-md-open]) *
) {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
}
@media (width >= 1200px) {
&:where(
[data-rail='collapsed'] [data-md-navigation-rail='adaptive']:not([data-md-open]),
[data-rail='collapsed'] [data-md-navigation-rail='adaptive']:not([data-md-open]) *
) {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
}
}
/* A modal rail keeps its collapsed width in the layout while it is open over it, as Compose's
@@ -284,7 +219,7 @@
/* "Compact → don't use a standard rail, use a navigation bar." A `collapsible` rail takes
the width the visitor chose, which on a 360px screen would be two-thirds of it, so it is
floored at its collapsed width (N-24). `collapsed` and `expanded` mean what they say and
floored at its collapsed width. `collapsed` and `expanded` mean what they say and
are left alone: wrap one in an application's own `medium:` element if it must not show
on a phone. */
[data-md-navigation-rail='collapsible'] {
@@ -315,7 +250,7 @@
/* M3's two optional container treatments: "optional vertical divider separates rail from
content, placed on the content-adjacent edge" — also its answer to a page scrolling under a
fixed rail — and "container fill can be turned off (transparent) as long as items keep ≥3:1
contrast" (N-22). Neither applies to a rail open over a scrim, a surface over the page. */
contrast". Neither applies to a rail open over a scrim, a surface over the page. */
[data-md-navigation-rail][data-md-divider]:not([data-md-open], [data-md-closing='sheet']) > [data-md-navigation-rail-panel] {
border-inline-end: 1px solid var(--md-sys-color-outline-variant);
}
@@ -393,14 +328,7 @@
the collapsed branches, which stop the moment the rail is open — that is what makes it the
expanded rail that comes back, on the unconditional rule below. */
[data-md-navigation-rail][data-md-hide-when-collapsed] > [data-md-navigation-rail-panel] {
&:where(
[data-md-navigation-rail='collapsed'],
[data-md-navigation-rail='collapsed'] *,
[data-rail='collapsed'] [data-md-navigation-rail='collapsible']:not([data-md-open]),
[data-rail='collapsed'] [data-md-navigation-rail='collapsible']:not([data-md-open]) *,
[data-md-navigation-rail='modal']:not([data-md-open]),
[data-md-navigation-rail='modal']:not([data-md-open]) *
) {
@container style(--md-navigation-rail-value: collapsed) {
display: none;
translate: -100% 0;
transition:
@@ -410,64 +338,6 @@
translate: 100% 0;
}
}
@media (width < 600px) {
&:where([data-md-navigation-rail='collapsible']:not([data-md-open]), [data-md-navigation-rail='collapsible']:not([data-md-open]) *) {
display: none;
translate: -100% 0;
transition:
translate var(--md-sys-motion-effects-default-duration) var(--md-sys-motion-easing-emphasized-accelerate);
&:is([dir='rtl'], [dir='rtl'] *) {
translate: 100% 0;
}
}
}
@media (width < 840px) {
&:where([data-md-navigation-rail='adaptive']:not([data-md-open]), [data-md-navigation-rail='adaptive']:not([data-md-open]) *) {
display: none;
translate: -100% 0;
transition:
translate var(--md-sys-motion-effects-default-duration) var(--md-sys-motion-easing-emphasized-accelerate);
&:is([dir='rtl'], [dir='rtl'] *) {
translate: 100% 0;
}
}
}
@media (840px <= width < 1200px) {
&:where(
:is([data-rail='collapsed'], [data-rail-auto]) [data-md-navigation-rail='adaptive']:not([data-md-open]),
:is([data-rail='collapsed'], [data-rail-auto]) [data-md-navigation-rail='adaptive']:not([data-md-open]) *
) {
display: none;
translate: -100% 0;
transition:
translate var(--md-sys-motion-effects-default-duration) var(--md-sys-motion-easing-emphasized-accelerate);
&:is([dir='rtl'], [dir='rtl'] *) {
translate: 100% 0;
}
}
}
@media (width >= 1200px) {
&:where(
[data-rail='collapsed'] [data-md-navigation-rail='adaptive']:not([data-md-open]),
[data-rail='collapsed'] [data-md-navigation-rail='adaptive']:not([data-md-open]) *
) {
display: none;
translate: -100% 0;
transition:
translate var(--md-sys-motion-effects-default-duration) var(--md-sys-motion-easing-emphasized-accelerate);
&:is([dir='rtl'], [dir='rtl'] *) {
translate: 100% 0;
}
}
}
}
[data-md-navigation-rail][data-md-hide-when-collapsed][data-md-open] > [data-md-navigation-rail-panel] {
@@ -591,46 +461,9 @@
}
[data-md-navigation-rail][data-md-width='narrow'] [data-md-navigation-rail-header]:has([data-md-navigation-rail-menu]) [data-md-navigation-rail-menu-row] {
&:where(
[data-md-navigation-rail='collapsed'],
[data-md-navigation-rail='collapsed'] *,
[data-rail='collapsed'] [data-md-navigation-rail='collapsible']:not([data-md-open]),
[data-rail='collapsed'] [data-md-navigation-rail='collapsible']:not([data-md-open]) *,
[data-md-navigation-rail='modal']:not([data-md-open]),
[data-md-navigation-rail='modal']:not([data-md-open]) *
) {
@container style(--md-navigation-rail-value: collapsed) {
padding-inline-start: 20px;
}
@media (width < 600px) {
&:where([data-md-navigation-rail='collapsible']:not([data-md-open]), [data-md-navigation-rail='collapsible']:not([data-md-open]) *) {
padding-inline-start: 20px;
}
}
@media (width < 840px) {
&:where([data-md-navigation-rail='adaptive']:not([data-md-open]), [data-md-navigation-rail='adaptive']:not([data-md-open]) *) {
padding-inline-start: 20px;
}
}
@media (840px <= width < 1200px) {
&:where(
:is([data-rail='collapsed'], [data-rail-auto]) [data-md-navigation-rail='adaptive']:not([data-md-open]),
:is([data-rail='collapsed'], [data-rail-auto]) [data-md-navigation-rail='adaptive']:not([data-md-open]) *
) {
padding-inline-start: 20px;
}
}
@media (width >= 1200px) {
&:where(
[data-rail='collapsed'] [data-md-navigation-rail='adaptive']:not([data-md-open]),
[data-rail='collapsed'] [data-md-navigation-rail='adaptive']:not([data-md-open]) *
) {
padding-inline-start: 20px;
}
}
}
[data-md-navigation-rail-menu] {
@@ -658,137 +491,24 @@
[data-md-navigation-rail-menu-collapse-icon],
[data-md-navigation-rail-menu-expand-icon] {
&:where(
[data-md-navigation-rail='collapsed'],
[data-md-navigation-rail='collapsed'] *,
[data-rail='collapsed'] [data-md-navigation-rail='collapsible']:not([data-md-open]),
[data-rail='collapsed'] [data-md-navigation-rail='collapsible']:not([data-md-open]) *,
[data-md-navigation-rail='modal']:not([data-md-open]),
[data-md-navigation-rail='modal']:not([data-md-open]) *
) {
@container style(--md-navigation-rail-value: collapsed) {
display: none;
}
@media (width < 600px) {
&:where([data-md-navigation-rail='collapsible']:not([data-md-open]), [data-md-navigation-rail='collapsible']:not([data-md-open]) *) {
display: none;
}
}
@media (width < 840px) {
&:where([data-md-navigation-rail='adaptive']:not([data-md-open]), [data-md-navigation-rail='adaptive']:not([data-md-open]) *) {
display: none;
}
}
@media (840px <= width < 1200px) {
&:where(
:is([data-rail='collapsed'], [data-rail-auto]) [data-md-navigation-rail='adaptive']:not([data-md-open]),
:is([data-rail='collapsed'], [data-rail-auto]) [data-md-navigation-rail='adaptive']:not([data-md-open]) *
) {
display: none;
}
}
@media (width >= 1200px) {
&:where(
[data-rail='collapsed'] [data-md-navigation-rail='adaptive']:not([data-md-open]),
[data-rail='collapsed'] [data-md-navigation-rail='adaptive']:not([data-md-open]) *
) {
display: none;
}
}
}
[data-md-navigation-rail-menu-expand-icon] {
&:where(
[data-md-navigation-rail='collapsed'],
[data-md-navigation-rail='collapsed'] *,
[data-rail='collapsed'] [data-md-navigation-rail='collapsible']:not([data-md-open]),
[data-rail='collapsed'] [data-md-navigation-rail='collapsible']:not([data-md-open]) *,
[data-md-navigation-rail='modal']:not([data-md-open]),
[data-md-navigation-rail='modal']:not([data-md-open]) *
) {
@container style(--md-navigation-rail-value: collapsed) {
display: contents;
}
@media (width < 600px) {
&:where([data-md-navigation-rail='collapsible']:not([data-md-open]), [data-md-navigation-rail='collapsible']:not([data-md-open]) *) {
display: contents;
}
}
@media (width < 840px) {
&:where([data-md-navigation-rail='adaptive']:not([data-md-open]), [data-md-navigation-rail='adaptive']:not([data-md-open]) *) {
display: contents;
}
}
@media (840px <= width < 1200px) {
&:where(
:is([data-rail='collapsed'], [data-rail-auto]) [data-md-navigation-rail='adaptive']:not([data-md-open]),
:is([data-rail='collapsed'], [data-rail-auto]) [data-md-navigation-rail='adaptive']:not([data-md-open]) *
) {
display: contents;
}
}
@media (width >= 1200px) {
&:where(
[data-rail='collapsed'] [data-md-navigation-rail='adaptive']:not([data-md-open]),
[data-rail='collapsed'] [data-md-navigation-rail='adaptive']:not([data-md-open]) *
) {
display: contents;
}
}
}
[data-md-navigation-rail-brand] {
min-width: 0;
flex: 1 1 0%;
}
[data-md-navigation-rail-brand] {
&:where(
[data-md-navigation-rail='collapsed'],
[data-md-navigation-rail='collapsed'] *,
[data-rail='collapsed'] [data-md-navigation-rail='collapsible']:not([data-md-open]),
[data-rail='collapsed'] [data-md-navigation-rail='collapsible']:not([data-md-open]) *,
[data-md-navigation-rail='modal']:not([data-md-open]),
[data-md-navigation-rail='modal']:not([data-md-open]) *
) {
@container style(--md-navigation-rail-value: collapsed) {
display: none;
}
@media (width < 600px) {
&:where([data-md-navigation-rail='collapsible']:not([data-md-open]), [data-md-navigation-rail='collapsible']:not([data-md-open]) *) {
display: none;
}
}
@media (width < 840px) {
&:where([data-md-navigation-rail='adaptive']:not([data-md-open]), [data-md-navigation-rail='adaptive']:not([data-md-open]) *) {
display: none;
}
}
@media (840px <= width < 1200px) {
&:where(
:is([data-rail='collapsed'], [data-rail-auto]) [data-md-navigation-rail='adaptive']:not([data-md-open]),
:is([data-rail='collapsed'], [data-rail-auto]) [data-md-navigation-rail='adaptive']:not([data-md-open]) *
) {
display: none;
}
}
@media (width >= 1200px) {
&:where(
[data-rail='collapsed'] [data-md-navigation-rail='adaptive']:not([data-md-open]),
[data-rail='collapsed'] [data-md-navigation-rail='adaptive']:not([data-md-open]) *
) {
display: none;
}
}
}
/* The FAB row: 20px either side in the default 96px rail, 12px in a narrow 80 while collapsed
@@ -803,46 +523,9 @@
}
[data-md-navigation-rail][data-md-width='narrow'] [data-md-navigation-rail-fab-row] {
&:where(
[data-md-navigation-rail='collapsed'],
[data-md-navigation-rail='collapsed'] *,
[data-rail='collapsed'] [data-md-navigation-rail='collapsible']:not([data-md-open]),
[data-rail='collapsed'] [data-md-navigation-rail='collapsible']:not([data-md-open]) *,
[data-md-navigation-rail='modal']:not([data-md-open]),
[data-md-navigation-rail='modal']:not([data-md-open]) *
) {
@container style(--md-navigation-rail-value: collapsed) {
padding-inline: 12px;
}
@media (width < 600px) {
&:where([data-md-navigation-rail='collapsible']:not([data-md-open]), [data-md-navigation-rail='collapsible']:not([data-md-open]) *) {
padding-inline: 12px;
}
}
@media (width < 840px) {
&:where([data-md-navigation-rail='adaptive']:not([data-md-open]), [data-md-navigation-rail='adaptive']:not([data-md-open]) *) {
padding-inline: 12px;
}
}
@media (840px <= width < 1200px) {
&:where(
:is([data-rail='collapsed'], [data-rail-auto]) [data-md-navigation-rail='adaptive']:not([data-md-open]),
:is([data-rail='collapsed'], [data-rail-auto]) [data-md-navigation-rail='adaptive']:not([data-md-open]) *
) {
padding-inline: 12px;
}
}
@media (width >= 1200px) {
&:where(
[data-rail='collapsed'] [data-md-navigation-rail='adaptive']:not([data-md-open]),
[data-rail='collapsed'] [data-md-navigation-rail='adaptive']:not([data-md-open]) *
) {
padding-inline: 12px;
}
}
}
[data-md-navigation-rail-destinations] {
@@ -858,50 +541,10 @@
[data-md-navigation-rail-footer] {
display: flex;
flex-direction: column;
}
[data-md-navigation-rail-destinations],
[data-md-navigation-rail-footer] {
&:where(
[data-md-navigation-rail='collapsed'],
[data-md-navigation-rail='collapsed'] *,
[data-rail='collapsed'] [data-md-navigation-rail='collapsible']:not([data-md-open]),
[data-rail='collapsed'] [data-md-navigation-rail='collapsible']:not([data-md-open]) *,
[data-md-navigation-rail='modal']:not([data-md-open]),
[data-md-navigation-rail='modal']:not([data-md-open]) *
) {
@container style(--md-navigation-rail-value: collapsed) {
gap: 4px;
}
@media (width < 600px) {
&:where([data-md-navigation-rail='collapsible']:not([data-md-open]), [data-md-navigation-rail='collapsible']:not([data-md-open]) *) {
gap: 4px;
}
}
@media (width < 840px) {
&:where([data-md-navigation-rail='adaptive']:not([data-md-open]), [data-md-navigation-rail='adaptive']:not([data-md-open]) *) {
gap: 4px;
}
}
@media (840px <= width < 1200px) {
&:where(
:is([data-rail='collapsed'], [data-rail-auto]) [data-md-navigation-rail='adaptive']:not([data-md-open]),
:is([data-rail='collapsed'], [data-rail-auto]) [data-md-navigation-rail='adaptive']:not([data-md-open]) *
) {
gap: 4px;
}
}
@media (width >= 1200px) {
&:where(
[data-rail='collapsed'] [data-md-navigation-rail='adaptive']:not([data-md-open]),
[data-rail='collapsed'] [data-md-navigation-rail='adaptive']:not([data-md-open]) *
) {
gap: 4px;
}
}
}
[data-md-navigation-rail-footer] {
@@ -921,7 +564,7 @@
/*
* A FAB in the rail's header rests at elevation 0, not the 3 a standalone FAB has
* (§ Navigation Rail/Behaviour: "when nested within another component, such as the navigation
* rail, the FAB's resting elevation should be level 0" — N-03). The doubled `[data-md-fab]`
* rail, the FAB's resting elevation should be level 0"). The doubled `[data-md-fab]`
* attribute only adds specificity, over fab.css's `[data-md-fab]:hover` too, as
* `[data-md-navigation-rail-item][data-md-navigation-rail-item]::before`
* (navigation-rail-item.css) does for the same reason.
@@ -933,7 +576,7 @@
/*
* "Rail transitions from collapsed to expanded should animate the FAB into and out of an
* extended FAB" (N-23) — so the header takes one `<x-fab label icon>` and morphs it, rather
* extended FAB" — so the header takes one `<x-fab label icon>` and morphs it, rather
* than swapping two by `display`, which showed the collapsed one at once while the rail's
* width was still springing. The label's width springs on the rail's own spatial spring; with
* the gap and the extended FAB's own minimum width both zeroed, `aspect-ratio` squares what is
@@ -949,109 +592,21 @@
transition:
max-width var(--md-sys-motion-spatial-default-duration) var(--md-sys-motion-spatial-default),
opacity var(--md-sys-motion-effects-default-duration) var(--md-sys-motion-effects-default);
}
[data-md-navigation-rail-header] [data-md-fab] > span {
&:where(
[data-md-navigation-rail='collapsed'],
[data-md-navigation-rail='collapsed'] *,
[data-rail='collapsed'] [data-md-navigation-rail='collapsible']:not([data-md-open]),
[data-rail='collapsed'] [data-md-navigation-rail='collapsible']:not([data-md-open]) *,
[data-md-navigation-rail='modal']:not([data-md-open]),
[data-md-navigation-rail='modal']:not([data-md-open]) *
) {
@container style(--md-navigation-rail-value: collapsed) {
max-width: 0;
opacity: 0;
}
@media (width < 600px) {
&:where([data-md-navigation-rail='collapsible']:not([data-md-open]), [data-md-navigation-rail='collapsible']:not([data-md-open]) *) {
max-width: 0;
opacity: 0;
}
}
@media (width < 840px) {
&:where([data-md-navigation-rail='adaptive']:not([data-md-open]), [data-md-navigation-rail='adaptive']:not([data-md-open]) *) {
max-width: 0;
opacity: 0;
}
}
@media (840px <= width < 1200px) {
&:where(
:is([data-rail='collapsed'], [data-rail-auto]) [data-md-navigation-rail='adaptive']:not([data-md-open]),
:is([data-rail='collapsed'], [data-rail-auto]) [data-md-navigation-rail='adaptive']:not([data-md-open]) *
) {
max-width: 0;
opacity: 0;
}
}
@media (width >= 1200px) {
&:where(
[data-rail='collapsed'] [data-md-navigation-rail='adaptive']:not([data-md-open]),
[data-rail='collapsed'] [data-md-navigation-rail='adaptive']:not([data-md-open]) *
) {
max-width: 0;
opacity: 0;
}
}
}
/* `[data-md-extended]` doubled for the same reason as the shadow's `[data-md-fab]` above: it
outranks fab.css's `[data-md-fab][data-md-extended][data-md-size]` gap and its collapsed
collapse-on-scroll FAB's minimum width, three attributes each. */
[data-md-navigation-rail-header] [data-md-fab][data-md-extended][data-md-extended] {
&:where(
[data-md-navigation-rail='collapsed'],
[data-md-navigation-rail='collapsed'] *,
[data-rail='collapsed'] [data-md-navigation-rail='collapsible']:not([data-md-open]),
[data-rail='collapsed'] [data-md-navigation-rail='collapsible']:not([data-md-open]) *,
[data-md-navigation-rail='modal']:not([data-md-open]),
[data-md-navigation-rail='modal']:not([data-md-open]) *
) {
@container style(--md-navigation-rail-value: collapsed) {
min-inline-size: 0;
aspect-ratio: 1;
gap: 0;
}
@media (width < 600px) {
&:where([data-md-navigation-rail='collapsible']:not([data-md-open]), [data-md-navigation-rail='collapsible']:not([data-md-open]) *) {
min-inline-size: 0;
aspect-ratio: 1;
gap: 0;
}
}
@media (width < 840px) {
&:where([data-md-navigation-rail='adaptive']:not([data-md-open]), [data-md-navigation-rail='adaptive']:not([data-md-open]) *) {
min-inline-size: 0;
aspect-ratio: 1;
gap: 0;
}
}
@media (840px <= width < 1200px) {
&:where(
:is([data-rail='collapsed'], [data-rail-auto]) [data-md-navigation-rail='adaptive']:not([data-md-open]),
:is([data-rail='collapsed'], [data-rail-auto]) [data-md-navigation-rail='adaptive']:not([data-md-open]) *
) {
min-inline-size: 0;
aspect-ratio: 1;
gap: 0;
}
}
@media (width >= 1200px) {
&:where(
[data-rail='collapsed'] [data-md-navigation-rail='adaptive']:not([data-md-open]),
[data-rail='collapsed'] [data-md-navigation-rail='adaptive']:not([data-md-open]) *
) {
min-inline-size: 0;
aspect-ratio: 1;
gap: 0;
}
}
}
}