/* The screener's own CSS. A plugin view is an iframe of its own, so there is no Tailwind here: plain classes, the house style by hand. Colours are the app's theme variables, so the view follows its light and dark, each with its light value as the fallback for an app from before the theme; the screener's own colours get their dark values at the end. Square everything, one grey line, muted secondary text, 13px in the table, and no accent colour but the sign of a number and the verdict of a run, which reuse the same two. */ .sc-root { position: relative; display: flex; flex-direction: column; height: 100%; width: 100%; background: var(--jaspers-background, #fff); color: var(--jaspers-foreground, #171717); font: 13px/1.45 var(--jaspers-font-sans, system-ui, -apple-system, sans-serif); } /* The two bars: filters and counts above, paging and status below. */ .sc-bar { flex: 0 0 auto; display: flex; align-items: center; flex-wrap: wrap; gap: 6px; padding: 6px 8px; border-bottom: 1px solid var(--jaspers-border, #e5e5e5); } .sc-foot { border-bottom: 0; border-top: 1px solid var(--jaspers-border, #e5e5e5); } /* The element's close button sits over the top-right corner. */ .sc-top { padding-right: 40px; } /* The funnel: the screen as it goes. A row for the universe, one for each filter in its turn, and one for the stage after them, on one grid so the counts line up down the rows: the mark, what the row is, what it left, what it removed, and the first of those by name. It takes the rows it has and scrolls past a share of the view, so a long list of filters leaves the table its room. */ .sc-funnel { flex: 0 0 auto; display: grid; grid-template-columns: max-content minmax(0, max-content) max-content max-content minmax(0, 1fr); column-gap: 10px; max-height: 40%; overflow-y: auto; padding: 4px 8px; border-bottom: 1px solid var(--jaspers-border, #e5e5e5); color: var(--jaspers-muted-foreground, #737373); } .sc-funnel b { color: var(--jaspers-foreground, #171717); font-weight: 600; } .sc-step { grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; align-items: baseline; min-height: 21px; } /* A row's mark: a tick once it is in; a square, filled and pulsing while it is at work, hollow while it is still to come. */ .sc-step-mark { width: 11px; text-align: center; } .sc-step-working .sc-step-mark::before, .sc-step-pending .sc-step-mark::before { content: ''; display: inline-block; box-sizing: border-box; width: 7px; height: 7px; border: 1px solid #a3a3a3; } .sc-step-working .sc-step-mark::before { border-color: var(--jaspers-foreground, #171717); background: var(--jaspers-foreground, #171717); animation: sc-pulse 1.1s ease-in-out infinite; } .sc-step-what { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--jaspers-foreground, #171717); } .sc-step-pending .sc-step-what { color: #a3a3a3; } .sc-step-n { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; } /* What a row at work says, and the whole of what the stage after the filters says, take the rest of the row. */ .sc-step-note, .sc-step-run { grid-column: 3 / -1; min-width: 0; } .sc-step-run { display: flex; align-items: center; flex-wrap: wrap; gap: 0 10px; } .sc-step-note { white-space: nowrap; font-variant-numeric: tabular-nums; } /* The names: as many as the row has room for, and how many more there are, which stays in sight. */ .sc-step-names, .sc-step-verdict { display: flex; gap: 6px; min-width: 0; white-space: nowrap; } /* Who passed and who failed share what the row has left, and go under it when that is too little. */ .sc-step-verdict { flex: 1 1 14ch; } .sc-step-verdict b { color: inherit; } .sc-names { min-width: 0; overflow: hidden; text-overflow: ellipsis; } .sc-names-more { flex: 0 0 auto; } /* The numbers of a row arrive; they do not blink in. */ .sc-step-done > .sc-step-n, .sc-step-done > .sc-step-names { animation: sc-in 0.28s ease-out; } @keyframes sc-in { from { opacity: 0; transform: translateY(-2px); } } @keyframes sc-pulse { 50% { opacity: 0.25; } } /* How far a run is: one bar cut into what was found and what is still to be. The track is what waits. */ .sc-meter { flex: 0 0 auto; display: inline-flex; gap: 1px; width: 120px; height: 8px; background: var(--jaspers-border, #e5e5e5); } .sc-seg { display: block; min-width: 2px; } .sc-seg-pass { background: var(--jaspers-positive, #15803d); } .sc-seg-fail { background: var(--jaspers-negative, #b91c1c); } .sc-seg-unclear { background: #a16207; } .sc-seg-unverified { background: var(--jaspers-muted-foreground, #737373); } /* An error is not a fail: the same red, hatched. */ .sc-seg-error { background: repeating-linear-gradient(135deg, var(--jaspers-destructive, #dc2626) 0 2px, transparent 2px 4px); } .sc-seg-fetched, .sc-seg-running { background: var(--jaspers-foreground, #171717); } .sc-seg-running { animation: sc-pulse 1.1s ease-in-out infinite; } .sc-btn { border: 1px solid var(--jaspers-border, #e5e5e5); background: var(--jaspers-background, #fff); color: var(--jaspers-foreground, #171717); padding: 2px 8px; cursor: pointer; } .sc-btn:hover:not(:disabled) { background: var(--jaspers-muted, #f5f5f5); } .sc-btn:disabled { color: #a3a3a3; cursor: default; } .sc-chip { display: inline-flex; align-items: center; gap: 4px; border: 1px solid var(--jaspers-border, #e5e5e5); background: var(--jaspers-muted, #fafafa); padding: 1px 3px 1px 6px; white-space: nowrap; } .sc-chip-label { border: 0; background: none; color: inherit; font: inherit; padding: 0; cursor: pointer; } .sc-chip-x { border: 0; background: none; color: var(--jaspers-muted-foreground, #737373); cursor: pointer; padding: 0 3px; line-height: 1; } .sc-chip-x:hover:not(:disabled) { color: var(--jaspers-foreground, #171717); } .sc-chip-x:disabled { cursor: default; } .sc-input { border: 1px solid var(--jaspers-border, #e5e5e5); background: var(--jaspers-background, #fff); color: var(--jaspers-foreground, #171717); padding: 2px 6px; outline: none; } .sc-input:focus { border-color: var(--jaspers-foreground, #171717); } .sc-count { margin-left: auto; color: var(--jaspers-muted-foreground, #737373); white-space: nowrap; } .sc-status { color: var(--jaspers-muted-foreground, #737373); white-space: nowrap; } .sc-error { color: var(--jaspers-destructive, #dc2626); white-space: normal; } /* The table fills what is left and scrolls both ways; nothing else on the page moves. */ .sc-table-wrap { flex: 1 1 auto; overflow: auto; transition: opacity 0.12s; } /* The rows of the list before the one that is on its way. */ .sc-stale { opacity: 0.5; } .sc-table { border-collapse: collapse; font-size: 13px; width: max-content; min-width: 100%; } .sc-table th, .sc-table td { border-bottom: 1px solid var(--jaspers-border, #e5e5e5); padding: 3px 8px; white-space: nowrap; } .sc-table th { position: sticky; top: 0; z-index: 1; background: var(--jaspers-background, #fff); text-align: left; font-weight: 500; color: var(--jaspers-muted-foreground, #737373); padding: 0; } .sc-sort { width: 100%; border: 0; background: none; color: inherit; font: inherit; text-align: right; padding: 4px 8px; cursor: pointer; } .sc-sort:hover { color: var(--jaspers-foreground, #171717); } .sc-num { text-align: right; font-variant-numeric: tabular-nums; } .sc-up { color: var(--jaspers-positive, #15803d); } .sc-down { color: var(--jaspers-negative, #b91c1c); } /* The company column stays put while the numbers scroll past it. */ .sc-company { position: sticky; left: 0; background: var(--jaspers-background, #fff); z-index: 2; padding: 3px 8px; text-align: left; min-width: 190px; } th.sc-company { z-index: 3; padding: 4px 8px; } .sc-ticker { font-weight: 600; } .sc-name { display: block; color: var(--jaspers-muted-foreground, #737373); max-width: 210px; overflow: hidden; text-overflow: ellipsis; } .sc-table tbody tr:hover td { background: var(--jaspers-muted, #f5f5f5); } .sc-empty { padding: 12px; color: var(--jaspers-muted-foreground, #737373); } /* The filter dialog: a panel over the view, not a portal and not a window. */ .sc-dialog { position: absolute; inset: 0; z-index: 10; display: flex; align-items: flex-start; justify-content: center; padding: 10px; background: rgba(23, 23, 23, 0.15); } .sc-dialog-panel { display: flex; flex-direction: column; width: 100%; max-width: 760px; max-height: 100%; background: var(--jaspers-background, #fff); border: 1px solid var(--jaspers-border, #e5e5e5); box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12); } .sc-dialog-head, .sc-dialog-foot { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; padding: 6px 10px; } .sc-dialog-head { border-bottom: 1px solid var(--jaspers-border, #e5e5e5); font-weight: 600; } .sc-dialog-foot { border-top: 1px solid var(--jaspers-border, #e5e5e5); justify-content: flex-end; } .sc-dialog-body { flex: 1 1 auto; overflow: auto; padding: 10px; } .sc-section { margin-bottom: 12px; } .sc-label { display: block; margin-bottom: 4px; color: var(--jaspers-muted-foreground, #737373); font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; } .sc-check { display: inline-flex; align-items: center; gap: 5px; cursor: pointer; user-select: none; } .sc-check input { accent-color: var(--jaspers-primary, #171717); } /* One filter to a row: the field, how it is compared, the value in the unit the user types. */ .sc-filter { margin-bottom: 6px; } .sc-filter-row { display: flex; align-items: center; flex-wrap: wrap; gap: 4px; } .sc-filter-field { flex: 0 1 230px; min-width: 0; } .sc-filter-value { flex: 1 1 110px; min-width: 0; } .sc-hint { margin: 2px 0 0; color: var(--jaspers-muted-foreground, #737373); font-size: 12px; } .sc-filter .sc-error, .sc-dialog-body > .sc-error { margin: 2px 0 0; } .sc-tickers { width: 100%; resize: vertical; font: inherit; } .sc-columns { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 2px 16px; } .sc-unit { color: #a3a3a3; white-space: nowrap; } /* The question chip carries a sentence; its text truncates and its cross stays. */ .sc-chip.sc-q { display: inline-flex; align-items: center; max-width: 480px; min-width: 0; } .sc-q-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } /* The qualitative stage: the criteria and their input on the left, the run on the right. */ .sc-q-input { flex: 1 1 220px; min-width: 0; } .sc-run, .sc-verdicts { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 6px; } .sc-run { margin-left: auto; } .sc-primary { border-color: var(--jaspers-foreground, #171717); font-weight: 600; } .sc-toggle.sc-on { border-color: currentColor; background: var(--jaspers-muted, #f5f5f5); } /* A verdict is the one other thing with a colour: the sign's two, an amber, and the muted grey. */ .sc-v-pass { color: var(--jaspers-positive, #15803d); } .sc-v-fail { color: var(--jaspers-negative, #b91c1c); } .sc-v-unclear { color: #a16207; } .sc-v-unverified { color: var(--jaspers-muted-foreground, #737373); font-style: italic; } .sc-table th.sc-verdict-head { padding: 4px 8px; max-width: 140px; overflow: hidden; text-overflow: ellipsis; } .sc-verdict { text-align: left; } .sc-mark { color: var(--jaspers-destructive, #dc2626); font-weight: 600; cursor: help; } /* A company being read: a square for each step the server takes it through, the ones behind it filled, the one it is in pulsing. */ .sc-rail { display: inline-flex; align-items: center; gap: 2px; } .sc-rail i { box-sizing: border-box; width: 6px; height: 6px; border: 1px solid #a3a3a3; } .sc-rail i:last-of-type { margin-right: 4px; } .sc-rail .sc-rail-done { border-color: var(--jaspers-muted-foreground, #737373); background: var(--jaspers-muted-foreground, #737373); } .sc-rail .sc-rail-now { border-color: var(--jaspers-foreground, #171717); background: var(--jaspers-foreground, #171717); animation: sc-pulse 1.1s ease-in-out infinite; } /* A ticker with a run's answer behind it opens that company's evidence. */ .sc-ticker-open { border: 0; border-bottom: 1px dotted var(--jaspers-muted-foreground, #737373); background: none; color: inherit; font: inherit; font-weight: 600; padding: 0; cursor: pointer; } .sc-table tbody tr.sc-row-open td { background: var(--jaspers-muted, #f5f5f5); } /* The evidence pane: under the table, as tall as it needs up to under half the view. */ .sc-evidence { flex: 0 1 auto; display: flex; flex-direction: column; max-height: 45%; min-height: 80px; border-top: 1px solid var(--jaspers-border, #e5e5e5); } .sc-evidence-head { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; padding: 4px 8px; border-bottom: 1px solid var(--jaspers-border, #e5e5e5); } .sc-evidence-body { flex: 1 1 auto; overflow: auto; padding: 6px 10px 10px; } .sc-evidence-body p { margin: 0 0 4px; white-space: normal; } .sc-criterion { padding: 6px 0; border-bottom: 1px solid var(--jaspers-border, #e5e5e5); } .sc-criterion:last-child { border-bottom: 0; } .sc-question { font-weight: 600; } .sc-cite { margin: 6px 0; padding: 4px 8px; border-left: 2px solid var(--jaspers-border, #e5e5e5); background: var(--jaspers-muted, #fafafa); } .sc-cite .sc-quote { margin: 0 0 2px; } .sc-cite .sc-cite-foot { margin: 0; } .sc-cite-foot { display: flex; flex-wrap: wrap; gap: 2px 10px; color: var(--jaspers-muted-foreground, #737373); font-size: 12px; } .sc-link { border: 0; background: none; color: var(--jaspers-foreground, #171717); font: inherit; padding: 0; text-decoration: underline; cursor: pointer; } /* Dark values for the screener's own colours: faint text a step under the muted, and, on a page already near black, a backdrop with more black to dim it and a shadow with more to show. */ @media (prefers-color-scheme: dark) { .sc-btn:disabled, .sc-unit, .sc-step-pending .sc-step-what { color: #737373; } .sc-step-pending .sc-step-mark::before, .sc-rail i { border-color: #737373; } .sc-v-unclear { color: #eab308; } .sc-seg-unclear { background: #eab308; } .sc-dialog { background: rgba(0, 0, 0, 0.5); } .sc-dialog-panel { box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5); } } /* Someone who asked for less motion gets the same states, standing still. */ @media (prefers-reduced-motion: reduce) { .sc-step-working .sc-step-mark::before, .sc-seg-running, .sc-rail .sc-rail-now, .sc-step-done > .sc-step-n, .sc-step-done > .sc-step-names { animation: none; } .sc-table-wrap { transition: none; } }