@layer base { /* Page chrome: the sticky
band, dropdown anchoring, the tab strip, breadcrumbs and the * footer. styles/theme/ repaints these; what stays here is the geometry a view can rely on. */ header { position: sticky; top: 0; z-index: var(--fs-z-header); overflow: visible; color: var(--fs-dim); display: flex; } li.menu, .dropdown { position: relative; } .dropdown:hover ul.dropdown-menu { inset-inline-start: 0; } /* Tab-strip visuals (margins, gradients, per-state colours): theme/40-tabs.css — * absorbed. Left: strip geometry. */ .tabs > li, .cbi-tabmenu > li { flex: 0 1 auto; display: flex; align-items: center; } .tabs > li > a, .cbi-tabmenu > li > a { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-decoration: none; outline: none; } /* the tab focus ring lives in theme/40-tabs.css: an accent outline is invisible on the ACTIVE * pill, whose fill is that same accent. The theme repaints the rule that stood here in full * (same selectors), so a copy left behind would be a dead declaration tools/audit.py --strict * reports. */ .cbi-tab-disabled[data-errors]::after { content: attr(data-errors); /* badge fill: theme/40-tabs.css — absorbed */ color: var(--fs-on-danger); height: var(--fs-space-4); min-width: var(--fs-space-4); /* a pill, so it says so, rather than half the height above restated by hand */ border-radius: var(--fs-radius-pill); text-align: center; margin-inline-end: var(--fs-space-1); padding: 0 var(--fs-space-1); display: inline-flex; flex-direction: column; justify-content: center; font-size: var(--fs-type); } .cbi-tab-descr { /* the negative top pulls it under the tab strip it describes */ margin: calc(var(--fs-space-2) * -1) 0 var(--fs-space-4) 0; } /* hangs directly under the tab strip: 100% IS the strip's height by definition, where a literal * would be a hidden pair with whatever sizes the tab */ .tabs .menu-dropdown, .tabs .dropdown-menu { top: 100%; border-width: 1px; /* square top-left only: the panel hangs off the tab above it and the two share that * corner */ border-radius: 0 var(--fs-radius) var(--fs-radius) var(--fs-radius); } /* the caret beside a tab's label, centred on the text box rather than nudged down it */ .tabs a.menu:after, .tabs .dropdown-toggle:after { border-top-color: var(--fs-dim); align-self: center; margin-inline-start: var(--fs-space-1); } .tabs li.open.menu .menu, .tabs .open.dropdown .dropdown-toggle { border-color: var(--fs-border); } .tabs li.open a.menu:after, .tabs .dropdown.open .dropdown-toggle:after { border-top-color: var(--fs-text); } .breadcrumb { padding: var(--fs-space-2) var(--fs-space-3); margin: 0 0 var(--fs-space-4); background: linear-gradient(to bottom, var(--fs-panel), var(--fs-panel2)); border: var(--fs-hairline); border-radius: var(--fs-radius); display: flex; flex: 0; } .breadcrumb li { list-style: none; } .breadcrumb li:not(:last-child)::after { content: "|"; padding: 0 var(--fs-space-1); } .breadcrumb .active a { color: var(--fs-dim); } /* Footer paint: theme/20-shell.css — absorbed. Left: the flex skeleton, where margin-top:auto * pins the footer to the bottom of the flex-column body. Do not re-add * `justify-content: space-between` or a span margin — they came from a two-column footer this * theme does not have. */ footer { margin-top: auto; display: flex; flex-wrap: wrap; align-items: baseline; } footer ul.breadcrumb { margin-inline-start: auto; } }