1372 lines
57 KiB
CSS
1372 lines
57 KiB
CSS
/* SPDX-License-Identifier: MIT OR Apache-2.0
|
|
flowRS's component kit: flowRS's own work, under MIT OR Apache-2.0 (at your option), the licence
|
|
of the runtime crates. Every exported app ships a copy (ui/kit.css); the root NOTICE says so. */
|
|
/* ============================================================================
|
|
The component kit (crates/flowrs-ui/src/kit): app blocks, charts, controls and
|
|
instruments, every value a token from styles/tokens.css, so the same markup wears
|
|
Instrument and Paper.
|
|
|
|
House rules, checked by e2e/kit-polish.spec.js and js-test/tokens.test.mjs:
|
|
- space from the 4 px scale (--fr-space-*), type from the ramp (12/14/18/28; 24 for
|
|
the display sizes on a phone), weights 400/500/600, three radii on a screen;
|
|
- colours only through var(--fr-*); motion only through the duration tokens, which
|
|
fall to zero under prefers-reduced-motion;
|
|
- nothing sets a width the content cannot shrink to: min-width: 0 on flex and grid
|
|
children, and wide content (tables, registers) scrolls inside itself.
|
|
============================================================================ */
|
|
|
|
/* ---- Utilities ------------------------------------------------------------ */
|
|
.fr-sr {
|
|
position: absolute !important;
|
|
width: 1px;
|
|
height: 1px;
|
|
margin: -1px;
|
|
padding: 0;
|
|
overflow: hidden;
|
|
clip-path: inset(50%);
|
|
white-space: nowrap;
|
|
border: 0;
|
|
}
|
|
.fr-mono {
|
|
font-family: var(--fr-font-mono);
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
.fr-btn:focus-visible,
|
|
.fr-tab:focus-visible,
|
|
.fr-tabpanel:focus-visible,
|
|
.fr-seg:focus-visible,
|
|
.fr-toggle:focus-visible,
|
|
.fr-input:focus-visible,
|
|
.fr-number-step:focus-visible,
|
|
.fr-slider-input:focus-visible,
|
|
.fr-knob:focus-visible,
|
|
.fr-th-sort:focus-visible,
|
|
.fr-table-scroll:focus-visible,
|
|
.fr-reg-scroll:focus-visible,
|
|
.fr-chart-data > summary:focus-visible,
|
|
.fr-gallery a:focus-visible {
|
|
outline: 2px solid var(--fr-focus);
|
|
outline-offset: 2px;
|
|
box-shadow: none;
|
|
}
|
|
|
|
/* Fills and strokes by meaning (SVG). Used by the kit and by the Front Panel's
|
|
instruments (crate::instruments), which draw the same way. */
|
|
.fr-f-none { fill: none; }
|
|
.fr-s-none { stroke: none; }
|
|
.fr-f-ink { fill: var(--fr-text); }
|
|
.fr-s-ink { stroke: var(--fr-text); }
|
|
.fr-f-muted { fill: var(--fr-text-3); }
|
|
.fr-s-muted { stroke: var(--fr-text-3); }
|
|
.fr-f-accent { fill: var(--fr-accent); }
|
|
.fr-s-accent { stroke: var(--fr-accent); }
|
|
.fr-f-accent-2 { fill: var(--fr-accent-2); }
|
|
.fr-s-accent-2 { stroke: var(--fr-accent-2); }
|
|
.fr-f-good { fill: var(--fr-good); }
|
|
.fr-s-good { stroke: var(--fr-good); }
|
|
.fr-f-warn { fill: var(--fr-warn); }
|
|
.fr-s-warn { stroke: var(--fr-warn); }
|
|
.fr-f-crit { fill: var(--fr-crit); }
|
|
.fr-s-crit { stroke: var(--fr-crit); }
|
|
.fr-f-track { fill: var(--fr-track); }
|
|
.fr-s-track { stroke: var(--fr-track); }
|
|
.fr-f-needle { fill: var(--fr-needle); }
|
|
.fr-s-needle { stroke: var(--fr-needle); }
|
|
.fr-f-card { fill: var(--fr-surface-2); }
|
|
.fr-f-cat-1 { fill: var(--fr-cat-1); }
|
|
.fr-s-cat-1 { stroke: var(--fr-cat-1); }
|
|
.fr-f-cat-2 { fill: var(--fr-cat-2); }
|
|
.fr-s-cat-2 { stroke: var(--fr-cat-2); }
|
|
.fr-f-cat-3 { fill: var(--fr-cat-3); }
|
|
.fr-s-cat-3 { stroke: var(--fr-cat-3); }
|
|
.fr-f-cat-4 { fill: var(--fr-cat-4); }
|
|
.fr-s-cat-4 { stroke: var(--fr-cat-4); }
|
|
.fr-f-cat-5 { fill: var(--fr-cat-5); }
|
|
.fr-s-cat-5 { stroke: var(--fr-cat-5); }
|
|
.fr-f-cat-6 { fill: var(--fr-cat-6); }
|
|
.fr-s-cat-6 { stroke: var(--fr-cat-6); }
|
|
.fr-f-cat-other { fill: var(--fr-cat-other); }
|
|
.fr-s-cat-other { stroke: var(--fr-cat-other); }
|
|
.fr-f-seq-1 { fill: var(--fr-seq-1); }
|
|
.fr-f-seq-2 { fill: var(--fr-seq-2); }
|
|
.fr-f-seq-3 { fill: var(--fr-seq-3); }
|
|
.fr-f-seq-4 { fill: var(--fr-seq-4); }
|
|
.fr-f-seq-5 { fill: var(--fr-seq-5); }
|
|
.fr-f-seq-6 { fill: var(--fr-seq-6); }
|
|
.fr-f-seq-7 { fill: var(--fr-seq-7); }
|
|
.fr-f-seq-8 { fill: var(--fr-seq-8); }
|
|
.fr-f-seq-9 { fill: var(--fr-seq-9); }
|
|
.fr-dashed { stroke-dasharray: 4 4; }
|
|
|
|
/* Front Panel instrument parts (crate::instruments) */
|
|
.fr-stop-from { stop-color: var(--fr-accent-2); }
|
|
.fr-stop-to { stop-color: var(--fr-accent); }
|
|
.fr-stop-liquid-top { stop-color: color-mix(in srgb, var(--fr-accent-2) 70%, var(--fr-white)); }
|
|
.fr-stop-liquid { stop-color: var(--fr-accent-2); }
|
|
.fr-i-vessel { fill: var(--fr-surface-sunk); stroke: var(--fr-track); }
|
|
.fr-i-band-2 { fill: var(--fr-border-2); }
|
|
.fr-i-band-3 { fill: var(--fr-border-3); }
|
|
.fr-i-area { fill: color-mix(in srgb, var(--fr-accent-2) 30%, transparent); stroke: var(--fr-accent-2); }
|
|
.fr-i-up { fill: var(--fr-good); stroke: var(--fr-good); }
|
|
.fr-i-down { fill: var(--fr-crit); stroke: var(--fr-crit); }
|
|
.fr-i-cellgap { stroke: var(--fr-surface-2); }
|
|
.fr-i-geo-sea { fill: var(--fr-surface-sunk); }
|
|
.fr-i-geo-grid { stroke: var(--fr-border-2); }
|
|
.fr-i-geo-equator { stroke: var(--fr-border-3); }
|
|
.fr-i-geo-pt { fill: var(--fr-accent-2); fill-opacity: 0.85; }
|
|
|
|
/* ---- Text ----------------------------------------------------------------- */
|
|
.fr-heading-block { display: flex; flex-direction: column; gap: var(--fr-space-1); min-width: 0; }
|
|
.fr-heading {
|
|
margin: 0;
|
|
color: var(--fr-text);
|
|
font-weight: var(--fr-fw-strong);
|
|
overflow-wrap: break-word;
|
|
}
|
|
.fr-h1 {
|
|
font-size: var(--fr-fs-2xl);
|
|
line-height: var(--fr-lh-display);
|
|
letter-spacing: var(--fr-tracking-display);
|
|
}
|
|
.fr-h2 { font-size: var(--fr-fs-lg); line-height: var(--fr-lh-heading); letter-spacing: var(--fr-tracking); }
|
|
.fr-h3,
|
|
.fr-h4 { font-size: var(--fr-fs-sm); line-height: var(--fr-lh-heading); }
|
|
.fr-heading-sub {
|
|
margin: 0;
|
|
color: var(--fr-text-2);
|
|
font-size: var(--fr-fs-sm);
|
|
line-height: var(--fr-lh-body);
|
|
}
|
|
.fr-text {
|
|
margin: 0;
|
|
max-width: 68ch;
|
|
color: var(--fr-text);
|
|
font-size: var(--fr-fs-sm);
|
|
line-height: var(--fr-lh-body);
|
|
overflow-wrap: break-word;
|
|
}
|
|
.fr-text-sm { font-size: var(--fr-fs-xs); }
|
|
.fr-text-lead { line-height: 1.6; }
|
|
.fr-text-secondary { color: var(--fr-text-2); }
|
|
.fr-text-muted { color: var(--fr-text-3); }
|
|
|
|
.fr-badge {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--fr-space-1);
|
|
min-height: 24px;
|
|
padding: var(--fr-space-half) var(--fr-space-2);
|
|
border-radius: var(--fr-radius-full);
|
|
font-size: var(--fr-fs-xs);
|
|
font-weight: var(--fr-fw-medium);
|
|
line-height: var(--fr-lh-heading);
|
|
white-space: nowrap;
|
|
background: var(--fr-layer-pressed);
|
|
color: var(--fr-text-2);
|
|
}
|
|
.fr-badge-dot { width: 8px; height: 8px; border-radius: var(--fr-radius-full); background: currentColor; flex: none; }
|
|
.fr-badge.fr-tone-good { background: var(--fr-good-soft); color: var(--fr-good-text); }
|
|
.fr-badge.fr-tone-warn { background: var(--fr-warn-soft); color: var(--fr-warn-text); }
|
|
.fr-badge.fr-tone-crit { background: var(--fr-crit-soft); color: var(--fr-crit-text); }
|
|
.fr-badge.fr-tone-info { background: var(--fr-info-soft); color: var(--fr-info-text); }
|
|
.fr-badge.fr-tone-accent { background: var(--fr-accent-soft); color: var(--fr-accent-text); }
|
|
|
|
.fr-tone-text-neutral { color: var(--fr-text-2); }
|
|
.fr-tone-text-accent { color: var(--fr-accent-text); }
|
|
.fr-tone-text-good { color: var(--fr-good-text); }
|
|
.fr-tone-text-warn { color: var(--fr-warn-text); }
|
|
.fr-tone-text-crit { color: var(--fr-crit-text); }
|
|
.fr-tone-text-info { color: var(--fr-info-text); }
|
|
|
|
.fr-callout {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
gap: var(--fr-space-3);
|
|
padding: var(--fr-space-3) var(--fr-space-4);
|
|
border-radius: var(--fr-radius-control);
|
|
background: var(--fr-layer-hover);
|
|
}
|
|
.fr-callout-mark {
|
|
display: inline-grid;
|
|
place-items: center;
|
|
width: 24px;
|
|
height: 24px;
|
|
flex: none;
|
|
border-radius: var(--fr-radius-full);
|
|
font-size: var(--fr-fs-xs);
|
|
font-weight: var(--fr-fw-strong);
|
|
background: var(--fr-layer-pressed);
|
|
color: var(--fr-text);
|
|
}
|
|
.fr-callout-body { display: flex; flex-direction: column; gap: var(--fr-space-half); min-width: 0; }
|
|
.fr-callout-title { margin: 0; font-weight: var(--fr-fw-strong); font-size: var(--fr-fs-sm); color: var(--fr-text); }
|
|
.fr-callout-text { margin: 0; font-size: var(--fr-fs-sm); color: var(--fr-text-2); overflow-wrap: break-word; }
|
|
.fr-callout.fr-tone-good { background: var(--fr-good-soft); }
|
|
.fr-callout.fr-tone-good .fr-callout-mark { background: var(--fr-good-text); color: var(--fr-surface-2); }
|
|
.fr-callout.fr-tone-good .fr-callout-title { color: var(--fr-good-text); }
|
|
.fr-callout.fr-tone-warn { background: var(--fr-warn-soft); }
|
|
.fr-callout.fr-tone-warn .fr-callout-mark { background: var(--fr-warn-text); color: var(--fr-surface-2); }
|
|
.fr-callout.fr-tone-warn .fr-callout-title { color: var(--fr-warn-text); }
|
|
.fr-callout.fr-tone-crit { background: var(--fr-crit-soft); }
|
|
.fr-callout.fr-tone-crit .fr-callout-mark { background: var(--fr-crit-text); color: var(--fr-surface-2); }
|
|
.fr-callout.fr-tone-crit .fr-callout-title { color: var(--fr-crit-text); }
|
|
.fr-callout.fr-tone-info { background: var(--fr-info-soft); }
|
|
.fr-callout.fr-tone-info .fr-callout-mark { background: var(--fr-info-text); color: var(--fr-surface-2); }
|
|
.fr-callout.fr-tone-info .fr-callout-title { color: var(--fr-info-text); }
|
|
|
|
/* Text on a soft tint reads in the text colour, not the tint's own: keep body copy legible. */
|
|
.fr-callout.fr-tone-good .fr-callout-text,
|
|
.fr-callout.fr-tone-warn .fr-callout-text,
|
|
.fr-callout.fr-tone-crit .fr-callout-text,
|
|
.fr-callout.fr-tone-info .fr-callout-text { color: var(--fr-text-soft); }
|
|
|
|
.fr-kv { margin: 0; display: flex; flex-direction: column; }
|
|
.fr-kv-row {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: baseline;
|
|
gap: var(--fr-space-4);
|
|
padding: var(--fr-space-2) 0;
|
|
border-bottom: 1px solid var(--fr-border);
|
|
}
|
|
.fr-kv-row:last-child { border-bottom: 0; }
|
|
.fr-kv-label { color: var(--fr-text-2); min-width: 0; }
|
|
.fr-kv-value {
|
|
margin: 0;
|
|
color: var(--fr-text);
|
|
font-variant-numeric: tabular-nums;
|
|
text-align: right;
|
|
overflow-wrap: anywhere;
|
|
}
|
|
.fr-kv-value.fr-tone-text-neutral { color: var(--fr-text); }
|
|
|
|
/* ---- States --------------------------------------------------------------- */
|
|
.fr-skeleton { display: flex; flex-direction: column; gap: var(--fr-space-2); padding: var(--fr-space-1) 0; }
|
|
.fr-skel {
|
|
display: block;
|
|
border-radius: var(--fr-space-1);
|
|
background: var(--fr-layer-pressed);
|
|
animation: fr-pulse 1.2s ease-in-out infinite;
|
|
}
|
|
.fr-skel-line { height: 12px; width: 100%; }
|
|
.fr-skel-short { width: 60%; }
|
|
.fr-skel-tiny { width: 32%; }
|
|
.fr-skel-figure { height: 32px; width: 48%; }
|
|
.fr-skel-block { width: 100%; border-radius: var(--fr-radius-control); }
|
|
.fr-skel-row { height: 40px; width: 100%; }
|
|
@keyframes fr-pulse {
|
|
0%, 100% { opacity: 0.3; }
|
|
50% { opacity: 0.85; }
|
|
}
|
|
|
|
.fr-empty {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
text-align: center;
|
|
gap: var(--fr-space-2);
|
|
padding: var(--fr-space-6) var(--fr-space-4);
|
|
}
|
|
.fr-empty-mark {
|
|
width: 32px;
|
|
height: 32px;
|
|
border-radius: var(--fr-radius-full);
|
|
border: 2px dashed var(--fr-border-3);
|
|
}
|
|
.fr-empty-title { margin: 0; font-weight: var(--fr-fw-strong); color: var(--fr-text); }
|
|
.fr-empty-reason { margin: 0; max-width: 40ch; color: var(--fr-text-2); }
|
|
|
|
.fr-error {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: flex-start;
|
|
gap: var(--fr-space-3);
|
|
padding: var(--fr-space-4);
|
|
border-radius: var(--fr-radius-control);
|
|
background: var(--fr-crit-soft);
|
|
}
|
|
.fr-error-mark {
|
|
display: inline-grid;
|
|
place-items: center;
|
|
width: 24px;
|
|
height: 24px;
|
|
flex: none;
|
|
border-radius: var(--fr-radius-full);
|
|
background: var(--fr-crit-text);
|
|
color: var(--fr-surface-2);
|
|
font-weight: var(--fr-fw-strong);
|
|
font-size: var(--fr-fs-xs);
|
|
}
|
|
.fr-error-body { flex: 1 1 160px; min-width: 0; display: flex; flex-direction: column; gap: var(--fr-space-half); }
|
|
.fr-error-title { margin: 0; font-weight: var(--fr-fw-strong); color: var(--fr-crit-text); }
|
|
.fr-error-cause { margin: 0; color: var(--fr-text-soft); overflow-wrap: break-word; }
|
|
|
|
/* ---- Layout --------------------------------------------------------------- */
|
|
.fr-stack { display: flex; min-width: 0; }
|
|
.fr-stack-col { flex-direction: column; }
|
|
.fr-stack-row { flex-direction: row; flex-wrap: wrap; }
|
|
.fr-stack-row.fr-nowrap { flex-wrap: nowrap; }
|
|
.fr-stack > * { min-width: 0; }
|
|
.fr-gap-none { gap: 0; }
|
|
.fr-gap-inner { gap: var(--fr-space-2); }
|
|
.fr-gap-group { gap: var(--fr-gap-stack); }
|
|
.fr-gap-section { gap: var(--fr-space-6); }
|
|
.fr-gap-card { gap: var(--fr-gap-card); }
|
|
.fr-align-start { align-items: flex-start; }
|
|
.fr-align-center { align-items: center; }
|
|
.fr-align-end { align-items: flex-end; }
|
|
.fr-align-baseline { align-items: baseline; }
|
|
.fr-justify-center { justify-content: center; }
|
|
.fr-justify-end { justify-content: flex-end; }
|
|
.fr-justify-between { justify-content: space-between; }
|
|
|
|
.fr-grid { display: grid; min-width: 0; }
|
|
.fr-grid > * { min-width: 0; }
|
|
.fr-grid-narrow { grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); }
|
|
.fr-grid-medium { grid-template-columns: repeat(auto-fit, minmax(min(100%, 248px), 1fr)); }
|
|
.fr-grid-wide { grid-template-columns: repeat(auto-fit, minmax(min(100%, 360px), 1fr)); }
|
|
.fr-span-all { grid-column: 1 / -1; min-width: 0; display: flex; flex-direction: column; }
|
|
.fr-span-all > * { flex: 1; }
|
|
|
|
.fr-box { min-width: 0; border-radius: var(--fr-radius-control); }
|
|
.fr-pad-none { padding: 0; }
|
|
.fr-pad-inner { padding: var(--fr-space-2); }
|
|
.fr-pad-group { padding: var(--fr-space-4); }
|
|
.fr-pad-section { padding: var(--fr-space-6); }
|
|
.fr-box.fr-raised { background: var(--fr-surface-2); border: 1px solid var(--fr-border); }
|
|
.fr-box.fr-sunk { background: var(--fr-layer-hover); }
|
|
|
|
.fr-card {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--fr-gap-stack);
|
|
min-width: 0;
|
|
padding: var(--fr-pad-card);
|
|
border-radius: var(--fr-radius-card);
|
|
}
|
|
.fr-card.fr-raised {
|
|
background: var(--fr-surface-2);
|
|
border: 1px solid var(--fr-border);
|
|
box-shadow: var(--fr-shadow-card);
|
|
}
|
|
.fr-card.fr-sunk { background: var(--fr-layer-hover); }
|
|
.fr-card.fr-clear { padding: 0; }
|
|
.fr-card-head { display: flex; flex-direction: column; gap: var(--fr-space-half); min-width: 0; }
|
|
.fr-card-title { margin: 0; font-size: var(--fr-fs-sm); font-weight: var(--fr-fw-strong); line-height: var(--fr-lh-heading); color: var(--fr-text); }
|
|
.fr-card-sub { margin: 0; font-size: var(--fr-fs-xs); color: var(--fr-text-2); }
|
|
.fr-card-body { display: flex; flex-direction: column; gap: var(--fr-gap-stack); min-width: 0; }
|
|
|
|
.fr-tabs { display: flex; flex-direction: column; gap: var(--fr-space-4); min-width: 0; }
|
|
.fr-tablist {
|
|
display: flex;
|
|
gap: var(--fr-space-4);
|
|
border-bottom: 1px solid var(--fr-border);
|
|
overflow-x: auto;
|
|
scrollbar-width: none;
|
|
}
|
|
.fr-tab {
|
|
appearance: none;
|
|
border: 0;
|
|
background: none;
|
|
padding: var(--fr-space-2) 0;
|
|
min-height: 40px;
|
|
font: inherit;
|
|
font-weight: var(--fr-fw-medium);
|
|
color: var(--fr-text-2);
|
|
border-bottom: 2px solid transparent;
|
|
margin-bottom: -1px;
|
|
cursor: pointer;
|
|
white-space: nowrap;
|
|
transition: color var(--fr-dur-fast) var(--fr-ease-out), border-color var(--fr-dur-fast) var(--fr-ease-out);
|
|
}
|
|
.fr-tab:hover { color: var(--fr-text); }
|
|
.fr-tab[aria-selected="true"] { color: var(--fr-text); border-bottom-color: var(--fr-accent); }
|
|
.fr-tabpanel { min-width: 0; border-radius: var(--fr-space-1); }
|
|
.fr-tabpanel[hidden] { display: none; }
|
|
|
|
.fr-divider { width: 100%; height: 1px; border: 0; margin: 0; background: var(--fr-border); }
|
|
|
|
/* ---- Data ----------------------------------------------------------------- */
|
|
.fr-stat { display: flex; flex-direction: column; gap: var(--fr-space-2); min-width: 0; }
|
|
.fr-stat-label { margin: 0; color: var(--fr-text-2); font-size: var(--fr-fs-sm); line-height: var(--fr-lh-heading); overflow-wrap: break-word; }
|
|
.fr-stat-value {
|
|
margin: 0;
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: baseline;
|
|
gap: var(--fr-space-1);
|
|
min-width: 0;
|
|
}
|
|
.fr-stat-figure {
|
|
font-size: var(--fr-fs-2xl);
|
|
font-weight: var(--fr-fw-strong);
|
|
line-height: var(--fr-lh-display);
|
|
letter-spacing: var(--fr-tracking-display);
|
|
font-variant-numeric: tabular-nums;
|
|
color: var(--fr-text);
|
|
overflow-wrap: anywhere;
|
|
}
|
|
.fr-stat-unit { color: var(--fr-text-2); font-size: var(--fr-fs-sm); font-weight: var(--fr-fw-medium); }
|
|
.fr-stat-delta {
|
|
margin: 0;
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: baseline;
|
|
gap: var(--fr-space-1) var(--fr-space-2);
|
|
font-size: var(--fr-fs-xs);
|
|
}
|
|
.fr-delta { display: inline-flex; align-items: baseline; gap: var(--fr-space-1); font-weight: var(--fr-fw-medium); font-variant-numeric: tabular-nums; }
|
|
.fr-delta-arrow { font-size: var(--fr-fs-xs); }
|
|
.fr-stat-cmp { color: var(--fr-text-3); }
|
|
/* The line stretches with the tile; its end marker sits over it in pixels, so it is round
|
|
at any width. */
|
|
.fr-spark-wrap { position: relative; display: block; width: 100%; min-width: 0; }
|
|
.fr-spark { display: block; width: 100%; height: 28px; overflow: visible; }
|
|
.fr-spark-end {
|
|
position: absolute;
|
|
width: 6px;
|
|
height: 6px;
|
|
border-radius: var(--fr-radius-full);
|
|
transform: translate(-50%, -50%);
|
|
background: var(--fr-accent);
|
|
pointer-events: none;
|
|
}
|
|
.fr-spark-line { fill: none; stroke-width: 1.5; stroke-linejoin: round; stroke-linecap: round; }
|
|
.fr-spark-area { stroke: none; opacity: 0.12; }
|
|
.fr-tone-mark-accent .fr-spark-line { stroke: var(--fr-accent); }
|
|
.fr-tone-mark-accent .fr-spark-area { fill: var(--fr-accent); }
|
|
.fr-tone-mark-accent .fr-spark-end { background: var(--fr-accent); }
|
|
.fr-spark-none { color: var(--fr-text-3); }
|
|
|
|
.fr-progress-block { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--fr-space-1) var(--fr-space-3); align-items: center; }
|
|
.fr-progress-label { grid-column: 1; color: var(--fr-text); font-size: var(--fr-fs-sm); }
|
|
.fr-progress-value { grid-column: 2; grid-row: 1; color: var(--fr-text-2); font-size: var(--fr-fs-xs); font-variant-numeric: tabular-nums; text-align: right; }
|
|
.fr-progress { grid-column: 1 / -1; }
|
|
.fr-progress-track {
|
|
display: block;
|
|
height: 8px;
|
|
border-radius: var(--fr-radius-full);
|
|
background: var(--fr-layer-track);
|
|
overflow: hidden;
|
|
}
|
|
.fr-progress-fill {
|
|
display: block;
|
|
height: 100%;
|
|
border-radius: var(--fr-radius-full);
|
|
background: var(--fr-accent);
|
|
transition: width var(--fr-dur-slow) var(--fr-ease-out);
|
|
}
|
|
.fr-tone-mark-good .fr-progress-fill { background: var(--fr-good); }
|
|
.fr-tone-mark-warn .fr-progress-fill { background: var(--fr-warn); }
|
|
.fr-tone-mark-crit .fr-progress-fill { background: var(--fr-crit); }
|
|
.fr-tone-mark-info .fr-progress-fill { background: var(--fr-info); }
|
|
|
|
.fr-table-block { display: flex; flex-direction: column; gap: var(--fr-space-3); min-width: 0; }
|
|
.fr-table-tools { display: flex; flex-direction: column; gap: var(--fr-space-1); max-width: 320px; }
|
|
.fr-table-scroll {
|
|
overflow: auto;
|
|
min-width: 0;
|
|
border: 1px solid var(--fr-border);
|
|
border-radius: var(--fr-radius-control);
|
|
}
|
|
.fr-table {
|
|
width: 100%;
|
|
border-collapse: separate;
|
|
border-spacing: 0;
|
|
font-size: var(--fr-fs-sm);
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
.fr-table th,
|
|
.fr-table td {
|
|
padding: var(--fr-space-3) var(--fr-space-4);
|
|
text-align: left;
|
|
vertical-align: middle;
|
|
border-bottom: 1px solid var(--fr-border);
|
|
white-space: nowrap;
|
|
color: var(--fr-text);
|
|
}
|
|
.fr-table thead th {
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 1;
|
|
background: var(--fr-surface-2);
|
|
color: var(--fr-text-2);
|
|
font-size: var(--fr-fs-xs);
|
|
font-weight: var(--fr-fw-strong);
|
|
}
|
|
.fr-table tbody th { font-weight: var(--fr-fw-medium); }
|
|
.fr-table tbody tr:last-child > * { border-bottom: 0; }
|
|
.fr-table tbody tr:hover > * { background: var(--fr-layer-hover); }
|
|
.fr-table .fr-num { text-align: right; }
|
|
.fr-th-sort {
|
|
appearance: none;
|
|
border: 0;
|
|
background: none;
|
|
padding: 0;
|
|
font: inherit;
|
|
color: inherit;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--fr-space-1);
|
|
cursor: pointer;
|
|
min-height: 24px;
|
|
border-radius: var(--fr-space-1);
|
|
}
|
|
.fr-num .fr-th-sort { flex-direction: row-reverse; }
|
|
.fr-th-sort:hover { color: var(--fr-text); }
|
|
.fr-sort-mark { color: var(--fr-text-3); font-size: var(--fr-fs-xs); }
|
|
.fr-table-nomatch td { white-space: normal; color: var(--fr-text-2); }
|
|
.fr-table-nomatch td > * + * { margin-left: var(--fr-space-3); }
|
|
.fr-table-count { margin: 0; color: var(--fr-text-3); font-size: var(--fr-fs-xs); }
|
|
|
|
/* ---- Charts --------------------------------------------------------------- */
|
|
.fr-chart { margin: 0; display: flex; flex-direction: column; gap: var(--fr-space-2); min-width: 0; }
|
|
.fr-chart-head { display: flex; flex-direction: column; gap: var(--fr-space-half); }
|
|
.fr-chart-title { margin: 0; font-weight: var(--fr-fw-strong); color: var(--fr-text); line-height: var(--fr-lh-heading); }
|
|
.fr-chart-sub { margin: 0; color: var(--fr-text-2); font-size: var(--fr-fs-xs); }
|
|
.fr-axis-caption { margin: 0; color: var(--fr-text-3); font-size: var(--fr-fs-xs); }
|
|
.fr-axis-caption-x { text-align: center; }
|
|
.fr-chart-plot { position: relative; width: 100%; min-width: 0; }
|
|
.fr-chart-svg { display: block; max-width: 100%; height: auto; overflow: visible; }
|
|
.fr-chart-fail { margin: 0; color: var(--fr-text-2); }
|
|
.fr-chart-gridline { stroke: var(--fr-chart-grid); stroke-width: 1; }
|
|
.fr-chart-baseline { stroke: var(--fr-chart-axis); stroke-width: 1; }
|
|
.fr-chart-tick {
|
|
fill: var(--fr-text-3);
|
|
font-family: var(--fr-font-ui);
|
|
font-size: var(--fr-fs-xs);
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
.fr-chart-endlabel { fill: var(--fr-text-2); font-size: var(--fr-fs-xs); font-weight: var(--fr-fw-medium); }
|
|
.fr-line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
|
|
.fr-area { stroke: none; opacity: 0.22; }
|
|
.fr-line-dot { stroke: var(--fr-surface-2); stroke-width: 1.5; }
|
|
.fr-bar,
|
|
.fr-cell,
|
|
.fr-point { stroke: none; }
|
|
.fr-point { fill-opacity: 0.85; }
|
|
.fr-hit { fill: transparent; stroke: none; }
|
|
.fr-crosshair { stroke: var(--fr-border-3); stroke-width: 1; stroke-dasharray: 3 3; pointer-events: none; }
|
|
.fr-point-ring { fill: none; stroke: var(--fr-text); stroke-width: 1.5; pointer-events: none; }
|
|
.fr-end-dot { stroke: none; }
|
|
|
|
/* The categorical slots and the ramp, as stroke for lines and fill for everything else. */
|
|
.fr-line.fr-cat-1, .fr-scope-trace.fr-cat-1, .fr-wave-trace.fr-cat-1 { stroke: var(--fr-cat-1); }
|
|
.fr-line.fr-cat-2, .fr-scope-trace.fr-cat-2, .fr-wave-trace.fr-cat-2 { stroke: var(--fr-cat-2); }
|
|
.fr-line.fr-cat-3, .fr-scope-trace.fr-cat-3, .fr-wave-trace.fr-cat-3 { stroke: var(--fr-cat-3); }
|
|
.fr-line.fr-cat-4, .fr-scope-trace.fr-cat-4, .fr-wave-trace.fr-cat-4 { stroke: var(--fr-cat-4); }
|
|
.fr-line.fr-cat-5, .fr-scope-trace.fr-cat-5, .fr-wave-trace.fr-cat-5 { stroke: var(--fr-cat-5); }
|
|
.fr-line.fr-cat-6, .fr-scope-trace.fr-cat-6, .fr-wave-trace.fr-cat-6 { stroke: var(--fr-cat-6); }
|
|
.fr-line.fr-cat-other { stroke: var(--fr-cat-other); }
|
|
.fr-cat-1:not(.fr-line, .fr-scope-trace, .fr-wave-trace) { fill: var(--fr-cat-1); background: var(--fr-cat-1); }
|
|
.fr-cat-2:not(.fr-line, .fr-scope-trace, .fr-wave-trace) { fill: var(--fr-cat-2); background: var(--fr-cat-2); }
|
|
.fr-cat-3:not(.fr-line, .fr-scope-trace, .fr-wave-trace) { fill: var(--fr-cat-3); background: var(--fr-cat-3); }
|
|
.fr-cat-4:not(.fr-line, .fr-scope-trace, .fr-wave-trace) { fill: var(--fr-cat-4); background: var(--fr-cat-4); }
|
|
.fr-cat-5:not(.fr-line, .fr-scope-trace, .fr-wave-trace) { fill: var(--fr-cat-5); background: var(--fr-cat-5); }
|
|
.fr-cat-6:not(.fr-line, .fr-scope-trace, .fr-wave-trace) { fill: var(--fr-cat-6); background: var(--fr-cat-6); }
|
|
.fr-cat-other:not(.fr-line) { fill: var(--fr-cat-other); background: var(--fr-cat-other); }
|
|
.fr-seq-1 { fill: var(--fr-seq-1); background: var(--fr-seq-1); }
|
|
.fr-seq-2 { fill: var(--fr-seq-2); background: var(--fr-seq-2); }
|
|
.fr-seq-3 { fill: var(--fr-seq-3); background: var(--fr-seq-3); }
|
|
.fr-seq-4 { fill: var(--fr-seq-4); background: var(--fr-seq-4); }
|
|
.fr-seq-5 { fill: var(--fr-seq-5); background: var(--fr-seq-5); }
|
|
.fr-seq-6 { fill: var(--fr-seq-6); background: var(--fr-seq-6); }
|
|
.fr-seq-7 { fill: var(--fr-seq-7); background: var(--fr-seq-7); }
|
|
.fr-seq-8 { fill: var(--fr-seq-8); background: var(--fr-seq-8); }
|
|
.fr-seq-9 { fill: var(--fr-seq-9); background: var(--fr-seq-9); }
|
|
|
|
.fr-legend {
|
|
margin: 0;
|
|
padding: 0;
|
|
list-style: none;
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: var(--fr-space-1) var(--fr-space-4);
|
|
font-size: var(--fr-fs-xs);
|
|
color: var(--fr-text-2);
|
|
}
|
|
.fr-legend-item { display: inline-flex; align-items: center; gap: var(--fr-space-2); }
|
|
.fr-legend-swatch { width: 12px; height: 12px; border-radius: var(--fr-radius-mark); flex: none; }
|
|
|
|
.fr-tip {
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
z-index: 3;
|
|
pointer-events: none;
|
|
transition: transform var(--fr-dur-fast) var(--fr-ease-out);
|
|
}
|
|
.fr-tip-card {
|
|
transform: translateY(-100%);
|
|
min-width: 160px;
|
|
max-width: 240px;
|
|
padding: var(--fr-space-2) var(--fr-space-3);
|
|
border-radius: var(--fr-radius-control);
|
|
background: var(--fr-surface-3);
|
|
border: 1px solid var(--fr-border-2);
|
|
box-shadow: var(--fr-shadow-2);
|
|
font-size: var(--fr-fs-xs);
|
|
color: var(--fr-text);
|
|
}
|
|
.fr-tip-flip .fr-tip-card { transform: translate(-100%, -100%); }
|
|
.fr-tip-head { margin: 0 0 var(--fr-space-1); font-weight: var(--fr-fw-strong); }
|
|
.fr-tip-rows { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: var(--fr-space-1); }
|
|
.fr-tip-row { display: flex; align-items: center; gap: var(--fr-space-2); }
|
|
.fr-tip-name { color: var(--fr-text-2); flex: 1; min-width: 0; }
|
|
.fr-tip-value { font-variant-numeric: tabular-nums; font-weight: var(--fr-fw-medium); }
|
|
|
|
.fr-chart-data > summary {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--fr-space-2);
|
|
list-style: none;
|
|
min-height: 24px;
|
|
color: var(--fr-text-2);
|
|
font-size: var(--fr-fs-xs);
|
|
cursor: pointer;
|
|
border-radius: var(--fr-space-1);
|
|
}
|
|
.fr-chart-data > summary::-webkit-details-marker { display: none; }
|
|
.fr-chart-data > summary::before {
|
|
content: "";
|
|
border-left: 5px solid currentColor;
|
|
border-top: 4px solid transparent;
|
|
border-bottom: 4px solid transparent;
|
|
transition: transform var(--fr-dur-fast) var(--fr-ease-out);
|
|
}
|
|
.fr-chart-data[open] > summary::before { transform: rotate(90deg); }
|
|
.fr-chart-data > summary:hover { color: var(--fr-text); }
|
|
|
|
/* A heatmap's scale: its nine steps between the lowest and highest value. */
|
|
.fr-scale { display: flex; align-items: center; gap: var(--fr-space-2); font-size: var(--fr-fs-xs); color: var(--fr-text-2); font-variant-numeric: tabular-nums; }
|
|
.fr-scale-steps { display: flex; gap: var(--fr-space-half); }
|
|
.fr-scale-step { width: 16px; height: 12px; border-radius: var(--fr-radius-mark); }
|
|
.fr-chart-data[open] > summary { margin-bottom: var(--fr-space-2); }
|
|
|
|
.fr-donut { display: flex; flex-wrap: wrap; align-items: center; gap: var(--fr-space-6); }
|
|
.fr-donut-figure { position: relative; width: 180px; height: 180px; flex: none; }
|
|
.fr-donut-svg { display: block; width: 100%; height: 100%; }
|
|
.fr-slice { stroke: var(--fr-surface-2); stroke-width: 2; transition: opacity var(--fr-dur-fast) var(--fr-ease-out); }
|
|
.fr-slice-dim { opacity: 0.35; }
|
|
/* The hole is its own disc in the card's colour, so the total reads against the card and
|
|
never against a slice under its box. */
|
|
.fr-donut-centre {
|
|
position: absolute;
|
|
inset: 32px;
|
|
border-radius: var(--fr-radius-full);
|
|
background: var(--fr-surface-2);
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
text-align: center;
|
|
pointer-events: none;
|
|
padding: 0 var(--fr-space-2);
|
|
}
|
|
.fr-donut-centre-value { font-size: var(--fr-fs-lg); font-weight: var(--fr-fw-strong); font-variant-numeric: tabular-nums; color: var(--fr-text); line-height: var(--fr-lh-heading); }
|
|
.fr-donut-centre-label { font-size: var(--fr-fs-xs); color: var(--fr-text-2); line-height: var(--fr-lh-heading); }
|
|
.fr-donut-legend { flex: 1 1 200px; min-width: 0; margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; }
|
|
.fr-donut-item {
|
|
display: grid;
|
|
grid-template-columns: 12px minmax(0, 1fr) auto auto;
|
|
align-items: center;
|
|
gap: var(--fr-space-2);
|
|
padding: var(--fr-space-1) 0;
|
|
font-size: var(--fr-fs-xs);
|
|
color: var(--fr-text-2);
|
|
}
|
|
.fr-donut-name { color: var(--fr-text); overflow-wrap: anywhere; }
|
|
.fr-donut-val,
|
|
.fr-donut-share { font-variant-numeric: tabular-nums; text-align: right; }
|
|
.fr-donut-share { min-width: 48px; color: var(--fr-text); font-weight: var(--fr-fw-medium); }
|
|
.fr-donut-item-on .fr-donut-name { font-weight: var(--fr-fw-strong); }
|
|
|
|
/* ---- Controls ------------------------------------------------------------- */
|
|
.fr-btn {
|
|
appearance: none;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: var(--fr-space-2);
|
|
min-height: 40px;
|
|
padding: 0 var(--fr-space-4);
|
|
border-radius: var(--fr-radius-control);
|
|
border: 1px solid transparent;
|
|
font: inherit;
|
|
font-weight: var(--fr-fw-medium);
|
|
line-height: var(--fr-lh-heading);
|
|
text-decoration: none;
|
|
white-space: nowrap;
|
|
cursor: pointer;
|
|
transition: background var(--fr-dur-press) var(--fr-ease-out), border-color var(--fr-dur-press) var(--fr-ease-out),
|
|
transform var(--fr-dur-press) var(--fr-ease-out);
|
|
}
|
|
.fr-btn:active:not(:disabled) { transform: translateY(1px); }
|
|
.fr-btn:disabled { cursor: not-allowed; opacity: 0.55; }
|
|
.fr-btn-sm { min-height: 32px; padding: 0 var(--fr-space-3); font-size: var(--fr-fs-xs); }
|
|
.fr-btn-primary { background: var(--fr-primary-fill); color: var(--fr-accent-ink); }
|
|
.fr-btn-primary:hover:not(:disabled) { filter: brightness(1.06); }
|
|
.fr-btn-secondary { background: var(--fr-surface-2); color: var(--fr-text); border-color: var(--fr-border-3); }
|
|
.fr-btn-secondary:hover:not(:disabled) { background: var(--fr-surface-3); }
|
|
.fr-btn-ghost { background: transparent; color: var(--fr-text-2); }
|
|
.fr-btn-ghost:hover:not(:disabled) { background: var(--fr-layer-hover); color: var(--fr-text); }
|
|
.fr-btn-danger { background: var(--fr-crit-soft); color: var(--fr-crit-text); border-color: color-mix(in srgb, var(--fr-crit) 45%, transparent); }
|
|
.fr-btn-danger:hover:not(:disabled) { background: color-mix(in srgb, var(--fr-crit) 22%, transparent); }
|
|
|
|
.fr-field { display: flex; flex-direction: column; gap: var(--fr-space-2); min-width: 0; }
|
|
/* A field reads at a field's width, not a page's: a number or a line of text in a wide card
|
|
stops at 480 px (P4's measure, for inputs). */
|
|
.fr-card-body > .fr-field,
|
|
.fr-section-body > .fr-field,
|
|
.fr-form > .fr-field,
|
|
.fr-grid > .fr-field { max-width: 480px; }
|
|
.fr-field-head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--fr-space-3); }
|
|
.fr-field-label { color: var(--fr-text); font-weight: var(--fr-fw-medium); font-size: var(--fr-fs-sm); }
|
|
.fr-field-value { color: var(--fr-text-2); font-variant-numeric: tabular-nums; font-size: var(--fr-fs-sm); white-space: nowrap; }
|
|
.fr-field-hint { margin: 0; color: var(--fr-text-3); font-size: var(--fr-fs-xs); }
|
|
.fr-field-hint:empty { display: none; }
|
|
.fr-field-error { margin: 0; color: var(--fr-crit-text); font-size: var(--fr-fs-xs); font-weight: var(--fr-fw-medium); }
|
|
.fr-field-error[hidden] { display: none; }
|
|
.fr-field-invalid .fr-input { border-color: var(--fr-crit); }
|
|
|
|
.fr-input {
|
|
width: 100%;
|
|
min-width: 0;
|
|
height: 40px;
|
|
padding: 0 var(--fr-space-3);
|
|
border: 1px solid var(--fr-border-control);
|
|
border-radius: var(--fr-radius-control);
|
|
background: var(--fr-surface-sunk);
|
|
color: var(--fr-text);
|
|
font: inherit;
|
|
transition: border-color var(--fr-dur-fast) var(--fr-ease-out);
|
|
}
|
|
.fr-input::placeholder { color: var(--fr-text-3); }
|
|
.fr-input:hover { border-color: var(--fr-text-3); }
|
|
|
|
.fr-slider { position: relative; height: 24px; }
|
|
.fr-slider-track {
|
|
position: absolute;
|
|
left: 0;
|
|
right: 0;
|
|
top: 8px;
|
|
height: 8px;
|
|
border-radius: var(--fr-radius-full);
|
|
background: var(--fr-layer-track);
|
|
overflow: hidden;
|
|
}
|
|
.fr-slider-fill { display: block; height: 100%; background: var(--fr-accent); }
|
|
.fr-slider-input {
|
|
position: absolute;
|
|
inset: 0;
|
|
width: 100%;
|
|
margin: 0;
|
|
appearance: none;
|
|
background: transparent;
|
|
cursor: pointer;
|
|
border-radius: var(--fr-radius-full);
|
|
}
|
|
.fr-slider-input::-webkit-slider-runnable-track { height: 24px; background: transparent; }
|
|
.fr-slider-input::-webkit-slider-thumb {
|
|
appearance: none;
|
|
width: 20px;
|
|
height: 20px;
|
|
margin-top: 2px;
|
|
border-radius: var(--fr-radius-full);
|
|
background: var(--fr-surface-2);
|
|
border: 2px solid var(--fr-accent);
|
|
box-shadow: var(--fr-shadow-1);
|
|
}
|
|
.fr-slider-input::-moz-range-thumb {
|
|
width: 16px;
|
|
height: 16px;
|
|
border-radius: var(--fr-radius-full);
|
|
background: var(--fr-surface-2);
|
|
border: 2px solid var(--fr-accent);
|
|
}
|
|
.fr-slider-scale { display: flex; justify-content: space-between; color: var(--fr-text-3); font-size: var(--fr-fs-xs); font-variant-numeric: tabular-nums; }
|
|
|
|
.fr-number { display: flex; align-items: stretch; gap: var(--fr-space-2); }
|
|
.fr-number-input { flex: 1; text-align: right; font-variant-numeric: tabular-nums; }
|
|
.fr-number-unit { align-self: center; color: var(--fr-text-2); min-width: 24px; }
|
|
.fr-number-step {
|
|
appearance: none;
|
|
width: 40px;
|
|
flex: none;
|
|
border: 1px solid var(--fr-border-control);
|
|
border-radius: var(--fr-radius-control);
|
|
background: var(--fr-surface-2);
|
|
color: var(--fr-text);
|
|
font: inherit;
|
|
font-size: var(--fr-fs-lg);
|
|
cursor: pointer;
|
|
}
|
|
.fr-number-step:hover { background: var(--fr-surface-3); }
|
|
|
|
.fr-toggle-field { display: flex; align-items: center; justify-content: space-between; gap: var(--fr-space-4); }
|
|
.fr-toggle-text { display: flex; flex-direction: column; gap: var(--fr-space-half); min-width: 0; }
|
|
.fr-toggle-desc { color: var(--fr-text-2); font-size: var(--fr-fs-xs); }
|
|
.fr-toggle {
|
|
appearance: none;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--fr-space-2);
|
|
padding: 0;
|
|
border: 0;
|
|
background: none;
|
|
color: var(--fr-text-2);
|
|
font: inherit;
|
|
font-size: var(--fr-fs-xs);
|
|
font-weight: var(--fr-fw-medium);
|
|
cursor: pointer;
|
|
flex: none;
|
|
border-radius: var(--fr-radius-full);
|
|
}
|
|
.fr-toggle-knob {
|
|
position: relative;
|
|
width: 44px;
|
|
height: 24px;
|
|
border-radius: var(--fr-radius-full);
|
|
background: var(--fr-layer-track);
|
|
border: 1px solid var(--fr-border-control);
|
|
transition: background var(--fr-dur-fast) var(--fr-ease-out), border-color var(--fr-dur-fast) var(--fr-ease-out);
|
|
}
|
|
.fr-toggle-knob::after {
|
|
content: "";
|
|
position: absolute;
|
|
top: 2px;
|
|
left: 2px;
|
|
width: 18px;
|
|
height: 18px;
|
|
border-radius: var(--fr-radius-full);
|
|
background: var(--fr-text-2);
|
|
transition: transform var(--fr-dur-slow) var(--fr-ease-out), background var(--fr-dur-fast) var(--fr-ease-out);
|
|
}
|
|
.fr-toggle[aria-checked="true"] .fr-toggle-knob { background: var(--fr-accent); border-color: var(--fr-accent); }
|
|
.fr-toggle[aria-checked="true"] .fr-toggle-knob::after { transform: translateX(20px); background: var(--fr-accent-ink); }
|
|
.fr-toggle[aria-checked="true"] .fr-toggle-state { color: var(--fr-text); }
|
|
.fr-toggle-state { min-width: 24px; text-align: left; }
|
|
|
|
.fr-select { position: relative; }
|
|
.fr-select-input { appearance: none; padding-right: var(--fr-space-8); cursor: pointer; }
|
|
.fr-select-chevron {
|
|
position: absolute;
|
|
right: var(--fr-space-3);
|
|
top: 50%;
|
|
width: 8px;
|
|
height: 8px;
|
|
border-right: 2px solid var(--fr-text-2);
|
|
border-bottom: 2px solid var(--fr-text-2);
|
|
transform: translateY(-75%) rotate(45deg);
|
|
pointer-events: none;
|
|
}
|
|
|
|
.fr-seg-field { display: flex; flex-direction: column; align-items: flex-start; gap: var(--fr-space-2); min-width: 0; }
|
|
.fr-gallery-tools .fr-seg-field { flex-direction: row; align-items: center; }
|
|
.fr-segmented {
|
|
display: inline-flex;
|
|
flex-wrap: wrap;
|
|
gap: var(--fr-space-half);
|
|
padding: var(--fr-space-half);
|
|
border-radius: var(--fr-radius-control);
|
|
background: var(--fr-layer-pressed);
|
|
max-width: 100%;
|
|
}
|
|
.fr-seg {
|
|
appearance: none;
|
|
border: 0;
|
|
min-height: 32px;
|
|
padding: 0 var(--fr-space-3);
|
|
border-radius: var(--fr-space-2);
|
|
background: transparent;
|
|
color: var(--fr-text-2);
|
|
font: inherit;
|
|
font-weight: var(--fr-fw-medium);
|
|
cursor: pointer;
|
|
transition: background var(--fr-dur-fast) var(--fr-ease-out), color var(--fr-dur-fast) var(--fr-ease-out);
|
|
}
|
|
.fr-seg:hover { color: var(--fr-text); }
|
|
.fr-seg[aria-checked="true"] { background: var(--fr-surface-2); color: var(--fr-text); box-shadow: var(--fr-shadow-1); }
|
|
|
|
@media (pointer: coarse) {
|
|
.fr-btn, .fr-input, .fr-number-step { min-height: 44px; }
|
|
.fr-seg, .fr-tab { min-height: 44px; }
|
|
}
|
|
|
|
/* ---- Instruments ---------------------------------------------------------- */
|
|
.fr-instrument { display: flex; flex-direction: column; gap: var(--fr-space-3); min-width: 0; }
|
|
.fr-instrument-label { margin: 0; color: var(--fr-text); font-weight: var(--fr-fw-strong); }
|
|
|
|
.fr-gauge { display: flex; flex-direction: column; align-items: center; gap: var(--fr-space-1); }
|
|
.fr-gauge-svg { display: block; width: 100%; max-width: 200px; height: auto; overflow: visible; }
|
|
.fr-gauge-track { fill: none; stroke: var(--fr-track); stroke-width: 8; stroke-linecap: round; }
|
|
.fr-gauge-value { fill: none; stroke-width: 8; stroke-linecap: round; }
|
|
.fr-gauge-zone { fill: none; stroke-width: 3; stroke-linecap: butt; }
|
|
.fr-gauge-tick { stroke: var(--fr-text-3); stroke-width: 1.2; }
|
|
.fr-gauge-needle { stroke: var(--fr-needle); stroke-width: 2.5; stroke-linecap: round; }
|
|
.fr-gauge-hub { fill: var(--fr-needle); }
|
|
.fr-tone-stroke-accent { stroke: var(--fr-accent); }
|
|
.fr-tone-stroke-neutral { stroke: var(--fr-text-3); }
|
|
.fr-tone-stroke-good { stroke: var(--fr-good); }
|
|
.fr-tone-stroke-warn { stroke: var(--fr-warn); }
|
|
.fr-tone-stroke-crit { stroke: var(--fr-crit); }
|
|
.fr-tone-stroke-info { stroke: var(--fr-info); }
|
|
.fr-gauge-readout { margin: 0; display: flex; align-items: baseline; gap: var(--fr-space-1); }
|
|
.fr-gauge-figure { font-family: var(--fr-font-mono); font-size: var(--fr-fs-2xl); font-weight: var(--fr-fw-medium); font-variant-numeric: tabular-nums; line-height: var(--fr-lh-display); color: var(--fr-text); }
|
|
.fr-gauge-unit { color: var(--fr-text-2); font-weight: var(--fr-fw-medium); }
|
|
.fr-gauge-range { margin: 0; width: 100%; max-width: 200px; display: flex; justify-content: space-between; color: var(--fr-text-3); font-size: var(--fr-fs-xs); font-variant-numeric: tabular-nums; }
|
|
|
|
.fr-scope { display: flex; flex-direction: column; gap: var(--fr-space-3); }
|
|
.fr-scope-screen {
|
|
position: relative;
|
|
aspect-ratio: 5 / 3;
|
|
max-height: 320px;
|
|
border-radius: var(--fr-radius-control);
|
|
background: var(--fr-surface-sunk);
|
|
border: 1px solid var(--fr-border);
|
|
overflow: hidden;
|
|
}
|
|
.fr-scope-svg { position: absolute; inset: 0; width: 100%; height: 100%; }
|
|
.fr-scope-div { stroke: var(--fr-chart-grid); stroke-width: 1; vector-effect: non-scaling-stroke; }
|
|
.fr-scope-axis { stroke: var(--fr-border-3); }
|
|
.fr-scope-trace { fill: none; stroke-width: 2; stroke-linejoin: round; }
|
|
.fr-scope-scale,
|
|
.fr-scope-time {
|
|
position: absolute;
|
|
bottom: var(--fr-space-2);
|
|
padding: var(--fr-space-half) var(--fr-space-2);
|
|
border-radius: var(--fr-space-1);
|
|
background: var(--fr-surface-2);
|
|
color: var(--fr-text-2);
|
|
font-family: var(--fr-font-mono);
|
|
font-size: var(--fr-fs-xs);
|
|
}
|
|
.fr-scope-scale { left: var(--fr-space-2); }
|
|
.fr-scope-time { right: var(--fr-space-2); }
|
|
.fr-scope-chs { margin: 0; padding: 0; list-style: none; display: flex; flex-wrap: wrap; gap: var(--fr-space-2) var(--fr-space-6); }
|
|
.fr-scope-ch { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--fr-space-2); font-size: var(--fr-fs-xs); }
|
|
.fr-scope-ch-name { color: var(--fr-text); font-weight: var(--fr-fw-medium); }
|
|
.fr-scope-meas { color: var(--fr-text-2); font-family: var(--fr-font-mono); font-variant-numeric: tabular-nums; }
|
|
|
|
.fr-wave { display: flex; flex-direction: column; gap: var(--fr-space-1); }
|
|
.fr-wave-lane {
|
|
display: grid;
|
|
grid-template-columns: 48px minmax(0, 1fr) 48px;
|
|
align-items: center;
|
|
gap: var(--fr-space-3);
|
|
padding: var(--fr-space-1) var(--fr-space-2);
|
|
border-radius: var(--fr-space-2);
|
|
background: var(--fr-surface-sunk);
|
|
}
|
|
.fr-wave-name { font-family: var(--fr-font-mono); font-size: var(--fr-fs-xs); color: var(--fr-text); }
|
|
.fr-wave-svg { display: block; width: 100%; height: 24px; }
|
|
.fr-wave-trace { fill: none; stroke-width: 2; }
|
|
.fr-wave-level { font-size: var(--fr-fs-xs); color: var(--fr-text-2); text-align: right; }
|
|
.fr-wave-ruler {
|
|
margin: 0;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
padding: 0 64px 0 72px;
|
|
color: var(--fr-text-3);
|
|
font-size: var(--fr-fs-xs);
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
|
|
.fr-led {
|
|
display: grid;
|
|
grid-template-columns: 16px minmax(0, 1fr) auto;
|
|
align-items: center;
|
|
gap: var(--fr-space-3);
|
|
min-height: 32px;
|
|
}
|
|
.fr-led-lamp {
|
|
width: 16px;
|
|
height: 16px;
|
|
border-radius: var(--fr-radius-full);
|
|
border: 2px solid var(--fr-text-3);
|
|
background: transparent;
|
|
transition: background var(--fr-dur-base) var(--fr-ease-out), box-shadow var(--fr-dur-base) var(--fr-ease-out);
|
|
}
|
|
.fr-led-unknown .fr-led-lamp { border-style: dashed; }
|
|
.fr-led-on.fr-tone-mark-good .fr-led-lamp { background: var(--fr-good); border-color: var(--fr-good); box-shadow: 0 0 10px -1px var(--fr-good); }
|
|
.fr-led-on.fr-tone-mark-warn .fr-led-lamp { background: var(--fr-warn); border-color: var(--fr-warn); box-shadow: 0 0 10px -1px var(--fr-warn); }
|
|
.fr-led-on.fr-tone-mark-crit .fr-led-lamp { background: var(--fr-crit); border-color: var(--fr-crit); box-shadow: 0 0 10px -1px var(--fr-crit); }
|
|
.fr-led-on.fr-tone-mark-info .fr-led-lamp,
|
|
.fr-led-on.fr-tone-mark-accent .fr-led-lamp { background: var(--fr-info); border-color: var(--fr-info); box-shadow: 0 0 10px -1px var(--fr-info); }
|
|
.fr-led-label { color: var(--fr-text); }
|
|
.fr-led-word { color: var(--fr-text-2); font-size: var(--fr-fs-xs); font-weight: var(--fr-fw-medium); }
|
|
.fr-led-on .fr-led-word { color: var(--fr-text); }
|
|
/* A verdict says itself three ways: the lamp's colour, a mark and its word. A failure is
|
|
the loudest thing on the card: a filled --crit lamp with a glow and a --crit badge. */
|
|
.fr-led-verdict .fr-led-word { font-size: var(--fr-fs-sm); font-weight: var(--fr-fw-strong); }
|
|
.fr-led-verdict.fr-verdict-pass .fr-led-lamp { background: var(--fr-good); border-color: var(--fr-good); }
|
|
.fr-led-verdict.fr-verdict-fail .fr-led-lamp { background: var(--fr-crit); border-color: var(--fr-crit); box-shadow: 0 0 10px -1px var(--fr-crit); }
|
|
.fr-led-verdict.fr-verdict-warn .fr-led-lamp { background: var(--fr-warn); border-color: var(--fr-warn); }
|
|
.fr-led-verdict.fr-verdict-unknown .fr-led-lamp { border-style: dashed; }
|
|
.fr-verdict-mark { margin-right: var(--fr-space-1); }
|
|
/* A readout's verdict in its tone: the value's own colour would otherwise win. */
|
|
.fr-kv-value.fr-tone-text-crit { color: var(--fr-crit-text); font-weight: var(--fr-fw-strong); }
|
|
.fr-kv-value.fr-tone-text-good { color: var(--fr-good-text); font-weight: var(--fr-fw-strong); }
|
|
.fr-kv-value.fr-tone-text-warn { color: var(--fr-warn-text); font-weight: var(--fr-fw-strong); }
|
|
|
|
.fr-knob-field { display: flex; flex-direction: column; align-items: center; gap: var(--fr-space-2); }
|
|
.fr-knob {
|
|
width: 112px;
|
|
height: 112px;
|
|
border-radius: var(--fr-radius-full);
|
|
cursor: ns-resize;
|
|
touch-action: none;
|
|
}
|
|
.fr-knob-svg { display: block; width: 100%; height: 100%; }
|
|
.fr-knob-track { fill: none; stroke: var(--fr-track); stroke-width: 4; stroke-linecap: round; }
|
|
.fr-knob-fill { fill: none; stroke: var(--fr-accent); stroke-width: 4; stroke-linecap: round; }
|
|
.fr-knob-body {
|
|
fill: var(--fr-knob-lo);
|
|
stroke: var(--fr-knob-hi);
|
|
stroke-width: 2;
|
|
}
|
|
.fr-knob-pointer { stroke: var(--fr-accent); stroke-width: 3; stroke-linecap: round; }
|
|
.fr-knob-value { font-family: var(--fr-font-mono); font-size: var(--fr-fs-lg); font-variant-numeric: tabular-nums; color: var(--fr-text); }
|
|
|
|
.fr-reg { display: flex; flex-direction: column; gap: var(--fr-space-3); min-width: 0; }
|
|
.fr-reg-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--fr-space-2) var(--fr-space-4); }
|
|
.fr-reg-name { font-weight: var(--fr-fw-strong); color: var(--fr-text); }
|
|
.fr-reg-addr { font-family: var(--fr-font-mono); font-size: var(--fr-fs-xs); color: var(--fr-text-2); }
|
|
.fr-reg-value { margin-left: auto; font-family: var(--fr-font-mono); font-size: var(--fr-fs-lg); color: var(--fr-text); font-variant-numeric: tabular-nums; }
|
|
.fr-reg-scroll { overflow-x: auto; min-width: 0; padding-bottom: var(--fr-space-1); border-radius: var(--fr-space-1); }
|
|
.fr-reg-grid { display: grid; gap: var(--fr-space-half); }
|
|
.fr-reg-8 { grid-template-columns: repeat(8, minmax(40px, 1fr)); min-width: 336px; }
|
|
.fr-reg-16 { grid-template-columns: repeat(16, minmax(36px, 1fr)); min-width: 608px; }
|
|
.fr-reg-32 { grid-template-columns: repeat(32, minmax(32px, 1fr)); min-width: 1088px; }
|
|
.fr-reg-bit {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: var(--fr-space-half);
|
|
padding: var(--fr-space-1) 0;
|
|
border-radius: var(--fr-space-1);
|
|
background: var(--fr-surface-sunk);
|
|
font-family: var(--fr-font-mono);
|
|
}
|
|
.fr-reg-bitno { font-size: var(--fr-fs-xs); color: var(--fr-text-3); }
|
|
.fr-reg-bitval { font-size: var(--fr-fs-sm); color: var(--fr-text-2); }
|
|
.fr-reg-set { background: var(--fr-accent-soft); }
|
|
.fr-reg-set .fr-reg-bitval { color: var(--fr-accent-text); font-weight: var(--fr-fw-strong); }
|
|
.fr-reg-field {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: var(--fr-space-half);
|
|
min-width: 0;
|
|
padding: var(--fr-space-1);
|
|
border-top: 2px solid var(--fr-border-3);
|
|
font-size: var(--fr-fs-xs);
|
|
}
|
|
.fr-reg-field-name { color: var(--fr-text); font-weight: var(--fr-fw-medium); }
|
|
.fr-reg-field-val { color: var(--fr-text-2); font-family: var(--fr-font-mono); }
|
|
|
|
.fr-svg { display: block; width: 100%; height: auto; max-width: 480px; }
|
|
.fr-svg-text { font-family: var(--fr-font-ui); font-size: var(--fr-fs-sm); }
|
|
.fr-svg-text-sm { font-size: var(--fr-fs-xs); }
|
|
|
|
/* ---- The gallery page ----------------------------------------------------- */
|
|
.fr-gallery {
|
|
min-height: 100vh;
|
|
background: var(--fr-bg);
|
|
color: var(--fr-text);
|
|
font-family: var(--fr-font-ui);
|
|
font-size: var(--fr-fs-sm);
|
|
line-height: var(--fr-lh-body);
|
|
letter-spacing: var(--fr-tracking);
|
|
}
|
|
.fr-gallery-head {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: var(--fr-space-3) var(--fr-space-6);
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
padding: var(--fr-space-6) var(--fr-space-6) 0;
|
|
}
|
|
.fr-gallery-brand { display: inline-flex; align-items: center; gap: var(--fr-space-2); }
|
|
.fr-gallery-mark { width: 16px; height: 16px; border-radius: var(--fr-space-1); background: var(--fr-flow); }
|
|
.fr-gallery-kicker { color: var(--fr-text-2); font-weight: var(--fr-fw-medium); }
|
|
.fr-gallery-tools { display: flex; flex-wrap: wrap; align-items: center; gap: var(--fr-space-3); }
|
|
.fr-gallery-main {
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
padding: var(--fr-space-8) var(--fr-space-6) var(--fr-space-12);
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--fr-space-12);
|
|
}
|
|
.fr-gallery-section { display: flex; flex-direction: column; gap: var(--fr-space-6); min-width: 0; scroll-margin-top: var(--fr-space-6); }
|
|
.fr-gallery-hero { gap: var(--fr-space-4); }
|
|
.fr-gallery-said { margin: 0; color: var(--fr-text-2); min-height: 24px; }
|
|
|
|
|
|
/* ---- Section, code, text input, progress range (kit) ---------------------- */
|
|
.fr-section { display: flex; flex-direction: column; gap: var(--fr-space-4); min-width: 0; }
|
|
.fr-section-head { display: flex; flex-direction: column; gap: var(--fr-space-1); min-width: 0; }
|
|
.fr-section-title {
|
|
margin: 0;
|
|
color: var(--fr-text);
|
|
font-size: var(--fr-fs-lg);
|
|
font-weight: var(--fr-fw-strong);
|
|
line-height: var(--fr-lh-heading);
|
|
letter-spacing: var(--fr-tracking);
|
|
}
|
|
.fr-section-desc { margin: 0; color: var(--fr-text-2); font-size: var(--fr-fs-sm); }
|
|
.fr-section-body { display: flex; flex-direction: column; gap: var(--fr-gap-card); min-width: 0; }
|
|
.fr-code {
|
|
margin: 0;
|
|
max-height: 320px;
|
|
overflow: auto;
|
|
padding: var(--fr-space-3);
|
|
border: 1px solid var(--fr-border);
|
|
border-radius: var(--fr-radius-control);
|
|
background: var(--fr-surface-sunk);
|
|
color: var(--fr-text);
|
|
font-family: var(--fr-font-mono);
|
|
font-size: var(--fr-fs-xs);
|
|
line-height: var(--fr-lh-body);
|
|
white-space: pre;
|
|
}
|
|
.fr-code:focus-visible { outline: 2px solid var(--fr-focus); outline-offset: 2px; }
|
|
.fr-textarea { height: auto; min-height: 96px; padding: var(--fr-space-2) var(--fr-space-3); resize: vertical; line-height: var(--fr-lh-body); }
|
|
.fr-input-swatch { width: 64px; padding: var(--fr-space-1); }
|
|
.fr-progress-track { position: relative; }
|
|
.fr-progress-target {
|
|
position: absolute;
|
|
top: 0;
|
|
bottom: 0;
|
|
width: 2px;
|
|
background: var(--fr-text);
|
|
}
|
|
.fr-progress-vertical { display: flex; justify-content: flex-start; }
|
|
.fr-progress-vertical .fr-progress-track { width: 16px; height: 120px; display: flex; flex-direction: column; justify-content: flex-end; }
|
|
.fr-progress-vertical .fr-progress-fill { width: 100%; transition: height var(--fr-dur-slow) var(--fr-ease-out); }
|
|
.fr-progress-vertical .fr-progress-target { top: auto; left: 0; right: 0; width: auto; height: 2px; }
|
|
|
|
/* ---- The app view --------------------------------------------------------- */
|
|
.fr-app {
|
|
background: var(--fr-bg);
|
|
color: var(--fr-text);
|
|
font-family: var(--fr-font-ui);
|
|
font-size: var(--fr-fs-sm);
|
|
line-height: var(--fr-lh-body);
|
|
letter-spacing: var(--fr-tracking);
|
|
padding: var(--fr-space-6);
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--fr-space-4);
|
|
min-width: 0;
|
|
}
|
|
.fr-app-body { min-width: 0; max-width: 1280px; width: 100%; margin: 0 auto; }
|
|
/* A reading alone in its section is a tile, not a banner: on a wide page a KPI tile, a lamp
|
|
or a gauge keeps about the width it has in a row of four (OpenUI's KPI row), never the
|
|
page's. On a phone every card is the column's width, so their edges line up. */
|
|
@media (min-width: 600px) {
|
|
.fr-app .fr-section-body > .fr-card:only-child:has(.fr-stat, .fr-led, .fr-gauge) {
|
|
width: 100%;
|
|
max-width: 20rem;
|
|
}
|
|
.fr-app .fr-section-body > .fr-card:only-child:has(.fr-image) {
|
|
width: 100%;
|
|
max-width: 36rem;
|
|
}
|
|
}
|
|
/* An image in an app is a figure, not a wallpaper: its title above it, as a card's head,
|
|
and at most 32 rem wide however few pixels it has (a 64 px test pattern stays crisp). */
|
|
.fr-app .fr-image-img { width: 100%; max-width: 32rem; }
|
|
.fr-app .fr-image-caption {
|
|
order: -1;
|
|
color: var(--fr-text);
|
|
font-size: var(--fr-fs-sm);
|
|
font-weight: var(--fr-fw-strong);
|
|
line-height: var(--fr-lh-heading);
|
|
}
|
|
/* Everything an app can focus shows the kit's ring, the editor's own drawings (a test
|
|
report's controls) included. */
|
|
.fr-app :focus-visible,
|
|
.fr-runonly :focus-visible {
|
|
outline: 2px solid var(--fr-focus);
|
|
outline-offset: 2px;
|
|
box-shadow: none;
|
|
}
|
|
.fr-app-note { margin: 0; color: var(--fr-text-2); }
|
|
.fr-app-skeleton { display: flex; flex-direction: column; gap: var(--fr-space-2); min-width: 0; }
|
|
.fr-problems {
|
|
max-width: 1280px;
|
|
width: 100%;
|
|
margin: 0 auto;
|
|
padding: var(--fr-space-3) var(--fr-space-4);
|
|
border: 1px solid var(--fr-warn);
|
|
border-radius: var(--fr-radius-control);
|
|
background: var(--fr-warn-soft);
|
|
}
|
|
.fr-problems-title { margin: 0; color: var(--fr-warn-text); font-weight: var(--fr-fw-strong); }
|
|
.fr-problems-list { margin: var(--fr-space-2) 0 0; padding-left: var(--fr-space-5); color: var(--fr-text); }
|
|
.fr-problem-at { font-family: var(--fr-font-mono); color: var(--fr-text-soft); }
|
|
.fr-problem-hint { display: block; color: var(--fr-text-soft); }
|
|
.fr-error-hint { margin: 0; color: var(--fr-text-soft); font-size: var(--fr-fs-xs); overflow-wrap: break-word; }
|
|
.fr-figure,
|
|
.fr-image { margin: 0; display: flex; flex-direction: column; gap: var(--fr-space-2); min-width: 0; }
|
|
.fr-figure-title { margin: 0; color: var(--fr-text); font-weight: var(--fr-fw-medium); font-size: var(--fr-fs-sm); }
|
|
.fr-figure-body svg { width: 100%; height: 160px; display: block; }
|
|
.fr-image-img { max-width: 100%; height: auto; display: block; border-radius: var(--fr-radius-mark); image-rendering: pixelated; }
|
|
.fr-image-caption { color: var(--fr-text-2); font-size: var(--fr-fs-xs); }
|
|
.fr-kv-block { display: flex; flex-direction: column; gap: var(--fr-space-2); min-width: 0; }
|
|
.fr-kv-title { margin: 0; color: var(--fr-text); font-weight: var(--fr-fw-medium); }
|
|
.fr-gauge-block { display: flex; flex-direction: column; gap: var(--fr-space-2); min-width: 0; }
|
|
.fr-led-block.fr-lamp .fr-led-lamp { width: 24px; height: 24px; }
|
|
.fr-spacer { height: 0; }
|
|
.fr-spacer-inner { height: var(--fr-space-2); }
|
|
.fr-spacer-group { height: var(--fr-space-4); }
|
|
.fr-spacer-section { height: var(--fr-space-6); }
|
|
.fr-form { display: flex; flex-direction: column; gap: var(--fr-space-4); align-items: flex-start; min-width: 0; }
|
|
.fr-form > * { align-self: stretch; }
|
|
.fr-form > .fr-btn { align-self: flex-start; }
|
|
.fr-fieldset { margin: 0; padding: 0; border: 0; min-width: 0; display: flex; flex-direction: column; gap: var(--fr-space-2); }
|
|
.fr-range-pair { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: var(--fr-space-3); }
|
|
.fr-multi { display: flex; flex-direction: column; gap: var(--fr-space-2); }
|
|
.fr-empty-block { display: flex; flex-direction: column; align-items: center; gap: var(--fr-space-3); }
|
|
.fr-app-toolbar {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: flex-end;
|
|
gap: var(--fr-space-3) var(--fr-space-6);
|
|
padding: var(--fr-space-3) var(--fr-space-6);
|
|
border-bottom: 1px solid var(--fr-border);
|
|
background: var(--fr-surface-1);
|
|
color: var(--fr-text);
|
|
font-family: var(--fr-font-ui);
|
|
font-size: var(--fr-fs-sm);
|
|
}
|
|
.fr-app-toolbar .fr-seg-field,
|
|
.fr-app-toolbar .fr-toggle-field { flex-direction: row; align-items: center; gap: var(--fr-space-3); }
|
|
.fr-app-actions { display: flex; flex-wrap: wrap; gap: var(--fr-space-2); align-items: center; }
|
|
.fr-app-runonly { text-decoration: none; }
|
|
|
|
/* ---- The agent's app: its reply streaming in, and the host's confirmations ----- */
|
|
.fr-app-streaming {
|
|
margin: 0;
|
|
padding: var(--fr-space-2) var(--fr-space-6);
|
|
color: var(--fr-text-2);
|
|
font-family: var(--fr-font-ui);
|
|
font-size: var(--fr-fs-sm);
|
|
}
|
|
.fr-confirm {
|
|
max-width: 1280px;
|
|
width: 100%;
|
|
margin: 0 auto;
|
|
padding: var(--fr-space-3) var(--fr-space-4);
|
|
border: 1px solid var(--fr-warn);
|
|
border-radius: var(--fr-radius-control);
|
|
background: var(--fr-warn-soft);
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--fr-space-2);
|
|
}
|
|
.fr-confirm-title { margin: 0; color: var(--fr-warn-text); font-weight: var(--fr-fw-strong); }
|
|
.fr-confirm-body { margin: 0; color: var(--fr-text); overflow-wrap: anywhere; }
|
|
.fr-confirm-list {
|
|
margin: 0;
|
|
padding-left: var(--fr-space-5);
|
|
color: var(--fr-text);
|
|
font-family: var(--fr-font-mono);
|
|
font-size: var(--fr-fs-xs);
|
|
overflow-wrap: anywhere;
|
|
}
|
|
.fr-confirm-actions { display: flex; flex-wrap: wrap; gap: var(--fr-space-2); }
|
|
.fr-share,
|
|
.fr-app-editor {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--fr-space-2);
|
|
padding: var(--fr-space-3) var(--fr-space-6);
|
|
border-bottom: 1px solid var(--fr-border);
|
|
background: var(--fr-surface-1);
|
|
color: var(--fr-text);
|
|
font-family: var(--fr-font-ui);
|
|
font-size: var(--fr-fs-sm);
|
|
}
|
|
.fr-share-note { margin: 0; color: var(--fr-text-2); }
|
|
.fr-app-passes .fr-field { max-width: 360px; }
|
|
.fr-share-note code { font-family: var(--fr-font-mono); font-size: var(--fr-fs-xs); font-variant-ligatures: none; color: var(--fr-text); overflow-wrap: anywhere; }
|
|
.fr-share-refused { margin: 0; color: var(--fr-crit-text); font-weight: var(--fr-fw-medium); white-space: pre-line; }
|
|
.fr-app-source { min-height: 200px; font-family: var(--fr-font-mono); font-size: var(--fr-fs-xs); }
|
|
/* ---- Why each component, the checks the app keeps, and the two layouts --------- */
|
|
.fr-app-why > summary { cursor: pointer; font-weight: var(--fr-fw-medium); color: var(--fr-text); }
|
|
.fr-why-list {
|
|
margin: var(--fr-space-2) 0 0;
|
|
padding-left: var(--fr-space-5);
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--fr-space-1);
|
|
color: var(--fr-text-2);
|
|
}
|
|
.fr-why-list b { color: var(--fr-text); font-weight: var(--fr-fw-medium); }
|
|
.fr-why-off { color: var(--fr-warn-text); }
|
|
.fr-check-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--fr-space-2); }
|
|
.fr-check { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--fr-space-1) var(--fr-space-3); }
|
|
.fr-check code { font-family: var(--fr-font-mono); font-size: var(--fr-fs-xs); font-variant-ligatures: none; color: var(--fr-text); overflow-wrap: anywhere; }
|
|
.fr-check-why { color: var(--fr-text-2); }
|
|
.fr-check-broken code { color: var(--fr-crit-text); }
|
|
.fr-check-summary { margin: 0; font-weight: var(--fr-fw-medium); color: var(--fr-text); }
|
|
.fr-check-summary-broken { color: var(--fr-crit-text); }
|
|
.fr-app-ab { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--fr-space-4); }
|
|
.fr-app-ab-col {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--fr-space-2);
|
|
min-width: 0;
|
|
padding: var(--fr-space-3);
|
|
border: 1px solid var(--fr-border);
|
|
border-radius: var(--fr-radius-card);
|
|
background: var(--fr-surface-sunk);
|
|
}
|
|
.fr-app-ab-col .fr-app { padding: var(--fr-space-3); }
|
|
.fr-app-ab-name { margin: 0; font-weight: var(--fr-fw-strong); color: var(--fr-text); }
|
|
/* Run-only mode is the page: in flow, so the page (not a box in it) scrolls, and the
|
|
editor behind it is hidden rather than covered. */
|
|
.fr-runonly {
|
|
min-height: 100vh;
|
|
background: var(--fr-bg);
|
|
color: var(--fr-text);
|
|
font-family: var(--fr-font-ui);
|
|
}
|
|
.fr-runonly-bar {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
max-width: 1328px;
|
|
margin: 0 auto;
|
|
padding: var(--fr-space-3) var(--fr-space-6) 0;
|
|
}
|
|
.fr-runonly-bar .fr-btn { text-decoration: none; }
|
|
.fr-runonly > .fr-placeholder { max-width: 1280px; margin: var(--fr-space-4) auto 0; }
|
|
|
|
@media (max-width: 479px) {
|
|
.fr-grid-narrow,
|
|
.fr-grid-medium,
|
|
.fr-grid-wide { grid-template-columns: minmax(0, 1fr); }
|
|
.fr-h1,
|
|
.fr-stat-figure,
|
|
.fr-gauge-figure { font-size: var(--fr-fs-xl); }
|
|
.fr-gallery-head { padding: var(--fr-space-4) var(--fr-space-4) 0; }
|
|
.fr-gallery-main { padding: var(--fr-space-6) var(--fr-space-4) var(--fr-space-10); gap: var(--fr-space-10); }
|
|
.fr-card { padding: var(--fr-space-4); }
|
|
.fr-donut { justify-content: center; }
|
|
.fr-app { padding: var(--fr-space-4); }
|
|
.fr-app-toolbar,
|
|
.fr-share,
|
|
.fr-app-editor { padding-left: var(--fr-space-4); padding-right: var(--fr-space-4); }
|
|
.fr-runonly-bar { padding: var(--fr-space-3) var(--fr-space-4) 0; }
|
|
.fr-app-ab { grid-template-columns: minmax(0, 1fr); }
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.fr-skel { animation: none; opacity: 0.6; }
|
|
.fr-tip { transition: none; }
|
|
}
|