/* Scrolls horizontally within its own box on a narrow viewport instead of forcing the whole page to overflow — see Table.tsx's comment. */ .ui-table-scroll { overflow-x: auto; } .ui-table { width: 100%; border-collapse: collapse; } .ui-table th { text-align: left; font-weight: 600; color: var(--muted); padding: 0.5em 0.75em; border-bottom: 1px solid var(--border); } .ui-table td { padding: 0.5em 0.75em; border-bottom: 1px solid var(--border); } .ui-table tr:last-child td { border-bottom: none; } .ui-table-empty { color: var(--muted); text-align: center; padding: 1.25em 0.75em; } /* A cell holding free-form prose (an operator- or agent-provided string, not a short discrete label) rather than open-ended growth that drags the whole table wider — caps the column and wraps within it instead. */ .ui-table-prose { max-width: 32em; white-space: normal; word-break: break-word; } /* Sortable header — the whole header cell is the click target, not a separate icon-only button next to it, same "control lives on the thing it affects" reasoning as `Badge`'s own click-to-toggle shape. */ .ui-table-sort-button { display: inline-flex; align-items: center; gap: 0.35em; background: none; border: none; padding: 0; margin: 0; font: inherit; font-weight: 600; color: inherit; cursor: pointer; } .ui-table-sort-button:hover { color: var(--fg); } .ui-table-sort-glyph { opacity: 0.6; font-size: 0.85em; } .ui-table-sort-button:hover .ui-table-sort-glyph { opacity: 1; } /* `.ui-table-th-filterable` (set on a filterable column's ``, no rule of its own) exists purely as a `:hover`/`:focus-within` selector target for the fade below — nothing to do with positioning the popover itself, which is computed in JS and rendered via a portal instead (see Table.tsx's own comment on `popoverPos` for why it isn't just `position: absolute` under this ``). The filter-icon trigger — invisible by default, `opacity` transition rather than a hard show/hide (mara: "fade in out animation"). Shown on three signals, matching Table.tsx's own comment on `filterValue`: hovering/focusing the header cell (so it's discoverable without a filter already set), the popover being open (still visible while you're using it, even if the pointer has moved off the header), or `.ui-table-filter-icon-active` — a filter is *set* on this column, so the icon stays put as a persistent "this column is filtered" indicator rather than disappearing the moment the header isn't hovered (mara: "when a filter is set, the filter icon does not disappear"). `:focus-within` (not just `:hover`) so a keyboard user tabbing to the icon sees it appear too, not just a mouse hovering. */ .ui-table-filter-icon { display: inline-flex; align-items: center; justify-content: center; margin-left: 0.35em; padding: 0.15em; background: none; border: none; border-radius: 4px; color: var(--muted); cursor: pointer; opacity: 0; transition: opacity 0.15s ease; } .ui-table-th-filterable:hover .ui-table-filter-icon, .ui-table-th-filterable:focus-within .ui-table-filter-icon, .ui-table-filter-icon-active { opacity: 1; } .ui-table-filter-icon:hover { color: var(--fg); background: var(--bg); } /* A filter is live on this column — `--purple`, theme.css's own "active tabs, links, highlights" accent, so an operator scanning the header row reads it the same way anything else marked active does. */ .ui-table-filter-icon-active { color: var(--purple); } /* `position`/`top`/`left` are inline styles, not here — Table.tsx computes them from the anchor ``'s own `getBoundingClientRect()` and renders this via a portal onto `document.body` (see its own `popoverPos` comment for the full reasoning: escaping `.ui-table-scroll`'s clip). `z-index: 10` matches the existing overlay-menu convention (`LinksMenu`/`UserMenu`), now that this sits alongside them as a `document.body`-level sibling rather than nested inside the table. */ .ui-table-filter-popover { z-index: 10; min-width: 12em; padding: 0.5em; background: var(--bg-elev); border: 1px solid var(--border); border-radius: 6px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25); } .ui-table-filter-input { width: 100%; box-sizing: border-box; background: var(--bg); color: var(--fg); border: 1px solid var(--border); border-radius: 4px; padding: 0.25em 0.5em; font: inherit; font-size: 0.9em; } /* `filterMode: "multiselect"`'s actual checkbox-list content is `MultiselectFilterOptions` (`ui/multiselect-filter/`) now — its own colocated CSS, not here. */ /* The negate toggle sits under every filter mode's own control (mara: "you should be able to change if the filter is negated or not") — a hairline rule separates it from the control above so "exclude" doesn't read as one more option belonging to that control. */ .ui-table-filter-negate { display: flex; align-items: center; gap: 0.35em; margin-top: 0.5em; padding-top: 0.5em; border-top: 1px solid var(--border); color: var(--muted); font-size: 0.85em; cursor: pointer; } /* One button clears every column's filter on this table at once (mara: "have a small reset filters btn") — text-button styling matching `.ui-table-sort-button`'s "no chrome, just a clickable label" treatment, not a full `Badge`/bordered-button — this is a quiet secondary action, not a primary one. */ .ui-table-reset-filters { display: inline-block; background: none; border: none; padding: 0; margin: 0 0 0.5em; font: inherit; font-size: 0.85em; color: var(--muted); text-decoration: underline; cursor: pointer; } .ui-table-reset-filters:hover { color: var(--fg); }