@layer theme { /* realtime graphs size their canvas from #view, clipping 34px off the newest samples — docs/css.md "Misc: the realtime graph bleed" */ #view .cbi-section > div[style]:has(> svg) { width: auto !important; margin-inline: calc(-1 * (var(--fs-card-pad) + 1px)); } /* same box's frame, painted BLACK inline — only colour moves; wider than the bleed above, channel_analysis.js's box must not be bled but is just as black */ #view div[style]:has(> svg) { border-color: var(--fs-border) !important; } /* WCAG 1.4.1: --fs-accent on --fs-text measures 1.4:1 in dark, needs a non-colour cue in * prose. Nav links/buttons/pills are identified by position and shape instead. */ p a, dd a, .cbi-value-description a, .alert-message a:not(.btn):not(.cbi-button) { text-decoration: underline; } /* a label must set sans, not merely be excluded — excluded still inherits mono (227 elements/ * 20 KB of bold mono for nothing); exempt in pre/code/#syslog/textarea, monospaced content. * `.ifacebadge` is a badge (chrome, not a value) in a mono cell; wins on specificity (0,2,0) * over theme/60-inputs.css's (0,1,0) mono rule, not source order */ :is(strong, b):not(pre *, code *, #syslog *, textarea *), .ifacebadge, .cbi-value-field .ifacebadge { font-family: var(--fs-font-sans); } code, pre { font-weight: var(--fs-weight-normal); } .cbi-title-ref { color: var(--fs-accent); } .close { color: var(--fs-text); text-shadow: none; opacity: .6; } .close:hover { opacity: 1; } .ifacebox { background: var(--fs-panel); border-color: var(--fs-border); } .ifacebox .ifacebox-head { background: var(--fs-panel2); color: var(--fs-text); } /* lives in THIS layer, next to the head it overrides: the same rule in base was dead, a layer beats specificity */ .ifacebox .ifacebox-head.active { background: var(--fs-accent); color: var(--fs-on-accent); } .ifacebadge { background: var(--fs-panel2); border-color: var(--fs-border); } .ifacebadge-active { border-color: var(--fs-accent); } .zonebadge-empty { border-color: var(--fs-border); color: var(--fs-dim); } /* @container PLUMBING only, card rules live with the tables. Named: an unnamed query binds to the nearest container-type ancestor, silently re-targeted by a new one */ .cbi-map { container-type: inline-size; container-name: fs-content; } #view { container-type: inline-size; container-name: fs-view fs-content; } /* ui.js appends #modal_overlay outside #view, so the names above must repeat here or no dialog query resolves. * box-shadow merged in from theme/70-modal.css: base's elevation = --fs-bg's hex in footstrap * light, a glow not a shadow; others take --fs-shadow-pop */ .modal { container-type: inline-size; container-name: fs-view fs-content; box-shadow: var(--fs-shadow-pop); } /* pager (« prev · text · next ») — generic, not page-scoped */ .pager.center { display: flex; align-items: center; justify-content: center; gap: var(--fs-space-2-5); padding: var(--fs-space-3-5) 0; } .pager .text { flex: 0 0 auto; font-size: var(--fs-type); color: var(--fs-dim); } /* absorbed from base; stock LuCI only renders h2/h3, the rest is third-party coverage. * `legend` excluded: theme/30-tables.css owns it. */ h1, h2, h3, h4, h5, h6 { font-weight: var(--fs-weight-bold); color: var(--fs-text); /* 1.5 is prose leading; a heading is a label and looks slack at it */ line-height: var(--fs-leading-tight); } h1 { margin-bottom: var(--fs-space-4); font-size: var(--fs-type-2xl); } h2 { font-size: var(--fs-type-xl); } h3 { font-size: var(--fs-type-lg); } h4, h5 { font-size: var(--fs-type); } h6 { font-size: var(--fs-type-xs); color: var(--fs-dim); text-transform: uppercase; } /* heading card: h2 + .cbi-map-descr get a .cbi-section card's frame, so the page reads as a * stack of panels rather than loose text over the background */ .cbi-map > h2, #view > h2 { background: var(--fs-panel); border: var(--fs-hairline); border-radius: var(--fs-radius-lg); margin: 0 0 var(--fs-card-gap); padding: var(--fs-space-4); } /* split the card across the two siblings — no wrapper element exists to hold both */ .cbi-map > h2:has(+ .cbi-map-descr), #view > h2:has(+ .cbi-map-descr) { border-bottom: 0; border-radius: var(--fs-radius-lg) var(--fs-radius-lg) 0 0; padding-bottom: var(--fs-space-1); margin-bottom: 0; box-shadow: none; } .cbi-map > h2 + .cbi-map-descr, #view > h2 + .cbi-map-descr { background: var(--fs-panel); border: var(--fs-hairline); border-top: 0; border-radius: 0 0 var(--fs-radius-lg) var(--fs-radius-lg); margin: 0 0 var(--fs-card-gap); padding: 0 var(--fs-space-4) var(--fs-space-4); color: var(--fs-dim); font-size: var(--fs-type); line-height: var(--fs-leading); } /* .right holding Add/Save directly under a field had no gap: pinned the button to the textarea */ #view :is(textarea, input[type="text"], input[type="password"], .cbi-dropdown) + .right { margin-top: var(--fs-space-2-5); } /* button row belonging to the PAGE TITLE, not a section — same 16px as .cbi-section, half above */ .cbi-title-buttons { margin-block: var(--fs-space-2) var(--fs-card-gap); } /* Delete button luci-base renders for every NAMED section sat flush against what follows — one class, not one app */ .cbi-section-remove { margin-bottom: var(--fs-space-2); } /* a view may hand the map a bare widget with no `.cbi-section`; exclusions are the children luci-base already spaces itself */ .cbi-map > *:not(.cbi-section):not(.cbi-map-descr):not(.cbi-page-actions):not(h2):not(legend):not(.cbi-tabmenu):not(.cbi-map-tabbed):not(:empty) { margin-bottom: var(--fs-card-gap); } /* the disclosure chevron of the overview card toggle (a stock element, keyed by attribute). * pages/20-overview.css sizes the pill around it. */ .cbi-title .label[data-indicator="poll-status"]::after { content: ""; width: 7px; height: 7px; border-right: 2px solid currentColor; border-bottom: 2px solid currentColor; border-radius: 1px; transform: rotate(45deg); /* closed: chevron down */ margin-top: -2px; /* optical centring of the down chevron */ transition: transform var(--fs-dur-move); } .cbi-title .label[data-indicator="poll-status"][data-style="inactive"]::after { transform: rotate(-135deg); /* open: chevron up */ margin-top: var(--fs-space-0-5); } }