Files
member-console/internal/embeds/static/app.css
T
cgalo5758 ce3668d59e Refine operator overview metrics and styling
Replace domain claims with open invoices, show monthly recurring
revenue,
count team organizations, and add more informative trend captions.

Use standard bordered cards and add a README screenshot with reversible
sample-data tooling.
2026-07-27 02:44:55 -05:00

159 lines
5.5 KiB
CSS

/* ============================================================
* app.css — supplemental styles only
* ------------------------------------------------------------
* The member-console design system is Bootstrap-first. This file
* does NOT define a parallel token layer or utility system: it only
* covers the small set of things Bootstrap 5 does not.
*
* Contract:
* - Use Bootstrap utilities/components directly in templates.
* - Add a rule here only when Bootstrap genuinely cannot express it
* (e.g. the HTMX loading-indicator hook, fixed toast positioning,
* cross-browser <meter> styling).
* - Reference Bootstrap CSS variables (var(--bs-*)) instead of
* hardcoded color values so this file stays in sync if Bootstrap's
* defaults change.
*
* See docs/design-system.md for the full Bootstrap usage guide and the
* custom-primitives reference.
* ============================================================ */
/* HTMX loading indicators */
.htmx-indicator {
display: none;
}
.htmx-request .htmx-indicator {
display: inline-block;
}
.htmx-request.htmx-indicator {
display: inline-block;
}
/* Dashboard quota bar */
.quota-bar {
height: 8px;
border-radius: 4px;
}
/* Global toast positioning */
.toast-container {
position: fixed;
top: 1rem;
right: 1rem;
z-index: 1100;
}
/* Entitlement quota meter — Bootstrap doesn't style <meter> consistently
* across engines, so we normalize it to the Bootstrap primary color. */
meter {
height: 0.75rem;
border-radius: 0.25rem;
overflow: hidden;
}
meter::-webkit-meter-bar {
background: var(--bs-border-color);
border: none;
border-radius: 0.25rem;
}
meter::-webkit-meter-optimum-value,
meter::-webkit-meter-suboptimum-value,
meter::-webkit-meter-even-less-good-value {
background: var(--bs-primary);
border-radius: 0.25rem;
}
meter::-moz-meter-bar {
background: var(--bs-primary);
}
/* Shared application sidebar — present on every top-level layout
* (dashboard, products, operator). Gives the nav a stable minimum width on
* lg+ screens so capability labels don't reflow. */
.app-sidebar {
min-width: 14rem;
}
/* Active page indicator — Bootstrap's default .nav-link.active only changes
* color, which is faint against bg-light; add weight + a left accent bar
* + a tinted background so the current page is unambiguous at a glance. */
.app-sidebar .nav-link.active {
font-weight: 600;
border-left: 3px solid var(--bs-primary);
padding-left: calc(1rem - 3px);
background-color: rgba(var(--bs-primary-rgb), 0.08);
border-radius: 0.25rem;
}
/* Operator IA group separation between Runtime / Catalog / Integration.
* M7d's IA spec dropped visible group headings ("Members and Billing" /
* "Catalog" added cognitive load without disambiguating), so we use a
* hairline rule and extra top margin on the first item of each group
* instead. Dashboard/products sidebars are flat (no groups) so this rule
* stays scoped to the operator sidebar. */
.operator-ia-sidebar .operator-ia-group-start {
margin-top: 0.75rem;
padding-top: 0.75rem;
border-top: 1px solid var(--bs-border-color);
}
/* Plan topology overview (operator-topology-legibility). The first column
* (rank) stays pinned while the cross-ladder grid scrolls horizontally inside
* its .table-responsive wrapper, so ranks stay readable when many ladders push
* the grid wider than the viewport. Scoped to .topology-grid so no other
* operator table is affected. */
.topology-grid th:first-child,
.topology-grid td:first-child {
position: sticky;
left: 0;
z-index: 1;
background-color: var(--bs-body-bg);
}
/* Drag-to-reorder (operator) — shared by the topology ladder columns
* (horizontal) and the ladder tier rows (vertical), both driven by SortableJS
* (self-hosted for CSP) via sortable-reorder.js. Bootstrap-variable drag
* feedback + grab affordance, no inline styles. Pinned items (e.g. the topology
* rank column) carry no handle and are excluded via data-sortable-filter. */
.sortable-handle {
cursor: grab;
user-select: none;
}
.sortable-handle:active {
cursor: grabbing;
}
.sortable-ghost {
opacity: 0.5;
}
.sortable-ghost,
.sortable-chosen {
background-color: var(--bs-primary-bg-subtle) !important;
}
/* A table set flush against a card's edges (.card > .table-responsive — the
* operator landing's Recent activity timeline) is a scroll container: it
* clips its rows to its own square box, painting straight through the curve
* the card border draws at each corner. Give the wrapper Bootstrap's own
* inner-radius token so the clip follows the border; scoped to first/last
* child (mirroring Bootstrap's .card > .list-group treatment) so a wrapper
* sitting below a card header keeps its square top corners. */
.card > .table-responsive:first-child {
border-top-left-radius: var(--bs-card-inner-border-radius);
border-top-right-radius: var(--bs-card-inner-border-radius);
}
.card > .table-responsive:last-child {
border-bottom-left-radius: var(--bs-card-inner-border-radius);
border-bottom-right-radius: var(--bs-card-inner-border-radius);
}
/* Affected-population disclosure in preview panels (org-type default change,
* tier reorder/removal): the bucket line carries only the count; org names
* live behind a <details> and render one per row, scrolling past ~8 rows so
* hundred-org previews stay compact. */
.org-disclosure-list {
max-height: 10rem;
overflow-y: auto;
margin-top: .25rem;
padding-left: .75rem;
}