| """ |
| Working for the Weekend — How Much of Your Life Do You Trade for Two Days? |
| The math they don't put in the job listing. |
| """ |
|
|
| import gradio as gr |
| import os |
| import random |
| from huggingface_hub import InferenceClient |
|
|
| HF_TOKEN = os.environ.get("HF_TOKEN", "") |
| MODEL = "mistralai/Mistral-7B-Instruct-v0.3" |
|
|
| client = InferenceClient(model=MODEL, token=HF_TOKEN) if HF_TOKEN else None |
|
|
| SYSTEM_PROMPT = """Someone tells you about their work situation — hours, commute, job type, salary, whatever they share. Your job is to show them the real math of their work-life trade. Not to make them feel bad. To make the invisible visible. |
| |
| Rules: |
| - 5 to 7 sentences. |
| - Do real math when possible. Hours worked per year. Hours of free time. Percentage of waking life spent working. What their hourly rate actually is when you include commute and unpaid prep. |
| - Show one hidden cost they're not counting — the commute, the getting-ready time, the recovery time, the Sunday dread. |
| - Show one thing they're trading that isn't money — time with someone specific, a skill they stopped practicing, sleep. |
| - Don't tell them to quit. Don't tell them to hustle harder. Just show them the exchange rate. |
| - The tone is: "here's what you're actually trading. You decide if it's worth it." |
| - Talk like a friend who did the math on their own job and got real quiet for a minute. |
| - No hustle culture. No anti-work ideology. Just math.""" |
|
|
| JOBS = [ |
| "I work 9-5 with an hour commute each way", |
| "I work 60 hours a week in finance", |
| "I'm a teacher and I bring work home every night", |
| "I work retail, 35 hours, minimum wage", |
| "I do shift work, 12 hour shifts, 3 days on 4 off", |
| "I work from home but I'm always online", |
| "I work two jobs to make rent", |
| "I'm salaried but I work weekends for free", |
| "I freelance and I never stop working", |
| "I work 40 hours but my commute is 2 hours total", |
| ] |
|
|
| FALLBACKS = [ |
| "**I work 9-5 with an hour commute each way**\n\nYour official work week is 40 hours, but your real work week is 50 — that commute counts. You're spending 10 hours a week in a car or on a train doing nothing you chose. That's 520 hours a year. If you sleep 7 hours a night, you have about 119 waking hours per week. Work and commute take 50 of them. That leaves you 69 hours — but subtract getting ready, errands, cooking, cleaning, and you're looking at maybe 35 hours of actual free time per week. Five of those seven days are given away for two. And those two start with errands you couldn't do during the five. The exchange rate is real. You just never see it in the job listing.", |
| "**I work 60 hours a week in finance**\n\nSixty hours at, let's say, $120k salary. Sounds like $57 an hour. But you're salaried, so those extra 20 hours are free labor — your actual rate is closer to $38/hour once you count the real hours. Add in the Sunday night prep, the emails at dinner, the mental load you carry home, and you're probably working 70+ hours for the same check. You have 49 waking non-work hours per week. Subtract basic human maintenance and you're at maybe 25 hours of actual life. That's 15% of your waking existence that belongs to you. Finance pays well. But it pays in a currency you can't spend if you don't have the time to spend it.", |
| "**I'm a teacher and I bring work home every night**\n\nYour contract says 40 hours. Your reality is closer to 55. Grading at the kitchen table, lesson planning on Sunday, answering parent emails at 9pm — none of that shows up on a timesheet. If you're making $52k, your official rate is $25/hour. Your real rate, counting the invisible hours, is closer to $18. You're subsidizing the education system with your personal time and calling it dedication. The thing you're trading isn't just hours — it's the evening version of yourself. Your family and friends get the version that already gave everything to other people's kids. That's the cost that never makes it into the teacher appreciation posts.", |
| "**I work retail, 35 hours, minimum wage**\n\nThirty-five hours at minimum wage means your paycheck is around $500 a week before taxes. After taxes, maybe $430. Your rent probably takes half of that in the first week. Here's the hidden math: they scheduled you 35 hours instead of 40 so they don't have to give you benefits. So you're paying for your own health insurance — or more likely, you're not, and you're one emergency away from debt. The 35 hours sounds part-time but your availability has to be full-time because the schedule changes every week. You can't get a second job if you don't know when you're working. The real trade isn't hours for money. It's control. They have it. You don't.", |
| "**I do shift work, 12 hour shifts, 3 days on 4 off**\n\nOn paper, this looks like a hack — three days of work for four days off. But 12-hour shifts don't leave you with 12 hours of free time on work days. You sleep 7-8 hours. Getting ready and commuting eats another 2. You have maybe 2 hours of conscious free time on a work day, and you spend most of it recovering. Your 'four days off' start with a recovery day where you're basically useless. So it's really three days off. And your schedule rotates, which means your body never fully adjusts. You're always slightly jet-lagged in your own time zone. The trade here isn't time — it's rhythm. You gave up having a consistent week.", |
| "**I work from home but I'm always online**\n\nYou eliminated the commute but replaced it with something worse — the complete collapse of the boundary between work and not-work. Your commute used to be a decompression chamber. Now you go from spreadsheet to dinner table in four seconds and wonder why you can't relax. You're 'saving' 10 hours a week on commuting but spending 15 extra hours checking Slack because your laptop is right there. Your office is your living room, which means your living room is your office, which means you never leave work. The math: you're probably working 50+ hours and counting it as 40 because you took a lunch break on your own couch. The thing you traded for no commute is the ability to ever fully clock out.", |
| "**I work two jobs to make rent**\n\nLet's just do the math. Two jobs, probably 55-65 hours a week combined. If both are near minimum wage, you're making maybe $700-800 a week before taxes. Rent takes $1,200-1,500 a month. After rent, utilities, food, gas, and phone, you might have $200 left. You're working the equivalent of 1.5 full-time jobs to afford the basics of one life. Your free time is roughly 20 hours a week, most of which you spend sleeping or preparing for the next shift. The thing nobody says out loud: you're not working two jobs because you want to. You're working two jobs because one job doesn't pay enough to exist. The trade isn't hours for money. It's your entire life for the right to keep having one.", |
| ] |
|
|
|
|
| def calculate(user_input): |
| situation = user_input.strip() if user_input and user_input.strip() else random.choice(JOBS) |
| prompt = f"Their work situation: {situation}" |
|
|
| if client: |
| try: |
| response = client.chat_completion( |
| messages=[ |
| {"role": "system", "content": SYSTEM_PROMPT}, |
| {"role": "user", "content": prompt}, |
| ], |
| max_tokens=500, |
| temperature=0.75, |
| ) |
| result = response.choices[0].message.content |
| if not result or not result.strip(): |
| return random.choice(FALLBACKS) |
| return f"**{situation}**\n\n{result.strip()}" |
| except Exception: |
| return random.choice(FALLBACKS) |
| else: |
| return random.choice(FALLBACKS) |
|
|
|
|
| def calculate_random(): |
| return calculate("") |
|
|
|
|
| CUSTOM_CSS = """ |
| @import url('https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&family=Inter:wght@300;400;500;600&display=swap'); |
| |
| body, .gradio-container { |
| background: #0a0808 !important; |
| font-family: 'Inter', sans-serif !important; |
| color: #d8d0d0 !important; |
| } |
| footer { display: none !important; } |
| |
| .app-header { text-align: center; padding: 28px 20px 8px; } |
| .app-header h1 { |
| font-family: 'Space Mono', monospace; font-size: 1.6rem; font-weight: 700; |
| background: linear-gradient(135deg, #b08060, #d0a080); |
| -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin: 0; |
| } |
| .app-header .sub { color: #706060; font-size: 0.88rem; margin-top: 6px; font-weight: 300; letter-spacing: 0.04em; font-style: italic; } |
| .app-visual { text-align: center; font-size: 5rem; padding: 12px 0 4px; filter: drop-shadow(0 0 20px rgba(176, 128, 96, 0.3)); } |
| |
| .input-box textarea { background: #141010 !important; border: 1px solid rgba(176, 128, 96, 0.25) !important; color: #d8d0d0 !important; font-family: 'Inter', sans-serif !important; border-radius: 12px !important; font-size: 0.95rem !important; } |
| .input-box textarea::placeholder { color: #706060 !important; } |
| .input-box textarea:focus { border-color: #b08060 !important; box-shadow: 0 0 20px rgba(176, 128, 96, 0.15) !important; } |
| .input-box label, .output-box label { color: #706060 !important; font-family: 'Space Mono', monospace !important; font-size: 0.75rem !important; letter-spacing: 0.05em !important; } |
| |
| button.primary { background: linear-gradient(135deg, #b08060, #906040) !important; border: none !important; color: #fff !important; font-family: 'Space Mono', monospace !important; font-size: 1.1rem !important; font-weight: 700 !important; border-radius: 24px !important; padding: 12px 40px !important; box-shadow: 0 4px 20px rgba(176, 128, 96, 0.3) !important; } |
| button.primary:hover { box-shadow: 0 4px 30px rgba(176, 128, 96, 0.5) !important; } |
| button.secondary { background: transparent !important; border: 1px solid rgba(176, 128, 96, 0.3) !important; color: #b08060 !important; font-family: 'Space Mono', monospace !important; font-size: 0.8rem !important; border-radius: 20px !important; } |
| button.secondary:hover { background: rgba(176, 128, 96, 0.1) !important; } |
| |
| .output-box .prose { background: #141010 !important; border: 1px solid rgba(176, 128, 96, 0.15) !important; border-radius: 12px !important; padding: 24px !important; color: #d8d0d0 !important; font-size: 0.95rem !important; line-height: 1.7 !important; } |
| .output-box .prose strong { color: #d0a080 !important; font-family: 'Space Mono', monospace !important; } |
| .output-box .block { border: none !important; border-style: none !important; overflow: visible !important; box-shadow: none !important; padding: 0 !important; } |
| .output-box .hide-container { border: none !important; border-style: none !important; } |
| .output-box .wrap.hide { display: none !important; } |
| .output-box .label-wrap { display: none !important; } |
| .output-box span.prose, .output-box span.md { border: none !important; padding: 0 !important; display: inline !important; } |
| .output-box .prose:empty, .output-box div.prose:has(span:empty) { border: none !important; padding: 0 !important; min-height: 0 !important; } |
| |
| .footer-text { text-align: center; padding: 20px; color: #706060; font-size: 0.65rem; font-weight: 300; letter-spacing: 0.05em; } |
| .footer-text a { color: #b08060; text-decoration: none; } |
| """ |
|
|
| with gr.Blocks(css=CUSTOM_CSS, title="Working for the Weekend", theme=gr.themes.Base()) as demo: |
| gr.HTML(""" |
| <div class="app-header"> |
| <h1>Working for the Weekend</h1> |
| <div class="sub">Everybody's working for the weekend</div> |
| </div> |
| <div class="app-visual">⏰</div> |
| """) |
|
|
| with gr.Column(elem_classes="input-box"): |
| user_input = gr.Textbox( |
| label="What's your work situation?", |
| placeholder="9-5 with an hour commute, 60 hours in finance, two jobs to make rent...", |
| lines=2, max_lines=3, |
| ) |
| with gr.Row(): |
| go_btn = gr.Button("Show me the math", variant="primary", size="lg") |
| random_btn = gr.Button("Surprise me", variant="secondary", size="sm") |
| with gr.Column(elem_classes="output-box"): |
| output = gr.Markdown(label="") |
|
|
| gr.Examples( |
| examples=[ |
| ["I work 9-5 with an hour commute each way"], |
| ["I work 60 hours a week in finance"], |
| ["I'm a teacher and I bring work home every night"], |
| ["I work from home but I'm always online"], |
| ["I work two jobs to make rent"], |
| ["I freelance and I never stop working"], |
| ], |
| inputs=[user_input], |
| ) |
|
|
| go_btn.click(calculate, [user_input], [output]) |
| random_btn.click(calculate_random, [], [output]) |
| gr.HTML('<div class="footer-text">Heuremen — Let\'s stay connected and keep information free.<br><a href="https://heuremenforprofit.online">heuremenforprofit.online</a></div>') |
|
|
| if __name__ == "__main__": |
| demo.launch() |
|
|