Spaces:
Running
Running
| """Custom CSS for the verdict card. Kept in its own module so it can | |
| be imported without pulling in gradio (handy for tests). | |
| """ | |
| CUSTOM_CSS = """ | |
| @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap'); | |
| :root { | |
| --gw-bg: #fafaf7; | |
| --gw-card-bg: #ffffff; | |
| --gw-text: #1a1f1a; | |
| --gw-muted: #5b6961; | |
| --gw-border: #e7eae5; | |
| --gw-good: #2f9e58; | |
| --gw-good-soft: #e6f6ec; | |
| --gw-okay: #c79100; | |
| --gw-okay-soft: #fff5d9; | |
| --gw-warn: #d97706; | |
| --gw-warn-soft: #ffeacc; | |
| --gw-bad: #c44545; | |
| --gw-bad-soft: #fde2e2; | |
| --gw-legal: #5b21b6; | |
| --gw-legal-soft: #ede9fe; | |
| --gw-shadow: 0 1px 2px rgba(0,0,0,.04), 0 8px 24px rgba(0,0,0,.06); | |
| } | |
| /* ---------- top-level layout ---------- */ | |
| .gw-app { font-family: Inter, system-ui, -apple-system, sans-serif; color: var(--gw-text); } | |
| /* Header */ | |
| .gw-pageheader { padding: 12px 0 4px; } | |
| .gw-pageheader h1 { margin: 0; font-size: 28px; letter-spacing: -.02em; font-weight: 800; } | |
| .gw-pageheader p { margin: 4px 0 0; color: var(--gw-muted); font-size: 15px; } | |
| /* ---------- placeholder ---------- */ | |
| .gw-placeholder { | |
| border: 1px dashed var(--gw-border); | |
| background: linear-gradient(180deg, #ffffff 0%, #f7faf6 100%); | |
| border-radius: 16px; | |
| padding: 32px 24px; | |
| text-align: center; | |
| color: var(--gw-muted); | |
| } | |
| .gw-placeholder__emoji { font-size: 56px; line-height: 1; margin-bottom: 8px; } | |
| .gw-placeholder h2 { margin: 8px 0 4px; color: var(--gw-text); font-weight: 700; font-size: 20px; } | |
| .gw-placeholder p { margin: 4px 0; font-size: 14px; } | |
| .gw-placeholder__hint { font-size: 13px; max-width: 38ch; margin: 12px auto 0; } | |
| /* ---------- card ---------- */ | |
| .gw-card { | |
| background: var(--gw-card-bg); | |
| border-radius: 18px; | |
| box-shadow: var(--gw-shadow); | |
| overflow: hidden; | |
| margin: 0; | |
| } | |
| .gw-card--neutral .gw-hero--neutral { background: linear-gradient(135deg, #f1f3f0, #e7eae5); color: var(--gw-text); } | |
| .gw-card--green .gw-hero { background: linear-gradient(135deg, #2f9e58, #1f7a44); color: white; } | |
| .gw-card--greenwasher .gw-hero { background: linear-gradient(135deg, #f59f00, #c97a00); color: white; } | |
| .gw-card--hazard .gw-hero { background: linear-gradient(135deg, #c44545, #8e2929); color: white; } | |
| /* ---------- hero ---------- */ | |
| .gw-hero { | |
| display: flex; align-items: center; gap: 18px; | |
| padding: 22px 24px; | |
| flex-wrap: wrap; | |
| } | |
| .gw-hero__emoji { | |
| font-size: 56px; line-height: 1; | |
| flex: 0 0 auto; | |
| filter: drop-shadow(0 2px 6px rgba(0,0,0,.15)); | |
| } | |
| .gw-hero__text { flex: 1 1 220px; min-width: 0; } | |
| .gw-hero__label { | |
| font-size: 26px; font-weight: 800; letter-spacing: -.01em; line-height: 1.1; | |
| } | |
| .gw-hero__tagline { margin-top: 4px; font-size: 14px; opacity: .9; } | |
| .gw-hero__meta { display: flex; gap: 16px; flex: 0 0 auto; } | |
| .gw-hero__metaitem { text-align: right; min-width: 70px; } | |
| .gw-hero__metalabel { font-size: 11px; text-transform: uppercase; letter-spacing: .08em; opacity: .8; } | |
| .gw-hero__metavalue { font-size: 22px; font-weight: 700; } | |
| /* ---------- why ---------- */ | |
| .gw-why { | |
| padding: 14px 24px; | |
| border-bottom: 1px solid var(--gw-border); | |
| font-size: 14px; color: var(--gw-text); | |
| margin: 0; | |
| } | |
| .gw-why strong { font-weight: 700; } | |
| /* ---------- badges ---------- */ | |
| .gw-badges { | |
| display: flex; flex-wrap: wrap; gap: 8px; | |
| padding: 14px 24px 0; | |
| } | |
| .gw-badge { | |
| display: inline-flex; align-items: center; gap: 6px; | |
| padding: 6px 12px; | |
| border-radius: 999px; | |
| font-size: 12px; font-weight: 600; | |
| } | |
| .gw-badge--warn { background: var(--gw-warn-soft); color: var(--gw-warn); } | |
| .gw-badge--info { background: #e0f2fe; color: #075985; } | |
| .gw-badge--legal { background: var(--gw-legal-soft); color: var(--gw-legal); } | |
| /* ---------- section ---------- */ | |
| .gw-section { padding: 16px 24px; border-top: 1px solid var(--gw-border); } | |
| .gw-section__title { margin: 0 0 12px; font-size: 13px; font-weight: 700; letter-spacing: .04em; | |
| text-transform: uppercase; color: var(--gw-muted); } | |
| .gw-section--legal { background: var(--gw-legal-soft); } | |
| .gw-section--legal .gw-section__title { color: var(--gw-legal); } | |
| /* ---------- identification ---------- */ | |
| .gw-id { display: grid; gap: 6px; } | |
| .gw-id__row { display: flex; gap: 12px; align-items: center; font-size: 14px; } | |
| .gw-id__label { color: var(--gw-muted); min-width: 110px; font-weight: 600; } | |
| .gw-id__value { color: var(--gw-text); } | |
| .gw-id__meta { color: var(--gw-muted); font-style: italic; } | |
| .gw-warning { | |
| margin-top: 12px; | |
| padding: 10px 12px; | |
| background: var(--gw-warn-soft); | |
| border-left: 3px solid var(--gw-warn); | |
| border-radius: 6px; | |
| font-size: 13px; | |
| color: #7a4400; | |
| } | |
| /* ---------- chip ---------- */ | |
| .gw-chip { | |
| display: inline-block; | |
| padding: 2px 10px; | |
| border-radius: 999px; | |
| background: #f1f5f0; | |
| color: var(--gw-text); | |
| font-size: 12px; | |
| font-weight: 600; | |
| } | |
| .gw-chip--mono { font-family: ui-monospace, SFMono-Regular, monospace; } | |
| .gw-chips { display: flex; flex-wrap: wrap; gap: 6px; } | |
| /* ---------- axes ---------- */ | |
| .gw-axes { display: grid; gap: 14px; } | |
| .gw-axis {} | |
| .gw-axis__head { display: flex; justify-content: space-between; align-items: baseline; } | |
| .gw-axis__name { font-size: 14px; font-weight: 600; } | |
| .gw-axis__score { font-size: 16px; font-weight: 700; font-variant-numeric: tabular-nums; } | |
| .gw-axis__score-suffix { font-size: 12px; color: var(--gw-muted); font-weight: 500; } | |
| .gw-axis__track { | |
| margin-top: 6px; | |
| height: 10px; | |
| background: #f1f3f0; | |
| border-radius: 999px; | |
| overflow: hidden; | |
| position: relative; | |
| } | |
| .gw-axis__fill { height: 100%; border-radius: 999px; transition: width .4s ease; } | |
| .gw-axis__fill--good { background: linear-gradient(90deg, #2f9e58, #4cc473); } | |
| .gw-axis__fill--okay { background: linear-gradient(90deg, #f59f00, #ffc850); } | |
| .gw-axis__fill--warn { background: linear-gradient(90deg, #d97706, #fb923c); } | |
| .gw-axis__fill--bad { background: linear-gradient(90deg, #c44545, #ef6b6b); } | |
| .gw-axis__band { margin-top: 4px; font-size: 12px; color: var(--gw-muted); } | |
| /* ---------- reasons ---------- */ | |
| .gw-reasons { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; } | |
| .gw-reason { | |
| display: flex; gap: 12px; align-items: flex-start; | |
| padding: 12px; | |
| border: 1px solid var(--gw-border); | |
| border-radius: 12px; | |
| background: #fcfdfb; | |
| } | |
| .gw-reason__title { font-weight: 600; font-size: 14px; } | |
| .gw-reason__body { margin: 4px 0 0; font-size: 13px; color: var(--gw-muted); } | |
| .gw-pill { | |
| flex: 0 0 auto; | |
| padding: 4px 10px; | |
| border-radius: 999px; | |
| font-size: 11px; | |
| font-weight: 700; | |
| letter-spacing: .04em; | |
| text-transform: uppercase; | |
| white-space: nowrap; | |
| } | |
| .gw-pill--low { background: #e0f2fe; color: #075985; } | |
| .gw-pill--moderate { background: var(--gw-okay-soft); color: #7a5300; } | |
| .gw-pill--high { background: var(--gw-warn-soft); color: var(--gw-warn); } | |
| .gw-pill--very-high { background: var(--gw-bad-soft); color: var(--gw-bad); } | |
| .gw-pill--critical { background: #1a1a1a; color: #fff; } | |
| /* ---------- sources ---------- */ | |
| .gw-sources { margin: 0; padding-left: 18px; font-size: 13px; } | |
| .gw-sources li { margin: 4px 0; } | |
| .gw-sources a { color: var(--gw-good); text-decoration: none; word-break: break-all; } | |
| .gw-sources a:hover { text-decoration: underline; } | |
| /* ---------- footer ---------- */ | |
| .gw-footer { | |
| padding: 14px 24px; | |
| border-top: 1px solid var(--gw-border); | |
| font-size: 12px; color: var(--gw-muted); font-style: italic; | |
| background: #fafbf8; | |
| } | |
| /* ---------- tips list ---------- */ | |
| .gw-tips { padding-left: 18px; margin: 0; } | |
| .gw-tips li { margin: 6px 0; font-size: 14px; } | |
| /* ---------- mobile ---------- */ | |
| @media (max-width: 640px) { | |
| .gw-hero { padding: 18px 16px; gap: 12px; } | |
| .gw-hero__emoji { font-size: 44px; } | |
| .gw-hero__label { font-size: 22px; } | |
| .gw-hero__meta { width: 100%; justify-content: flex-end; } | |
| .gw-section { padding: 14px 16px; } | |
| .gw-why { padding: 12px 16px; } | |
| .gw-badges { padding: 12px 16px 0; } | |
| .gw-footer { padding: 12px 16px; } | |
| .gw-id__row { flex-direction: column; align-items: flex-start; gap: 2px; } | |
| .gw-id__label { min-width: 0; font-size: 12px; } | |
| .gw-pageheader h1 { font-size: 24px; } | |
| } | |
| /* Gradio chrome cleanups */ | |
| .gw-pageheader + * { margin-top: 8px; } | |
| /* ----- Phase 8: personalisation banner ----- */ | |
| .gw-personal-banner { | |
| margin: 12px 16px 0; | |
| padding: 12px 14px; | |
| background: linear-gradient(135deg, #f0f7ff 0%, #e6f0ff 100%); | |
| border: 1px solid #c7d8ee; | |
| border-radius: 10px; | |
| font-size: 13px; | |
| color: #243a5a; | |
| } | |
| .gw-personal-banner__head { | |
| display: flex; align-items: center; gap: 8px; | |
| margin-bottom: 6px; | |
| } | |
| .gw-personal-banner__title { font-weight: 600; } | |
| .gw-personal-banner__bucket { | |
| margin-left: auto; | |
| padding: 2px 8px; border-radius: 9999px; | |
| background: #ffffff; | |
| font-size: 11px; color: #5b6961; border: 1px solid #d6dee0; | |
| } | |
| .gw-personal-banner__list { margin: 0; padding-left: 18px; } | |
| .gw-personal-banner__list li { margin: 2px 0; } | |
| .gw-personal-banner code { | |
| background: #ffffff; padding: 1px 6px; border-radius: 4px; | |
| font-size: 12px; border: 1px solid #d6dee0; | |
| } | |
| /* ----- Phase 8: My Scans table ----- */ | |
| .gw-scans-wrap { overflow-x: auto; margin-top: 8px; } | |
| .gw-scans { | |
| width: 100%; border-collapse: collapse; | |
| font-size: 13px; | |
| } | |
| .gw-scans th, .gw-scans td { | |
| padding: 8px 10px; | |
| border-bottom: 1px solid #eaeef0; | |
| text-align: left; | |
| vertical-align: top; | |
| } | |
| .gw-scans th { | |
| background: #f5f7f7; | |
| font-weight: 600; | |
| font-size: 12px; | |
| color: #5b6961; | |
| text-transform: uppercase; | |
| letter-spacing: 0.04em; | |
| } | |
| .gw-scans__when { white-space: nowrap; color: #5b6961; font-family: ui-monospace, monospace; font-size: 12px; } | |
| .gw-scans__axes { white-space: nowrap; color: #5b6961; font-family: ui-monospace, monospace; font-size: 12px; } | |
| .gw-chip--good { background: #e7f5ec; color: #1f6b3a; } | |
| .gw-chip--warn { background: #fff5e0; color: #8a5a05; } | |
| .gw-chip--bad { background: #fde8e8; color: #8a1f1f; } | |
| /* ----- About / How it works tab ----- */ | |
| .gw-about-verdicts { list-style: none; padding: 0; margin: 8px 0; } | |
| .gw-about-verdicts li { | |
| padding: 10px 0; | |
| border-bottom: 1px solid #eaeef0; | |
| font-size: 14px; | |
| line-height: 1.5; | |
| } | |
| .gw-about-verdicts li:last-child { border-bottom: none; } | |
| .gw-about-verdicts .gw-chip { | |
| display: inline-block; margin-right: 8px; | |
| font-weight: 600; letter-spacing: 0.04em; | |
| } | |
| .gw-disclaimers { | |
| background: #fffbf2; | |
| border-left: 4px solid #d8a13b; | |
| padding-left: 16px; | |
| } | |
| .gw-disclaimers ol { padding-left: 20px; } | |
| .gw-disclaimers li { margin: 8px 0; line-height: 1.55; } | |
| /* ----- Phase 8c: My Scans aggregate summary ----- */ | |
| .gw-summary-tallies { | |
| display: grid; | |
| grid-template-columns: repeat(3, 1fr); | |
| gap: 10px; | |
| margin-top: 10px; | |
| } | |
| .gw-summary-tally { | |
| text-align: center; | |
| padding: 12px 8px; | |
| border-radius: 10px; | |
| border: 1px solid transparent; | |
| display: flex; flex-direction: column; gap: 2px; | |
| } | |
| .gw-summary-tally--good { background: #e7f5ec; border-color: #b9dec7; color: #1f6b3a; } | |
| .gw-summary-tally--warn { background: #fff5e0; border-color: #e8d29a; color: #8a5a05; } | |
| .gw-summary-tally--bad { background: #fde8e8; border-color: #e6b5b5; color: #8a1f1f; } | |
| .gw-summary-tally__count { font-size: 28px; font-weight: 700; line-height: 1.1; } | |
| .gw-summary-tally__label { font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; } | |
| .gw-summary-tally__pct { font-size: 11px; opacity: 0.7; } | |
| .gw-summary-cols { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 16px; | |
| } | |
| .gw-summary-col h3 { margin: 0 0 4px; font-size: 14px; font-weight: 600; } | |
| .gw-section__subtitle { font-size: 14px; font-weight: 600; margin: 0 0 4px; color: #243a5a; } | |
| .gw-brand-list { list-style: none; padding: 0; margin: 8px 0 0; font-size: 13px; } | |
| .gw-brand-list li { | |
| padding: 6px 0; | |
| border-bottom: 1px dashed #eaeef0; | |
| display: flex; flex-wrap: wrap; align-items: center; gap: 6px; | |
| } | |
| .gw-brand-list li:last-child { border-bottom: none; } | |
| .gw-brand-name { font-weight: 600; flex: 1; min-width: 100px; } | |
| .gw-brand-mix { display: inline-flex; gap: 4px; } | |
| .gw-mix { | |
| display: inline-block; | |
| padding: 1px 6px; | |
| font-size: 11px; | |
| font-weight: 600; | |
| border-radius: 4px; | |
| font-family: ui-monospace, monospace; | |
| } | |
| .gw-mix--good { background: #e7f5ec; color: #1f6b3a; } | |
| .gw-mix--warn { background: #fff5e0; color: #8a5a05; } | |
| .gw-mix--bad { background: #fde8e8; color: #8a1f1f; } | |
| .gw-empty-table { | |
| padding: 24px; | |
| text-align: center; | |
| color: #5b6961; | |
| border: 1px dashed #d6dee0; | |
| border-radius: 10px; | |
| margin-top: 8px; | |
| } | |
| .gw-empty-table p { margin: 4px 0; } | |
| @media (max-width: 720px) { | |
| .gw-summary-cols { grid-template-columns: 1fr; } | |
| .gw-summary-tally__count { font-size: 22px; } | |
| } | |
| """ | |