Spaces:
Sleeping
Sleeping
| """Patch app.py CSS block only — no imports, pure file I/O.""" | |
| import re, sys, pathlib | |
| TARGET = pathlib.Path(__file__).parent.parent / 'app.py' | |
| NEW_CSS = ( | |
| "\n" | |
| " @import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;700" | |
| "&family=Plus+Jakarta+Sans:wght@500;700;800&display=swap');\n" | |
| "\n" | |
| " :root {\n" | |
| " --bg: #0f1117;\n" | |
| " --bg-card: #181c27;\n" | |
| " --bg-inset: #11141d;\n" | |
| " --fg: #e8eaf0;\n" | |
| " --fg-soft: #9ea3b5;\n" | |
| " --muted: #636880;\n" | |
| " --accent: #7c6fff;\n" | |
| " --accent-light: #a89eff;\n" | |
| " --accent-glow: rgba(124, 111, 255, 0.28);\n" | |
| " --border: rgba(255, 255, 255, 0.07);\n" | |
| " --border-accent: rgba(124, 111, 255, 0.35);\n" | |
| " --shadow-card: 0 4px 32px rgba(0, 0, 0, 0.45), 0 1px 0 rgba(255,255,255,0.05) inset;\n" | |
| " --shadow-inset: inset 0 2px 8px rgba(0, 0, 0, 0.55);\n" | |
| " --shadow-btn: 0 4px 20px rgba(124, 111, 255, 0.28);\n" | |
| " --radius-card: 20px;\n" | |
| " --radius-base: 12px;\n" | |
| " --radius-sm: 8px;\n" | |
| " }\n" | |
| "\n" | |
| " html { scroll-behavior: smooth; }\n" | |
| "\n" | |
| " *, *::before, *::after { box-sizing: border-box; }\n" | |
| "\n" | |
| " body,\n" | |
| " .gradio-container,\n" | |
| " .gradio-container > .main,\n" | |
| " .gradio-container > .main > .wrap,\n" | |
| " footer {\n" | |
| " background: var(--bg) !important;\n" | |
| " color: var(--fg) !important;\n" | |
| " font-family: 'DM Sans', sans-serif !important;\n" | |
| " border: none !important;\n" | |
| " }\n" | |
| "\n" | |
| " .gradio-container {\n" | |
| " max-width: 1300px !important;\n" | |
| " padding: 28px 20px 56px !important;\n" | |
| " }\n" | |
| "\n" | |
| " h1, h2, h3, h4 {\n" | |
| " font-family: 'Plus Jakarta Sans', sans-serif !important;\n" | |
| " color: var(--fg) !important;\n" | |
| " letter-spacing: -0.025em;\n" | |
| " }\n" | |
| "\n" | |
| " /* === Hero === */\n" | |
| " .hero-shell {\n" | |
| " position: relative;\n" | |
| " overflow: hidden;\n" | |
| " padding: 40px 44px 36px;\n" | |
| " margin-bottom: 20px;\n" | |
| " background: var(--bg-card);\n" | |
| " border: 1px solid var(--border);\n" | |
| " border-radius: var(--radius-card);\n" | |
| " box-shadow: var(--shadow-card);\n" | |
| " }\n" | |
| "\n" | |
| " .hero-shell::before {\n" | |
| " content: '';\n" | |
| " position: absolute;\n" | |
| " right: -80px;\n" | |
| " top: -80px;\n" | |
| " width: 300px;\n" | |
| " height: 300px;\n" | |
| " border-radius: 9999px;\n" | |
| " background: radial-gradient(circle, rgba(124,111,255,0.25) 0%, transparent 70%);\n" | |
| " animation: orb-drift 6s ease-in-out infinite;\n" | |
| " pointer-events: none;\n" | |
| " }\n" | |
| "\n" | |
| " .hero-shell::after {\n" | |
| " content: '';\n" | |
| " position: absolute;\n" | |
| " left: 50%;\n" | |
| " bottom: -60px;\n" | |
| " width: 200px;\n" | |
| " height: 200px;\n" | |
| " border-radius: 9999px;\n" | |
| " background: radial-gradient(circle, rgba(99,200,200,0.12) 0%, transparent 70%);\n" | |
| " animation: orb-drift 8s ease-in-out infinite reverse;\n" | |
| " pointer-events: none;\n" | |
| " }\n" | |
| "\n" | |
| " .hero-kicker {\n" | |
| " display: inline-block;\n" | |
| " text-transform: uppercase;\n" | |
| " letter-spacing: 0.18em;\n" | |
| " font-size: 11px;\n" | |
| " color: var(--accent-light);\n" | |
| " font-weight: 700;\n" | |
| " background: rgba(124,111,255,0.12);\n" | |
| " border: 1px solid var(--border-accent);\n" | |
| " padding: 4px 12px;\n" | |
| " border-radius: 99px;\n" | |
| " margin-bottom: 16px;\n" | |
| " }\n" | |
| "\n" | |
| " .hero-title {\n" | |
| " margin: 0 0 14px;\n" | |
| " font-size: clamp(2.4rem, 4.5vw, 3.8rem);\n" | |
| " line-height: 1.0;\n" | |
| " font-weight: 800;\n" | |
| " background: linear-gradient(135deg, #ffffff 30%, var(--accent-light));\n" | |
| " -webkit-background-clip: text;\n" | |
| " -webkit-text-fill-color: transparent;\n" | |
| " background-clip: text;\n" | |
| " }\n" | |
| "\n" | |
| " .hero-copy {\n" | |
| " max-width: 680px;\n" | |
| " color: var(--fg-soft);\n" | |
| " font-size: 0.97rem;\n" | |
| " line-height: 1.75;\n" | |
| " margin: 0;\n" | |
| " }\n" | |
| "\n" | |
| " .hero-grid {\n" | |
| " display: grid;\n" | |
| " grid-template-columns: repeat(3, minmax(0, 1fr));\n" | |
| " gap: 12px;\n" | |
| " margin-top: 28px;\n" | |
| " }\n" | |
| "\n" | |
| " .hero-pill {\n" | |
| " border-radius: var(--radius-base);\n" | |
| " padding: 14px 16px;\n" | |
| " background: var(--bg-inset);\n" | |
| " border: 1px solid var(--border);\n" | |
| " min-height: 82px;\n" | |
| " transition: border-color 0.2s;\n" | |
| " }\n" | |
| " .hero-pill:hover { border-color: var(--border-accent); }\n" | |
| "\n" | |
| " .hero-pill-label {\n" | |
| " display: block;\n" | |
| " text-transform: uppercase;\n" | |
| " letter-spacing: 0.14em;\n" | |
| " color: var(--accent-light);\n" | |
| " font-size: 10px;\n" | |
| " margin-bottom: 6px;\n" | |
| " font-weight: 700;\n" | |
| " }\n" | |
| "\n" | |
| " /* === Status bar === */\n" | |
| " .soft-status {\n" | |
| " border-radius: var(--radius-base);\n" | |
| " padding: 10px 18px;\n" | |
| " margin-bottom: 18px;\n" | |
| " background: var(--bg-card) !important;\n" | |
| " border: 1px solid var(--border) !important;\n" | |
| " box-shadow: none !important;\n" | |
| " font-size: 0.88rem;\n" | |
| " color: var(--fg-soft) !important;\n" | |
| " }\n" | |
| "\n" | |
| " /* === Cards === */\n" | |
| " .soft-card {\n" | |
| " padding: 24px;\n" | |
| " background: var(--bg-card) !important;\n" | |
| " border: 1px solid var(--border) !important;\n" | |
| " border-radius: var(--radius-card) !important;\n" | |
| " box-shadow: var(--shadow-card) !important;\n" | |
| " }\n" | |
| "\n" | |
| " .section-title {\n" | |
| " margin: 0 0 6px;\n" | |
| " font-size: 1.35rem;\n" | |
| " font-weight: 800;\n" | |
| " color: var(--fg) !important;\n" | |
| " }\n" | |
| "\n" | |
| " .section-copy {\n" | |
| " margin: 0 0 18px;\n" | |
| " color: var(--muted);\n" | |
| " line-height: 1.6;\n" | |
| " font-size: 0.9rem;\n" | |
| " }\n" | |
| "\n" | |
| " /* === Image well === */\n" | |
| " .well {\n" | |
| " border-radius: var(--radius-base);\n" | |
| " box-shadow: var(--shadow-inset);\n" | |
| " padding: 10px;\n" | |
| " background: var(--bg-inset) !important;\n" | |
| " border: 1px solid var(--border) !important;\n" | |
| " }\n" | |
| "\n" | |
| " /* === Output boxes === */\n" | |
| " .summary-box {\n" | |
| " margin-top: 14px;\n" | |
| " border-radius: var(--radius-base);\n" | |
| " padding: 16px;\n" | |
| " background: var(--bg-inset) !important;\n" | |
| " border: 1px solid var(--border-accent) !important;\n" | |
| " box-shadow: 0 0 20px rgba(124,111,255,0.18) !important;\n" | |
| " }\n" | |
| "\n" | |
| " .detail-box {\n" | |
| " margin-top: 10px;\n" | |
| " border-radius: var(--radius-base);\n" | |
| " padding: 4px;\n" | |
| " background: var(--bg-inset) !important;\n" | |
| " border: 1px solid var(--border) !important;\n" | |
| " box-shadow: none !important;\n" | |
| " transition: border-color 0.2s;\n" | |
| " }\n" | |
| " .detail-box:hover { border-color: var(--border-accent) !important; }\n" | |
| "\n" | |
| " .download-box {\n" | |
| " margin-top: 12px;\n" | |
| " border-radius: var(--radius-base);\n" | |
| " padding: 8px;\n" | |
| " background: var(--bg-inset) !important;\n" | |
| " border: 1px dashed var(--border) !important;\n" | |
| " box-shadow: none !important;\n" | |
| " }\n" | |
| "\n" | |
| " .soft-footer {\n" | |
| " padding: 16px 20px;\n" | |
| " margin-top: 16px;\n" | |
| " background: transparent !important;\n" | |
| " border: none !important;\n" | |
| " box-shadow: none !important;\n" | |
| " }\n" | |
| "\n" | |
| " /* === Analyse button === */\n" | |
| " #analyze-btn {\n" | |
| " min-height: 52px;\n" | |
| " border: none !important;\n" | |
| " border-radius: var(--radius-base) !important;\n" | |
| " background: linear-gradient(135deg, var(--accent-light), var(--accent)) !important;\n" | |
| " color: white !important;\n" | |
| " font-weight: 700 !important;\n" | |
| " font-size: 1rem !important;\n" | |
| " letter-spacing: 0.02em !important;\n" | |
| " box-shadow: var(--shadow-btn) !important;\n" | |
| " transition: transform 260ms ease, box-shadow 260ms ease !important;\n" | |
| " }\n" | |
| " #analyze-btn:hover {\n" | |
| " transform: translateY(-2px) !important;\n" | |
| " box-shadow: 0 8px 30px rgba(124,111,255,0.4) !important;\n" | |
| " }\n" | |
| " #analyze-btn:active {\n" | |
| " transform: translateY(0) !important;\n" | |
| " box-shadow: none !important;\n" | |
| " }\n" | |
| "\n" | |
| " /* === Gradio structural overrides: kill conflicting defaults === */\n" | |
| " .gradio-container .block,\n" | |
| " .gradio-container .gr-box,\n" | |
| " .gradio-container .gr-group,\n" | |
| " .gradio-container .gr-form,\n" | |
| " .gradio-container .gr-panel,\n" | |
| " .gradio-container .gap-4,\n" | |
| " .gradio-container .row,\n" | |
| " .gradio-container [data-testid='block'] {\n" | |
| " background: transparent !important;\n" | |
| " border: none !important;\n" | |
| " box-shadow: none !important;\n" | |
| " color: var(--fg) !important;\n" | |
| " }\n" | |
| "\n" | |
| " /* Accordions */\n" | |
| " .gradio-container .gr-accordion {\n" | |
| " background: var(--bg-inset) !important;\n" | |
| " border: 1px solid var(--border) !important;\n" | |
| " border-radius: var(--radius-base) !important;\n" | |
| " box-shadow: none !important;\n" | |
| " overflow: hidden;\n" | |
| " }\n" | |
| " .gradio-container .gr-accordion > button {\n" | |
| " background: var(--bg-inset) !important;\n" | |
| " color: var(--fg) !important;\n" | |
| " font-weight: 600 !important;\n" | |
| " min-height: 46px;\n" | |
| " padding: 0 16px !important;\n" | |
| " border: none !important;\n" | |
| " }\n" | |
| "\n" | |
| " /* Text inputs */\n" | |
| " .gradio-container textarea,\n" | |
| " .gradio-container input[type='text'],\n" | |
| " .gradio-container input[type='number'] {\n" | |
| " background: var(--bg-inset) !important;\n" | |
| " border: 1px solid var(--border) !important;\n" | |
| " border-radius: var(--radius-sm) !important;\n" | |
| " color: var(--fg) !important;\n" | |
| " box-shadow: var(--shadow-inset) !important;\n" | |
| " }\n" | |
| "\n" | |
| " /* Image/file uploader zones */\n" | |
| " .gradio-container .wrap,\n" | |
| " .gradio-container .image-container,\n" | |
| " .gradio-container .upload-container,\n" | |
| " .gradio-container .empty,\n" | |
| " .gradio-container .file-preview,\n" | |
| " .gradio-container .file-wrap,\n" | |
| " .gradio-container [data-testid='image'],\n" | |
| " .gradio-container .gr-image,\n" | |
| " .gradio-container .gr-file {\n" | |
| " background: var(--bg-inset) !important;\n" | |
| " border: 1px dashed rgba(124,111,255,0.25) !important;\n" | |
| " border-radius: var(--radius-base) !important;\n" | |
| " box-shadow: none !important;\n" | |
| " color: var(--fg-soft) !important;\n" | |
| " }\n" | |
| "\n" | |
| " /* Markdown */\n" | |
| " .gradio-container .gradio-markdown,\n" | |
| " .gradio-container .prose {\n" | |
| " color: var(--fg) !important;\n" | |
| " background: transparent !important;\n" | |
| " }\n" | |
| " .gradio-container .gradio-markdown p,\n" | |
| " .gradio-container .gradio-markdown li,\n" | |
| " .gradio-container .gradio-markdown strong {\n" | |
| " color: var(--fg) !important;\n" | |
| " }\n" | |
| " .gradio-container .gradio-markdown h1,\n" | |
| " .gradio-container .gradio-markdown h2,\n" | |
| " .gradio-container .gradio-markdown h3 {\n" | |
| " color: var(--fg) !important;\n" | |
| " font-family: 'Plus Jakarta Sans', sans-serif !important;\n" | |
| " }\n" | |
| " .gradio-container .gradio-markdown blockquote {\n" | |
| " border-left: 3px solid var(--accent);\n" | |
| " padding-left: 12px;\n" | |
| " color: var(--fg-soft) !important;\n" | |
| " }\n" | |
| " .gradio-container .gradio-markdown code {\n" | |
| " background: rgba(124,111,255,0.12) !important;\n" | |
| " color: var(--accent-light) !important;\n" | |
| " border-radius: 4px;\n" | |
| " padding: 1px 5px;\n" | |
| " }\n" | |
| "\n" | |
| " /* Component labels */\n" | |
| " .gradio-container label > span,\n" | |
| " .gradio-container .label-wrap > span {\n" | |
| " color: var(--muted) !important;\n" | |
| " font-size: 0.75rem !important;\n" | |
| " font-weight: 700 !important;\n" | |
| " text-transform: uppercase !important;\n" | |
| " letter-spacing: 0.1em !important;\n" | |
| " }\n" | |
| "\n" | |
| " /* SVG icons */\n" | |
| " .gradio-container svg {\n" | |
| " color: var(--muted) !important;\n" | |
| " stroke: var(--muted) !important;\n" | |
| " }\n" | |
| "\n" | |
| " /* Secondary buttons */\n" | |
| " .gradio-container button:not(#analyze-btn) {\n" | |
| " background: var(--bg-card) !important;\n" | |
| " color: var(--fg) !important;\n" | |
| " border: 1px solid var(--border) !important;\n" | |
| " border-radius: var(--radius-sm) !important;\n" | |
| " }\n" | |
| "\n" | |
| " /* Focus rings */\n" | |
| " .gradio-container button:focus-visible,\n" | |
| " .gradio-container input:focus-visible,\n" | |
| " .gradio-container textarea:focus-visible {\n" | |
| " outline: none !important;\n" | |
| " box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--accent) !important;\n" | |
| " }\n" | |
| "\n" | |
| " /* Custom scrollbar */\n" | |
| " ::-webkit-scrollbar { width: 6px; height: 6px; }\n" | |
| " ::-webkit-scrollbar-track { background: var(--bg); }\n" | |
| " ::-webkit-scrollbar-thumb { background: var(--muted); border-radius: 99px; }\n" | |
| "\n" | |
| " @keyframes orb-drift {\n" | |
| " 0%, 100% { transform: translate(0, 0) scale(1); }\n" | |
| " 50% { transform: translate(-20px, 14px) scale(1.08); }\n" | |
| " }\n" | |
| "\n" | |
| " @media (max-width: 900px) {\n" | |
| " .hero-grid { grid-template-columns: 1fr; }\n" | |
| " .hero-title { font-size: 2.6rem; }\n" | |
| " .hero-shell { padding: 28px 24px; }\n" | |
| " }\n" | |
| " " | |
| ) | |
| # Read and normalise to LF so markers work regardless of CRLF | |
| raw = TARGET.read_bytes() | |
| src = raw.decode('utf-8').replace('\r\n', '\n') | |
| # Find the css = """...""" block | |
| start_marker = ' css = """\n' | |
| end_marker = '\n """\n' | |
| s = src.find(start_marker) | |
| if s == -1: | |
| print('ERROR: start marker not found') | |
| sys.exit(1) | |
| e = src.find(end_marker, s + len(start_marker)) | |
| if e == -1: | |
| print('ERROR: end marker not found') | |
| sys.exit(1) | |
| new_src = src[:s] + start_marker + NEW_CSS + src[e:] | |
| # Write back with LF endings | |
| TARGET.write_bytes(new_src.encode('utf-8')) | |
| print(f'OK - patched {TARGET} ({len(src)} -> {len(new_src)} bytes)') | |