"""The shared stylesheet. Three rules govern what belongs here. 1. **Fleet-wide fixes, not per-app taste.** Every line of CSS in the fleet today is a workaround for a gradio default (dropdown height, JSON-pane height), and each is written out separately in each repo. Those belong here, once. 2. **Nothing that removes information.** In particular this stylesheet does not hide the gradio footer. DecoupleRpy_Agent does, via eleven lines of escalating selectors plus injected JavaScript that also forces light mode — see ``FOOTER_CSS`` below for why that is offered separately and opt-in. 3. **Classes the provenance pattern needs** (``docs/design/provenance-panel.md`` in the orchestrator), so a panel styled here looks the same in every app. Everything is scoped under ``.gradio-container`` so an embedded app cannot leak styles into a host page. """ from __future__ import annotations from ._palette import DARK, LIGHT CSS = f""" /* ========================================================================== bcc-ui-theme — shared stylesheet Colour lives in the theme object; this file is layout, affordance and the provenance/caveat classes. Tokens are re-declared here only where a plain CSS rule needs them (gradio's own variables do not reach these selectors). ========================================================================== */ .gradio-container {{ --bcc-subdued: {LIGHT["subdued"]}; --bcc-border: {LIGHT["border"]}; --bcc-border-control: {LIGHT["border_control"]}; --bcc-focus: {LIGHT["focus"]}; --bcc-panel: {LIGHT["panel"]}; --bcc-danger: {LIGHT["danger"]}; --bcc-accent: {LIGHT["accent"]}; }} .dark .gradio-container, .gradio-container.dark, .dark {{ --bcc-subdued: {DARK["subdued"]}; --bcc-border: {DARK["border"]}; --bcc-border-control: {DARK["border_control"]}; --bcc-focus: {DARK["focus"]}; --bcc-panel: {DARK["panel"]}; --bcc-danger: {DARK["danger"]}; --bcc-accent: {DARK["accent"]}; }} /* --- 1. Fleet-wide gradio fixes ------------------------------------------- 1a. Dropdown listbox height. Lifted verbatim from pdac-subtype-agent, where a registry-length dataset list ran off the bottom of the viewport. */ .gradio-container ul[role="listbox"], .gradio-container .wrap-inner + ul, .gradio-container .options {{ max-height: 16rem; overflow-y: auto; }} /* 1b. Bounded result panes. Opt-in by class, because a global cap on every code block would clip short ones for no reason. Apply with `gr.Code(..., elem_classes="bcc-scroll")`. pdac-genomics-agent needs this: without a cap the page height tracks payload size (~300,000px on a full-panel query before abridgement). max_lines does not do it — gradio 6.18 ignores that argument on gr.Code. */ .gradio-container .bcc-scroll .cm-editor, .gradio-container .bcc-scroll .cm-scroller, .gradio-container .bcc-scroll pre {{ max-height: 460px; overflow: auto; }} /* 1c. Tables bounded the same way, for the same reason. */ .gradio-container .bcc-scroll table {{ display: block; max-height: 420px; overflow: auto; }} /* --- 2. Accessibility ------------------------------------------------------ A visible focus indicator on every keyboard-reachable control (WCAG 2.2 SC 2.4.7 / 2.4.11). gradio's default ring is low contrast on both of our backgrounds. :focus-visible so a mouse click does not draw it. */ .gradio-container :focus-visible {{ outline: 2px solid var(--bcc-focus); outline-offset: 2px; border-radius: 2px; }} /* Never let a control's boundary rest on colour alone at <3:1. */ .gradio-container input[type="text"], .gradio-container input[type="number"], .gradio-container textarea, .gradio-container select {{ border-color: var(--bcc-border-control); }} /* --- 3. Provenance pattern ------------------------------------------------- See docs/design/provenance-panel.md (pdac-analysis-orchestrator). These classes exist so the three panels read identically in every app. */ /* The standing line that introduces the panels. */ .gradio-container .bcc-provenance-intro p {{ color: var(--bcc-subdued); font-size: 0.9em; margin: 0.25rem 0 0.5rem; }} /* The group of accordions itself — set off from the answer above it. */ .gradio-container .bcc-provenance {{ border-left: 3px solid var(--bcc-border); padding-left: 0.75rem; }} /* A panel's own sub-caption ("what this panel contains"). */ .gradio-container .bcc-panel-note p {{ color: var(--bcc-subdued); font-size: 0.875em; margin: 0 0 0.5rem; }} /* Monospace inside the Code-used panel, so a tool call reads as a call. */ .gradio-container .bcc-panel-code code, .gradio-container .bcc-panel-code pre {{ font-size: 0.875em; }} /* The caveat, next to the result it qualifies — not in a header, not inside a collapsed accordion. Deliberately loud enough to be read and quiet enough not to look like a failure: a caveat is not an error. */ .gradio-container .bcc-caveat {{ border-left: 4px solid var(--bcc-danger); background: var(--bcc-panel); padding: 0.6rem 0.9rem; border-radius: 4px; margin: 0.5rem 0; }} .gradio-container .bcc-caveat p {{ margin: 0.2rem 0; }} /* The paired action ("re-run on the registered cohort to get grounded=true"). The rule in the doc is that a caveat never appears without one. */ .gradio-container .bcc-caveat-action p {{ color: var(--bcc-subdued); font-size: 0.9em; }} /* --- 4. Restraint ---------------------------------------------------------- Long prose in a research UI is unreadable at full window width. */ .gradio-container .bcc-prose {{ max-width: 72ch; }} """ FOOTER_CSS = """ /* OPT-IN, not part of CSS. Hides the gradio footer. DecoupleRpy_Agent does this today and may want to keep doing it; it is kept out of the shared stylesheet because hiding attribution is a decision each app should make deliberately rather than inherit. NOTE this is the CSS half only. DecoupleRpy also injects JavaScript that strips the `dark` class and rewrites the URL to `?__theme=light`, which overrides the user's own theme choice on that one app. That JS is NOT reproduced here and should be removed, not ported: with this theme the app renders correctly in both modes, so there is nothing left for it to fix. */ .gradio-container footer, .gradio-container .built-with-gradio { display: none !important; } """