/* ABD Security Models Playground. Dark operations console: slate surfaces, one blue for interaction, and a green/amber/red scale reserved for what a score actually means. */ :root, .dark, .gradio-container { --abd-bg: #0b1220; --abd-surface: #111a2b; --abd-raised: #172236; --abd-border: #1f2c44; --abd-border-strong: #2d3d59; --abd-text: #e8eef8; --abd-text-dim: #93a3bd; --abd-text-faint: #8798b5; --abd-accent: #4cc2ff; --abd-safe: #34d399; --abd-warn: #fbbf24; --abd-risk: #f87171; --abd-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; --abd-sans: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; --abd-radius: 10px; } body, gradio-app, .gradio-container { background: var(--abd-bg) !important; color: var(--abd-text) !important; font-family: var(--abd-sans) !important; } .gradio-container { /* Without an explicit width the container is a content-sized flex item, so a wide result grew the whole app and every column inside it. */ width: 100% !important; max-width: 1520px !important; margin: 0 auto !important; padding: 0 40px 56px !important; } /* Gradio paints its own light chrome on a lot of wrappers, and pads .block but not rows or columns — which left HTML blocks and form fields inset 12px from the buttons beside them. Flatten and unpad; components opt back in below. */ .gradio-container .block, .gradio-container .form, .gradio-container .panel, .gradio-container .wrap, .gradio-container .gr-group, .gradio-container .styler { background: transparent !important; border: none !important; box-shadow: none !important; padding: 0 !important; } /* gr.HTML nests its content one level deeper, with padding of its own. */ .gradio-container .html-container, .gradio-container .prose { padding: 0 !important; } /* ---------- header and hero ---------- */ .demo-header { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; padding: 26px 0 20px; border-bottom: 1px solid var(--abd-border); } .demo-header .brand { font-size: 1.3rem; font-weight: 500; letter-spacing: -0.01em; color: var(--abd-text); } .demo-header .brand b { font-weight: 700; color: var(--abd-accent); letter-spacing: 0.04em; } .demo-header .header-meta { font-family: var(--abd-mono); font-size: 0.76rem; text-transform: uppercase; letter-spacing: 0.14em; color: var(--abd-text-faint); } .demo-hero { padding: 34px 0 30px; max-width: 78ch; } .demo-hero h1 { margin: 0; font-size: clamp(1.7rem, 4.2vw, 2.5rem); line-height: 1.15; font-weight: 700; letter-spacing: -0.02em; color: var(--abd-text); } /* ---------- workbench ---------- */ /* A fixed rail and a pane that takes everything else, rather than a ratio that leaves the working column narrow on a wide screen. */ #workbench { gap: 34px !important; align-items: flex-start !important; flex-wrap: nowrap !important; } #model-rail { flex: 0 0 290px !important; min-width: 0 !important; } /* Gradio's own wrappers are content-sized and carry a 1280px cap of their own, so the workbench row grew whenever a result was wider than the form — an error message, a long marked span. Make the chain fill its parent, then flex-basis 0 splits that fixed width regardless of what is in it. */ .gradio-container .app, .gradio-container .app > .wrap, .gradio-container main.contain, .gradio-container main.contain > .column, #workbench { width: 100% !important; max-width: 100% !important; /* flex items default to min-width:auto, so content can still push a row wider than its own width. */ min-width: 0 !important; } #inference-pane { flex: 1 1 0 !important; width: auto !important; min-width: 0 !important; } .rail-title, .examples-title, .result-heading { font-family: var(--abd-mono); font-size: 0.72rem; /* an exact line box, so the two columns' headings are the same height to the pixel and the rows under them start level */ line-height: 16px; text-transform: uppercase; letter-spacing: 0.15em; color: var(--abd-text-faint); } .result-heading { margin: 30px 0 12px; padding-top: 22px; border-top: 1px solid var(--abd-border); } /* Model selector: stacked cards rather than a list of dots. */ #model-selector .wrap, #model-selector > div { display: flex !important; flex-direction: column !important; gap: 10px !important; } #model-selector label { display: flex !important; align-items: center; gap: 10px; margin: 0 !important; /* same box as an attack chip: both are a row of choices, one per column */ height: 52px !important; padding: 0 14px !important; background: var(--abd-surface) !important; border: 1px solid var(--abd-border) !important; border-radius: var(--abd-radius) !important; color: var(--abd-text-dim) !important; font-size: 0.9rem !important; font-weight: 500 !important; cursor: pointer; transition: border-color 180ms ease, background 180ms ease, color 180ms ease; } #model-selector label:hover { border-color: var(--abd-border-strong) !important; color: var(--abd-text) !important; } #model-selector label:has(input:checked) { background: var(--abd-raised) !important; border-color: var(--abd-accent) !important; color: var(--abd-text) !important; } /* Gradio paints the native control in its own accent; draw our own instead. */ #model-selector input[type="radio"] { appearance: none; -webkit-appearance: none; width: 14px; height: 14px; flex: 0 0 auto; margin: 0; border: 1.5px solid var(--abd-border-strong); border-radius: 50%; background: transparent; transition: border-color 180ms ease, box-shadow 180ms ease; } #model-selector input[type="radio"]:checked { border-color: var(--abd-accent); box-shadow: inset 0 0 0 3px var(--abd-bg), inset 0 0 0 9px var(--abd-accent); } #model-selector input[type="radio"]:focus-visible { outline: 2px solid var(--abd-accent); outline-offset: 2px; } #model-details { margin-top: 18px; } .model-card { padding: 16px; background: var(--abd-surface); border: 1px solid var(--abd-border); border-radius: var(--abd-radius); } .model-card h2 { margin: 0 0 8px; font-size: 0.98rem; font-weight: 600; color: var(--abd-text); } .model-card p { margin: 0 0 14px; font-size: 0.86rem; line-height: 1.6; color: var(--abd-text-dim); } .model-card dl { margin: 0; display: grid; gap: 8px; padding-top: 12px; border-top: 1px solid var(--abd-border); } .model-card dt { font-family: var(--abd-mono); font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.1em; color: var(--abd-text-faint); } .model-card dd { margin: 3px 0 0; font-family: var(--abd-mono); font-size: 0.76rem; color: var(--abd-text-dim); word-break: break-all; } /* ---------- the example row, first thing in every form ---------- */ .examples-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; } .example-row { display: grid !important; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px !important; margin-bottom: 10px !important; } /* One fixed cell per case, so a longer label never makes its box taller or wider than the rest of the set. */ button.example-chip { display: block !important; width: 100% !important; min-width: 0 !important; height: 52px !important; padding: 0 14px !important; line-height: 50px !important; background: var(--abd-raised) !important; border: 1px solid var(--abd-border-strong) !important; border-radius: var(--abd-radius) !important; color: var(--abd-text) !important; font-family: var(--abd-sans) !important; font-size: 0.9rem !important; font-weight: 500 !important; text-align: left !important; white-space: nowrap !important; overflow: hidden !important; text-overflow: ellipsis !important; cursor: pointer; transition: border-color 180ms ease, transform 180ms ease, background 180ms ease; } button.example-chip.risk { border-left: 3px solid var(--abd-risk) !important; padding-left: 13px !important; } button.example-chip.custom { background: transparent !important; border-style: dashed !important; color: var(--abd-text-dim) !important; } button.example-chip.custom:hover { background: var(--abd-raised) !important; color: var(--abd-text) !important; } button.example-chip.active { background: #17324e !important; border-color: var(--abd-accent) !important; box-shadow: inset 0 0 0 1px var(--abd-accent); color: #ffffff !important; font-weight: 600 !important; } button.example-chip.risk.active { border-left-color: var(--abd-risk) !important; } button.example-chip:hover { background: #1c2941 !important; border-color: var(--abd-accent) !important; transform: translateY(-1px); } button.example-chip:active { transform: translateY(0); } button.example-chip:focus-visible { outline: 2px solid var(--abd-accent) !important; outline-offset: 2px; } /* ---------- form fields ---------- */ /* The rail column spaces its children with a 16px gap and Gradio resets margins inside a block, so space the task form the same way rather than with margins that do not survive. Both columns then keep one rhythm. */ .task-form, .task-form .styler, .task-form .form { display: flex !important; flex-direction: column !important; /* Gradio nests the real children in a .styler with a 1px gap; that is the box the spacing has to land on. */ gap: 16px !important; } .gradio-container label > span, .gradio-container .block > label > span:first-child { font-size: 0.84rem !important; font-weight: 600 !important; color: var(--abd-text) !important; margin-bottom: 4px !important; } .gradio-container .info, .gradio-container div[data-testid="block-info"] { font-size: 0.79rem !important; line-height: 1.5 !important; color: var(--abd-text-faint) !important; margin-bottom: 8px !important; } .gradio-container textarea, .gradio-container input[type="text"] { background: var(--abd-surface) !important; border: 1px solid var(--abd-border) !important; border-radius: var(--abd-radius) !important; color: var(--abd-text) !important; padding: 12px 14px !important; transition: border-color 160ms ease, box-shadow 160ms ease; } .mono-field textarea, .mono-field input[type="text"] { font-family: var(--abd-mono) !important; font-size: 0.83rem !important; line-height: 1.6 !important; } /* Gradio sizes a textarea by writing an inline height that tracks its content, so every case would resize the form. Pin the height per field and scroll. */ .field-h2 textarea { --field-lines: 2; } .field-h3 textarea { --field-lines: 3; } .field-h5 textarea { --field-lines: 5; } .field-h6 textarea { --field-lines: 6; } .field-h8 textarea { --field-lines: 8; } .field-h2 textarea, .field-h3 textarea, .field-h5 textarea, .field-h6 textarea, .field-h8 textarea { height: calc(var(--field-lines) * 1.6 * 0.83rem + 24px) !important; min-height: calc(var(--field-lines) * 1.6 * 0.83rem + 24px) !important; max-height: calc(var(--field-lines) * 1.6 * 0.83rem + 24px) !important; overflow-y: auto !important; } .gradio-container textarea:focus, .gradio-container input[type="text"]:focus { border-color: var(--abd-accent) !important; box-shadow: 0 0 0 3px rgba(76, 194, 255, 0.16) !important; outline: none !important; } .task-form > .block, .task-form .form > .block { margin-bottom: 0 !important; } /* The JSON viewer's copy button keeps a white chip in both colour schemes. */ .gradio-container .icon-button-wrapper { background: var(--abd-surface) !important; border: 1px solid var(--abd-border) !important; border-radius: 6px !important; color: var(--abd-text-dim) !important; } .gradio-container .icon-button-wrapper button, .gradio-container button.icon-button { background: transparent !important; color: var(--abd-text-dim) !important; } /* The JSON viewer keeps a light chip for its label; flatten it like the rest. */ #inference-pane label { background: transparent !important; border: none !important; box-shadow: none !important; } #spans-json .json-holder, #inference-pane .json-holder { max-height: 260px; overflow: auto; background: var(--abd-surface) !important; border: 1px solid var(--abd-border) !important; border-radius: var(--abd-radius) !important; font-family: var(--abd-mono) !important; font-size: 0.8rem !important; } /* ---------- run button ---------- */ #run-button { margin-top: 8px !important; min-height: 46px; width: auto !important; min-width: 190px; flex: 0 0 auto !important; padding: 0 30px !important; align-self: flex-start; background: var(--abd-accent) !important; border: none !important; border-radius: var(--abd-radius) !important; color: #04121d !important; font-family: var(--abd-sans) !important; font-size: 0.92rem !important; font-weight: 600 !important; cursor: pointer; transition: filter 160ms ease, transform 160ms ease; } #run-button:hover { filter: brightness(1.1); transform: translateY(-1px); } #run-button[disabled] { filter: none; opacity: 0.55; cursor: progress; transform: none; } /* The browser's default ring is a 1px near-black outline: invisible on both the dark chips and the accent button. */ #run-button:focus-visible { outline: 2px solid var(--abd-text) !important; outline-offset: 2px; } #run-button:active { transform: translateY(0); } /* Gradio's progress tracker renders in its own near-invisible grey down in the corner; put it where the result will be and make it readable. */ .gradio-container [data-testid="status-tracker"] { background: transparent !important; } .gradio-container .progress-text, .gradio-container [data-testid="status-tracker"] .progress-text { background: var(--abd-surface) !important; border: 1px solid var(--abd-border) !important; border-radius: var(--abd-radius) !important; color: var(--abd-text-dim) !important; font-family: var(--abd-mono) !important; font-size: 0.78rem !important; } /* ---------- result ---------- */ .score-card { padding: 20px; background: var(--abd-surface); border: 1px solid var(--abd-border); border-left: 3px solid var(--abd-text-faint); border-radius: var(--abd-radius); } .score-card.band-low { border-left-color: var(--abd-safe); } .score-card.band-medium { border-left-color: var(--abd-warn); } .score-card.band-high { border-left-color: var(--abd-risk); } .score-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; } .score-label { font-family: var(--abd-mono); font-size: 0.74rem; text-transform: uppercase; letter-spacing: 0.12em; color: var(--abd-text-faint); } .score-verdict { font-size: 0.76rem; font-weight: 600; padding: 3px 9px; border-radius: 999px; } .score-verdict.high { color: var(--abd-risk); background: rgba(248, 113, 113, 0.12); } .score-verdict.medium { color: var(--abd-warn); background: rgba(251, 191, 36, 0.12); } .score-verdict.low { color: var(--abd-safe); background: rgba(52, 211, 153, 0.12); } /* Gradio colours bare spans, which beats inheritance: say it explicitly. */ .score-verdict .edge { color: inherit !important; margin-left: 6px; font-family: var(--abd-mono); font-size: 0.7rem; font-weight: 400; opacity: 0.8; } .score-value { margin: 10px 0 14px; font-family: var(--abd-mono); font-size: 2.6rem; font-weight: 700; line-height: 1; letter-spacing: -0.03em; color: var(--abd-text); } .score-track { height: 5px; border-radius: 999px; background: var(--abd-border); overflow: hidden; } .score-track span { display: block; height: 100%; border-radius: 999px; background: var(--abd-text-faint); transition: width 320ms ease; } .band-low .score-track span { background: var(--abd-safe); } .band-medium .score-track span { background: var(--abd-warn); } .band-high .score-track span { background: var(--abd-risk); } .span-summary { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; padding: 14px 18px; background: var(--abd-surface); border: 1px solid var(--abd-border); border-left: 3px solid var(--abd-text-faint); border-radius: var(--abd-radius); font-size: 0.9rem; color: var(--abd-text-dim); } .span-summary.marked { border-left-color: var(--abd-risk); } .span-summary.clean { border-left-color: var(--abd-safe); } .span-summary strong { font-family: var(--abd-mono); font-size: 1.3rem; color: var(--abd-text); } .span-cutoff { margin-left: auto; font-family: var(--abd-mono); font-size: 0.74rem; color: var(--abd-text-faint); } #result-summary:empty, #marked-text:empty { display: none !important; } #marked-text { margin-top: 14px; } /* The marked text and the span list are as long as whatever was pasted in, so cap them and let them scroll rather than push the page down. */ .highlighted-output { max-height: 340px; overflow-y: auto; padding: 16px 18px; background: var(--abd-surface); border: 1px solid var(--abd-border); border-radius: var(--abd-radius); font-family: var(--abd-mono); font-size: 0.84rem; line-height: 1.75; color: var(--abd-text-dim); white-space: pre-wrap; word-break: break-word; } mark.drop-mark { padding: 1px 3px; border-radius: 3px; background: rgba(248, 113, 113, 0.18); color: #fecaca; text-decoration: line-through; text-decoration-color: rgba(248, 113, 113, 0.7); } .demo-error { padding: 14px 18px; background: rgba(248, 113, 113, 0.08); border: 1px solid rgba(248, 113, 113, 0.32); border-radius: var(--abd-radius); font-size: 0.88rem; line-height: 1.6; color: #fca5a5; } /* ---------- responsive ---------- */ @media (max-width: 860px) { .gradio-container { padding: 0 16px 40px !important; } #workbench { flex-direction: column !important; flex-wrap: wrap !important; gap: 22px !important; } #model-rail, #inference-pane { flex: 1 1 100% !important; width: 100% !important; min-width: 0 !important; } .demo-hero { padding: 28px 0 24px; } .example-row { grid-template-columns: repeat(2, minmax(0, 1fr)); } #run-button { width: 100% !important; align-self: stretch; } .score-value { font-size: 2.1rem; } .span-cutoff { margin-left: 0; } } @media (max-width: 620px) { .example-row { grid-template-columns: minmax(0, 1fr); } button.example-chip { height: 48px !important; line-height: 46px !important; } } @media (prefers-reduced-motion: reduce) { * { transition: none !important; animation: none !important; } button.example-chip:hover, #run-button:hover { transform: none; } }