HumanPlusX / src /ui /styles.py
FajarHidaa's picture
Upload 2 files
f10d92f verified
Raw History Blame Contribute Delete
27.6 kB
"""
Human+ Custom CSS Injection
Overrides Streamlit defaults with Biopunk Dark Luxury design.
Call inject_custom_css() at the top of every page.
"""
import streamlit as st
from ui.theme import COLORS, FONTS
def inject_custom_css():
"""Inject all custom CSS into the Streamlit page."""
st.markdown(_build_css(), unsafe_allow_html=True)
def _build_css() -> str:
c = COLORS
f = FONTS
return f"""
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@300;400;500;600;700&family=DM+Serif+Display:ital@0;1&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<style>
/* ════════════════════════════════════════════════
RESET & ROOT
════════════════════════════════════════════════ */
:root {{
--bg-deep: {c['bg_deep']};
--bg-surface: {c['bg_surface']};
--bg-elevated: {c['bg_elevated']};
--bg-subtle: {c['bg_subtle']};
--bg-line: {c['bg_line']};
--grad-from: {c['grad_from']};
--grad-via: {c['grad_via']};
--grad-to: {c['grad_to']};
--text-primary: {c['text_primary']};
--text-secondary: {c['text_secondary']};
--text-tertiary: {c['text_tertiary']};
--optimal: {c['optimal']};
--warning: {c['warning']};
--danger: {c['danger']};
--accent-violet: {c['accent_violet']};
--accent-cyan: {c['accent_cyan']};
--font-display: {f['display']};
--font-body: {f['body']};
--font-mono: {f['mono']};
--radius-sm: 8px;
--radius-md: 12px;
--radius-lg: 16px;
--radius-xl: 24px;
--radius-full: 9999px;
--shadow-card: 0 4px 24px rgba(0,0,0,0.5), 0 1px 0 rgba(255,255,255,0.04) inset;
--shadow-glow: 0 0 40px rgba(109,40,217,0.25);
}}
/* ════════════════════════════════════════════════
GLOBAL PAGE
════════════════════════════════════════════════ */
html, body, [data-testid="stApp"], .stApp {{
background-color: var(--bg-deep) !important;
color: var(--text-primary) !important;
font-family: var(--font-body) !important;
}}
/* Scrollbar */
::-webkit-scrollbar {{ width: 4px; }}
::-webkit-scrollbar-track {{ background: var(--bg-deep); }}
::-webkit-scrollbar-thumb {{
background: var(--bg-line);
border-radius: var(--radius-full);
}}
::-webkit-scrollbar-thumb:hover {{ background: var(--accent-violet); }}
/* ════════════════════════════════════════════════
STREAMLIT CHROME β€” HIDE / OVERRIDE
════════════════════════════════════════════════ */
#MainMenu, footer, header {{ visibility: hidden; height: 0; }}
[data-testid="stToolbar"] {{ display: none; }}
[data-testid="stSidebarNav"] {{ display: none; }}
/* Remove default Streamlit padding */
.main .block-container {{
padding: 0 16px 80px !important;
max-width: 680px !important;
margin: 0 auto !important;
}}
/* Section background override */
[data-testid="stVerticalBlock"] > div {{
background: transparent !important;
}}
/* ════════════════════════════════════════════════
TYPOGRAPHY
════════════════════════════════════════════════ */
h1, h2, h3, h4 {{
font-family: var(--font-display) !important;
color: var(--text-primary) !important;
line-height: 1.2 !important;
}}
h1 {{ font-size: 2rem !important; }}
h2 {{ font-size: 1.4rem !important; }}
h3 {{ font-size: 1.1rem !important; }}
/* SAFE TYPOGRAPHY SCOPE */
[data-testid="stMarkdownContainer"] p,
[data-testid="stMarkdownContainer"] li {{
font-family: var(--font-body) !important;
color: var(--text-secondary) !important;
line-height: 1.6 !important;
}}
/* Caption */
[data-testid="stCaptionContainer"] {{
font-family: var(--font-body) !important;
color: var(--text-tertiary) !important;
}}
/* FIX: Material Icons (prevents overlapping "upload" text) */
[data-testid="stIconMaterial"] {{
font-family: 'Material Icons' !important;
font-weight: normal !important;
font-style: normal !important;
font-size: 20px !important;
line-height: 1 !important;
letter-spacing: normal !important;
text-transform: none !important;
display: inline-block !important;
white-space: nowrap !important;
}}
/* Markdown text */
[data-testid="stMarkdownContainer"] p {{
font-family: var(--font-body) !important;
color: var(--text-secondary) !important;
font-size: 0.9rem;
}}
/* Code blocks */
code, pre {{
font-family: var(--font-mono) !important;
background: var(--bg-elevated) !important;
border: 1px solid var(--bg-line) !important;
border-radius: var(--radius-sm) !important;
color: var(--accent-cyan) !important;
}}
/* ════════════════════════════════════════════════
BUTTONS
════════════════════════════════════════════════ */
/* Primary button */
.stButton > button[kind="primary"],
.stButton > button {{
font-family: var(--font-body) !important;
font-weight: 600 !important;
font-size: 0.9rem !important;
letter-spacing: 0.02em !important;
border-radius: var(--radius-full) !important;
border: none !important;
padding: 12px 28px !important;
background: linear-gradient(135deg, var(--grad-from), var(--grad-via), var(--grad-to)) !important;
color: white !important;
transition: all 0.2s ease !important;
box-shadow: 0 4px 20px rgba(109,40,217,0.35) !important;
width: 100% !important;
min-height: 48px !important;
cursor: pointer !important;
position: relative;
overflow: hidden;
}}
.stButton > button:hover {{
transform: translateY(-1px) !important;
box-shadow: 0 8px 30px rgba(109,40,217,0.5) !important;
opacity: 0.95 !important;
}}
.stButton > button:active {{
transform: translateY(0) !important;
}}
/* Secondary / outline variant */
.stButton > button[kind="secondary"] {{
background: transparent !important;
border: 1px solid var(--bg-line) !important;
color: var(--text-secondary) !important;
box-shadow: none !important;
}}
.stButton > button[kind="secondary"]:hover {{
border-color: var(--accent-violet) !important;
color: var(--text-primary) !important;
box-shadow: none !important;
}}
/* ════════════════════════════════════════
STEP INDICATOR (RESPONSIVE & PREMIUM)
════════════════════════════════════════ */
/* Base */
.hp-step {{
text-align: center;
font-weight: 600;
letter-spacing: 0.04em;
font-size: 0.95rem;
transition: all 0.2s ease;
}}
/* Active */
.hp-step.active {{
color: var(--accent-violet);
font-weight: 700;
font-size: 1.05rem;
}}
/* Done */
.hp-step.done {{
color: var(--optimal);
}}
/* Pending */
.hp-step.pending {{
color: var(--text-tertiary);
}}
/* Icon spacing */
.hp-step::first-letter {{
margin-right: 6px;
}}
/* ════════════════════════════════════════════════
FILE UPLOADER
════════════════════════════════════════════════ */
[data-testid="stFileUploader"] {{
background: var(--bg-surface) !important;
border: 1.5px dashed var(--bg-line) !important;
border-radius: var(--radius-lg) !important;
padding: 8px !important;
transition: border-color 0.2s ease, box-shadow 0.2s ease !important;
}}
[data-testid="stFileUploader"]:hover,
[data-testid="stFileUploader"]:focus-within {{
border-color: var(--accent-violet) !important;
box-shadow: 0 0 24px rgba(109,40,217,0.15) !important;
}}
[data-testid="stFileUploader"] label {{
color: var(--text-secondary) !important;
font-size: 0.85rem !important;
}}
[data-testid="stFileUploaderDropzone"] {{
background: transparent !important;
border: none !important;
}}
[data-testid="stFileUploaderDropzoneInstructions"] {{
color: var(--text-tertiary) !important;
}}
/* Center uploader content */
[data-testid="stFileUploader"] section {{
display: flex !important;
flex-direction: column;
align-items: center;
justify-content: center;
}}
/* Fix icon spacing */
[data-testid="stFileUploader"] [data-testid="stIconMaterial"] {{
margin-bottom: 6px;
}}
/* Center text */
[data-testid="stFileUploaderDropzoneInstructions"] {{
text-align: center !important;
}}
/* ════════════════════════════════════════════════
EXPANDER
════════════════════════════════════════════════ */
[data-testid="stExpander"] {{
background: var(--bg-surface) !important;
border: 1px solid var(--bg-line) !important;
border-radius: var(--radius-md) !important;
overflow: hidden !important;
margin-bottom: 8px !important;
}}
[data-testid="stExpander"] summary {{
font-family: var(--font-body) !important;
font-weight: 600 !important;
color: var(--text-primary) !important;
padding: 14px 16px !important;
background: var(--bg-surface) !important;
}}
[data-testid="stExpander"] summary:hover {{
background: var(--bg-elevated) !important;
}}
[data-testid="stExpander"] > div > div {{
background: var(--bg-elevated) !important;
border-top: 1px solid var(--bg-line) !important;
padding: 16px !important;
}}
/* ════════════════════════════════════════════════
ALERTS & STATUS
════════════════════════════════════════════════ */
[data-testid="stAlert"] {{
border-radius: var(--radius-md) !important;
border: 1px solid !important;
font-family: var(--font-body) !important;
font-size: 0.85rem !important;
}}
/* Success */
[data-testid="stAlert"][data-baseweb="notification"][kind="positive"],
.element-container .stSuccess {{
background: rgba(16,185,129,0.08) !important;
border-color: rgba(16,185,129,0.25) !important;
color: var(--optimal) !important;
}}
/* Error */
.element-container .stError {{
background: rgba(239,68,68,0.08) !important;
border-color: rgba(239,68,68,0.25) !important;
color: var(--danger) !important;
}}
/* Info */
.element-container .stInfo {{
background: rgba(34,211,238,0.08) !important;
border-color: rgba(34,211,238,0.2) !important;
color: var(--accent-cyan) !important;
}}
/* Warning */
.element-container .stWarning {{
background: rgba(245,158,11,0.08) !important;
border-color: rgba(245,158,11,0.25) !important;
color: var(--warning) !important;
}}
/* ════════════════════════════════════════════════
SPINNER / PROGRESS
════════════════════════════════════════════════ */
[data-testid="stSpinner"] > div {{
border-top-color: var(--accent-violet) !important;
}}
.stProgress > div > div > div {{
background: linear-gradient(90deg, var(--grad-from), var(--grad-to)) !important;
border-radius: var(--radius-full) !important;
}}
.stProgress > div > div {{
background: var(--bg-elevated) !important;
border-radius: var(--radius-full) !important;
height: 6px !important;
}}
/* ════════════════════════════════════════════════
DIVIDER
════════════════════════════════════════════════ */
hr {{
border: none !important;
border-top: 1px solid var(--bg-line) !important;
margin: 24px 0 !important;
}}
/* ════════════════════════════════════════════════
DOWNLOAD BUTTON
════════════════════════════════════════════════ */
[data-testid="stDownloadButton"] > button {{
font-family: var(--font-body) !important;
font-weight: 600 !important;
border-radius: var(--radius-full) !important;
border: 1.5px solid var(--bg-line) !important;
background: var(--bg-elevated) !important;
color: var(--text-primary) !important;
padding: 10px 24px !important;
min-height: 44px !important;
transition: all 0.2s !important;
box-shadow: none !important;
width: 100% !important;
}}
[data-testid="stDownloadButton"] > button:hover {{
border-color: var(--accent-violet) !important;
box-shadow: 0 0 20px rgba(109,40,217,0.2) !important;
transform: translateY(-1px) !important;
}}
/* ════════════════════════════════════════════════
COLUMNS
════════════════════════════════════════════════ */
[data-testid="stHorizontalBlock"] {{
gap: 10px !important;
}}
/* ════════════════════════════════════════════════
CUSTOM HUMAN+ COMPONENTS
════════════════════════════════════════════════ */
/* ── Noise texture overlay (atmospheric depth) ── */
.hp-noise-overlay {{
position: fixed;
inset: 0;
pointer-events: none;
z-index: 0;
opacity: 0.03;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
background-size: 200px;
}}
/* ── Hero section ── */
.hp-hero {{
padding: 48px 0 32px;
text-align: center;
position: relative;
}}
.hp-hero-logo {{
font-family: var(--font-display);
font-size: 3rem;
font-weight: 900;
background: linear-gradient(135deg, #a78bfa, #38bdf8, #22d3ee);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
line-height: 1;
margin-bottom: 6px;
letter-spacing: -0.02em;
}}
.hp-hero-tagline {{
font-family: var(--font-body);
font-size: 0.75rem;
font-weight: 600;
letter-spacing: 0.2em;
text-transform: uppercase;
color: var(--text-tertiary);
margin-bottom: 12px;
}}
.hp-hero-subtitle {{
font-family: var(--font-body);
font-size: 0.95rem;
color: var(--text-secondary);
max-width: 420px;
margin: 0 auto 24px;
line-height: 1.6;
}}
/* ── Step indicator ── */
.hp-steps {{
display: flex;
align-items: center;
justify-content: center;
gap: 0;
margin: 0 auto 40px;
max-width: 320px;
}}
.hp-step {{
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
flex: 1;
position: relative;
}}
.hp-step-dot {{
width: 32px;
height: 32px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.7rem;
font-weight: 700;
font-family: var(--font-mono);
z-index: 1;
transition: all 0.3s;
}}
.hp-step-dot.active {{
background: linear-gradient(135deg, var(--grad-from), var(--grad-to));
color: white;
box-shadow: 0 0 16px rgba(109,40,217,0.5);
}}
.hp-step-dot.done {{
background: rgba(16,185,129,0.15);
border: 1.5px solid var(--optimal);
color: var(--optimal);
}}
.hp-step-dot.pending {{
background: var(--bg-elevated);
border: 1.5px solid var(--bg-line);
color: var(--text-tertiary);
}}
.hp-step-label {{
font-size: 0.62rem;
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--text-tertiary);
text-align: center;
white-space: nowrap;
}}
.hp-step-label.active {{
color: var(--accent-violet);
}}
.hp-step-line {{
flex: 1;
height: 1px;
background: var(--bg-line);
margin-top: -22px;
z-index: 0;
}}
.hp-step-line.done {{
background: linear-gradient(90deg, var(--optimal), var(--grad-from));
}}
/* ── Card base ── */
.hp-card {{
background: var(--bg-surface);
border: 1px solid var(--bg-line);
border-radius: var(--radius-lg);
padding: 20px;
margin-bottom: 12px;
box-shadow: var(--shadow-card);
transition: border-color 0.2s, box-shadow 0.2s;
}}
.hp-card:hover {{
border-color: rgba(139,92,246,0.2);
}}
.hp-card-title {{
font-family: var(--font-body);
font-size: 0.7rem;
font-weight: 700;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--text-tertiary);
margin-bottom: 14px;
display: flex;
align-items: center;
gap: 8px;
}}
.hp-card-title-icon {{
font-size: 0.9rem;
}}
/* ── Biomarker chip ── */
.hp-biomarker-chip {{
display: inline-flex;
align-items: center;
gap: 6px;
padding: 4px 10px;
border-radius: var(--radius-full);
font-family: var(--font-mono);
font-size: 0.75rem;
font-weight: 500;
margin: 2px;
border: 1px solid;
}}
.hp-biomarker-chip.optimal {{
background: rgba(16,185,129,0.1);
border-color: rgba(16,185,129,0.3);
color: var(--optimal);
}}
.hp-biomarker-chip.warning {{
background: rgba(245,158,11,0.1);
border-color: rgba(245,158,11,0.3);
color: var(--warning);
}}
.hp-biomarker-chip.danger {{
background: rgba(239,68,68,0.1);
border-color: rgba(239,68,68,0.3);
color: var(--danger);
}}
/* ── Biomarker row (full card) ── */
.hp-biomarker-row {{
background: var(--bg-elevated);
border: 1px solid var(--bg-line);
border-radius: var(--radius-md);
padding: 14px 16px;
margin-bottom: 8px;
display: flex;
align-items: center;
justify-content: space-between;
transition: border-color 0.2s;
}}
.hp-biomarker-row.optimal {{ border-left: 3px solid var(--optimal); }}
.hp-biomarker-row.warning {{ border-left: 3px solid var(--warning); }}
.hp-biomarker-row.danger {{ border-left: 3px solid var(--danger); }}
.hp-biomarker-name {{
font-family: var(--font-body);
font-weight: 600;
font-size: 0.88rem;
color: var(--text-primary);
}}
.hp-biomarker-ref {{
font-family: var(--font-mono);
font-size: 0.68rem;
color: var(--text-tertiary);
margin-top: 2px;
}}
.hp-biomarker-value {{
font-family: var(--font-mono);
font-size: 1.05rem;
font-weight: 700;
text-align: right;
}}
.hp-biomarker-value.optimal {{ color: var(--optimal); }}
.hp-biomarker-value.warning {{ color: var(--warning); }}
.hp-biomarker-value.danger {{ color: var(--danger); }}
.hp-biomarker-unit {{
font-family: var(--font-mono);
font-size: 0.65rem;
color: var(--text-tertiary);
text-align: right;
}}
/* ── Protocol section card ── */
.hp-protocol-section {{
background: var(--bg-elevated);
border: 1px solid var(--bg-line);
border-radius: var(--radius-lg);
padding: 20px;
margin-bottom: 12px;
}}
.hp-protocol-header {{
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 14px;
padding-bottom: 12px;
border-bottom: 1px solid var(--bg-line);
}}
.hp-protocol-icon {{
width: 36px;
height: 36px;
border-radius: var(--radius-sm);
display: flex;
align-items: center;
justify-content: center;
font-size: 1.1rem;
flex-shrink: 0;
}}
.hp-protocol-title {{
font-family: var(--font-body);
font-weight: 700;
font-size: 0.95rem;
color: var(--text-primary);
}}
.hp-protocol-body {{
font-family: var(--font-body);
font-size: 0.88rem;
color: var(--text-secondary);
line-height: 1.7;
}}
/* ── Loading steps ── */
.hp-loading-steps {{
padding: 20px;
background: var(--bg-surface);
border: 1px solid var(--bg-line);
border-radius: var(--radius-lg);
margin: 16px 0;
}}
.hp-loading-step-row {{
display: flex;
align-items: center;
gap: 12px;
padding: 8px 0;
font-family: var(--font-body);
font-size: 0.85rem;
}}
.hp-loading-step-icon {{
width: 20px;
text-align: center;
font-size: 0.75rem;
flex-shrink: 0;
}}
.hp-loading-step-text.done {{ color: var(--optimal); }}
.hp-loading-step-text.active {{ color: var(--text-primary); font-weight: 600; }}
.hp-loading-step-text.pending {{ color: var(--text-tertiary); }}
/* ── Privacy badge ── */
.hp-privacy-badge {{
display: inline-flex;
align-items: center;
gap: 6px;
background: rgba(16,185,129,0.08);
border: 1px solid rgba(16,185,129,0.2);
border-radius: var(--radius-full);
padding: 5px 12px;
font-size: 0.72rem;
font-weight: 600;
color: var(--optimal);
letter-spacing: 0.03em;
margin: 4px auto;
display: flex;
width: fit-content;
}}
/* ── Trust badge row ── */
.hp-trust-row {{
display: flex;
gap: 8px;
justify-content: center;
flex-wrap: wrap;
margin-bottom: 28px;
}}
.hp-trust-badge {{
display: inline-flex;
align-items: center;
gap: 5px;
background: var(--bg-elevated);
border: 1px solid var(--bg-line);
border-radius: var(--radius-full);
padding: 5px 12px;
font-size: 0.7rem;
font-weight: 500;
color: var(--text-tertiary);
white-space: nowrap;
}}
/* ── Section label ── */
.hp-section-label {{
font-family: var(--font-body);
font-size: 0.68rem;
font-weight: 700;
letter-spacing: 0.16em;
text-transform: uppercase;
color: var(--text-tertiary);
margin: 28px 0 12px;
padding-left: 10px;
border-left: 2px solid var(--accent-violet);
}}
/* ── Gradient text utility ── */
.hp-gradient-text {{
background: linear-gradient(135deg, #a78bfa, #38bdf8);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}}
/* ── Footer ── */
.hp-footer {{
text-align: center;
padding: 32px 0 16px;
font-family: var(--font-body);
font-size: 0.72rem;
color: var(--text-tertiary);
letter-spacing: 0.04em;
border-top: 1px solid var(--bg-line);
margin-top: 40px;
}}
/* ── Glow orbs (background atmosphere) ── */
.hp-orbs {{
position: fixed;
inset: 0;
pointer-events: none;
z-index: 0;
overflow: hidden;
}}
.hp-orb {{
position: absolute;
border-radius: 50%;
filter: blur(80px);
opacity: 0.07;
}}
.hp-orb-1 {{
width: 400px;
height: 400px;
background: var(--grad-from);
top: -100px;
right: -100px;
}}
.hp-orb-2 {{
width: 300px;
height: 300px;
background: var(--grad-to);
bottom: 100px;
left: -80px;
}}
/* ════════════════════════════════════════════════
MOBILE RESPONSIVE
════════════════════════════════════════════════ */
@media (max-width: 480px) {{
.main .block-container {{
padding: 0 12px 80px !important;
}}
.hp-hero-logo {{ font-size: 2.4rem; }}
.hp-hero-subtitle {{ font-size: 0.88rem; }}
.stButton > button {{
min-height: 52px !important;
font-size: 0.95rem !important;
}}
.hp-card {{ padding: 16px; }}
.hp-protocol-section {{ padding: 16px; }}
.hp-trust-row {{ gap: 6px; }}
.hp-trust-badge {{ font-size: 0.65rem; padding: 4px 10px; }}
.hp-step {{
font-size: 0.85rem;
}}
.hp-step.active {{
font-size: 0.95rem;
}}
}}
/* ════════════════════════════════════════════════
SIDEBAR (if used later)
════════════════════════════════════════════════ */
[data-testid="stSidebar"] {{
background: var(--bg-surface) !important;
border-right: 1px solid var(--bg-line) !important;
}}
/* ════════════════════════════════════════════════
SELECTBOX & INPUTS (for future forms)
════════════════════════════════════════════════ */
[data-testid="stSelectbox"] > div > div,
[data-testid="stTextInput"] > div > div > input {{
background: var(--bg-elevated) !important;
border: 1px solid var(--bg-line) !important;
border-radius: var(--radius-md) !important;
color: var(--text-primary) !important;
font-family: var(--font-body) !important;
}}
[data-testid="stSelectbox"] > div > div:focus-within,
[data-testid="stTextInput"] > div > div > input:focus {{
border-color: var(--accent-violet) !important;
box-shadow: 0 0 0 2px rgba(109,40,217,0.2) !important;
}}
/* ════════════════════════════════════════
FIX: MATERIAL ICON (UPLOAD DOUBLE TEXT)
════════════════════════════════════════ */
[data-testid="stIconMaterial"] {{
font-family: 'Material Icons' !important;
font-style: normal !important;
font-weight: normal !important;
font-size: 20px !important;
line-height: 1 !important;
letter-spacing: normal !important;
text-transform: none !important;
white-space: nowrap !important;
display: inline-block !important;
}}
/* Remove possible duplicate rendering */
[data-testid="stIconMaterial"]::before,
[data-testid="stIconMaterial"]::after {{
content: none !important;
}}
/* Prevent global styling leaking into icon */
[data-testid="stIconMaterial"] * {{
all: unset;
}}
</style>
<!-- Atmospheric orbs -->
<div class="hp-orbs">
<div class="hp-orb hp-orb-1"></div>
<div class="hp-orb hp-orb-2"></div>
</div>
"""