timelord7000 commited on
Commit
7811d64
Β·
verified Β·
1 Parent(s): 583b8c2

bueaty now edit to mvp 3 functional features that save actual human struggle time

Browse files
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
- title: Career Command Center
3
- emoji: 🌍
4
- colorFrom: pink
5
- colorTo: purple
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
1
  ---
2
+ title: Career Command Center πŸš€
3
+ colorFrom: yellow
4
+ colorTo: yellow
5
+ emoji: 🐳
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite-v3
10
  ---
11
 
12
+ # Welcome to your new DeepSite project!
13
+ This project was created with [DeepSite](https://huggingface.co/deepsite).
components/footer.js ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class FooterWarrior extends HTMLElement {
2
+ connectedCallback() {
3
+ this.attachShadow({ mode: 'open' });
4
+ this.shadowRoot.innerHTML = `
5
+ <style>
6
+ :host {
7
+ display: block;
8
+ background: #020617;
9
+ padding: 4rem 1.5rem;
10
+ border-top: 1px solid rgba(255,255,255,0.05);
11
+ margin-top: auto;
12
+ }
13
+ .container {
14
+ max-width: 1200px;
15
+ margin: 0 auto;
16
+ }
17
+ .grid {
18
+ display: grid;
19
+ grid-template-columns: 1fr;
20
+ gap: 2rem;
21
+ }
22
+ @media (min-width: 768px) {
23
+ .grid {
24
+ grid-template-columns: 2fr 1fr 1fr;
25
+ }
26
+ }
27
+ h3 {
28
+ color: #f8fafc;
29
+ font-size: 1.1rem;
30
+ margin-bottom: 1rem;
31
+ font-weight: 600;
32
+ }
33
+ p {
34
+ color: #64748b;
35
+ line-height: 1.6;
36
+ font-size: 0.9rem;
37
+ }
38
+ .link {
39
+ display: block;
40
+ color: #64748b;
41
+ text-decoration: none;
42
+ margin-bottom: 0.75rem;
43
+ font-size: 0.9rem;
44
+ }
45
+ .link:hover {
46
+ color: #6366f1;
47
+ }
48
+ .copyright {
49
+ margin-top: 3rem;
50
+ padding-top: 1.5rem;
51
+ border-top: 1px solid rgba(255,255,255,0.05);
52
+ text-align: center;
53
+ color: #475569;
54
+ font-size: 0.85rem;
55
+ }
56
+ </style>
57
+ <div class="container">
58
+ <div class="grid">
59
+ <div>
60
+ <h3>About Wage Warrior</h3>
61
+ <p>
62
+ We believe in testing your worth constantly. If you are doing more for less,
63
+ you are in the wrong place. We provide the data to arm yourself for the negotiation table
64
+ or the exit door.
65
+ </p>
66
+ </div>
67
+ <div>
68
+ <h3>Tools</h3>
69
+ <a href="#calculator" class="link">Salary Gap Calculator</a>
70
+ <a href="#framework" class="link">Negotiation Pseudocode</a>
71
+ <a href="#jobs" class="link">Market Scanner</a>
72
+ </div>
73
+ <div>
74
+ <h3>Legal</h3>
75
+ <a href="#" class="link">Privacy Protocol</a>
76
+ <a href="#" class="link">Terms of Engagement</a>
77
+ </div>
78
+ </div>
79
+ <div class="copyright">
80
+ &copy; 2023 Wage Warrior. Don't settle.
81
+ </div>
82
+ </div>
83
+ `;
84
+ }
85
+ }
86
+ customElements.define('footer-warrior', FooterWarrior);
components/job-card.js ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class JobCard extends HTMLElement {
2
+ connectedCallback() {
3
+ this.attachShadow({ mode: 'open' });
4
+
5
+ // Get attributes
6
+ const title = this.getAttribute('title') || 'Unknown Role';
7
+ const company = this.getAttribute('company') || 'Unknown Corp';
8
+ const salary = this.getAttribute('salary') || 'Competitive';
9
+ const type = this.getAttribute('type') || 'Full-time';
10
+ const url = this.getAttribute('url') || '#';
11
+ const category = this.getAttribute('category') || 'General';
12
+ const isSaved = this.getAttribute('saved') === 'true';
13
+
14
+ this.shadowRoot.innerHTML = `
15
+ <style>
16
+ :host {
17
+ display: block;
18
+ }
19
+ .card {
20
+ background: #1e293b;
21
+ border: 1px solid #334155;
22
+ border-radius: 0.75rem;
23
+ padding: 1.5rem;
24
+ transition: transform 0.2s, box-shadow 0.2s;
25
+ display: flex;
26
+ flex-direction: column;
27
+ justify-content: space-between;
28
+ height: 100%;
29
+ position: relative;
30
+ }
31
+ .card:hover {
32
+ transform: translateY(-5px);
33
+ box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.3);
34
+ border-color: #6366f1;
35
+ }
36
+ .cat-tag {
37
+ display: inline-block;
38
+ background: rgba(99, 102, 241, 0.1);
39
+ color: #818cf8;
40
+ padding: 0.25rem 0.75rem;
41
+ border-radius: 9999px;
42
+ font-size: 0.75rem;
43
+ font-weight: 600;
44
+ text-transform: uppercase;
45
+ margin-bottom: 0.75rem;
46
+ }
47
+ h3 {
48
+ color: #f1f5f9;
49
+ font-size: 1.125rem;
50
+ font-weight: 600;
51
+ margin: 0 0 0.5rem 0;
52
+ line-height: 1.4;
53
+ padding-right: 2rem;
54
+ }
55
+ .company {
56
+ color: #94a3b8;
57
+ font-size: 0.9rem;
58
+ margin-bottom: 1.5rem;
59
+ display: flex;
60
+ align-items: center;
61
+ gap: 0.5rem;
62
+ }
63
+ .meta {
64
+ display: flex;
65
+ justify-content: space-between;
66
+ align-items: center;
67
+ font-size: 0.85rem;
68
+ color: #cbd5e1;
69
+ padding-top: 1rem;
70
+ border-top: 1px solid #334155;
71
+ }
72
+ .salary {
73
+ color: #10b981;
74
+ font-weight: 600;
75
+ }
76
+ .btn {
77
+ color: #6366f1;
78
+ text-decoration: none;
79
+ font-weight: 600;
80
+ font-size: 0.9rem;
81
+ display: flex;
82
+ align-items: center;
83
+ gap: 0.25rem;
84
+ }
85
+ .btn:hover {
86
+ text-decoration: underline;
87
+ }
88
+ .save-btn {
89
+ position: absolute;
90
+ top: 1.25rem;
91
+ right: 1.25rem;
92
+ background: rgba(15, 23, 42, 0.5);
93
+ border: 1px solid #334155;
94
+ color: ${isSaved ? '#ef4444' : '#94a3b8'};
95
+ border-radius: 50%;
96
+ width: 36px;
97
+ height: 36px;
98
+ display: flex;
99
+ align-items: center;
100
+ justify-content: center;
101
+ cursor: pointer;
102
+ transition: all 0.2s;
103
+ }
104
+ .save-btn:hover {
105
+ background: #ef4444;
106
+ color: white;
107
+ border-color: #ef4444;
108
+ }
109
+ .save-btn.active {
110
+ background: #ef4444;
111
+ color: white;
112
+ border-color: #ef4444;
113
+ }
114
+ </style>
115
+ <div class="card">
116
+ <div>
117
+ <button class="save-btn ${isSaved ? 'active' : ''}" id="saveBtn">
118
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="${isSaved ? 'currentColor' : 'none'}" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"></path></svg>
119
+ </button>
120
+ <span class="cat-tag">${category}</span>
121
+ <h3>${title}</h3>
122
+ <div class="company">
123
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="7" width="20" height="14" rx="2" ry="2"></rect><path d="M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"></path></svg>
124
+ ${company}
125
+ </div>
126
+ </div>
127
+ <div>
128
+ <div class="meta">
129
+ <span class="salary">${salary}</span>
130
+ <span>${type}</span>
131
+ </div>
132
+ <a href="${url}" target="_blank" class="btn">
133
+ Apply Now
134
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="7" y1="17" x2="17" y2="7"></line><polyline points="7 7 17 7 17 17"></polyline></svg>
135
+ </a>
136
+ </div>
137
+ </div>
138
+ `;
139
+
140
+ const saveBtn = this.shadowRoot.getElementById('saveBtn');
141
+ saveBtn.addEventListener('click', () => {
142
+ const eventData = { title, company, salary, type, url, category };
143
+
144
+ // Dispatch event to parent script.js
145
+ const eventName = isSaved ? 'job-removed' : 'job-saved';
146
+ this.dispatchEvent(new CustomEvent(eventName, {
147
+ bubbles: true,
148
+ composed: true,
149
+ detail: isSaved ? { id: url } : eventData
150
+ }));
151
+ });
152
+ }
153
+ }
154
+ customElements.define('job-card', JobCard);
components/navbar.js ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class NavbarWarrior extends HTMLElement {
2
+ connectedCallback() {
3
+ this.attachShadow({ mode: 'open' });
4
+ this.shadowRoot.innerHTML = `
5
+ <style>
6
+ :host {
7
+ display: block;
8
+ width: 100%;
9
+ background: rgba(15, 23, 42, 0.9);
10
+ backdrop-filter: blur(12px);
11
+ position: fixed;
12
+ top: 0;
13
+ z-index: 50;
14
+ border-bottom: 1px solid rgba(255,255,255,0.05);
15
+ }
16
+ nav {
17
+ max-width: 1200px;
18
+ margin: 0 auto;
19
+ padding: 1rem 1.5rem;
20
+ display: flex;
21
+ justify-content: space-between;
22
+ align-items: center;
23
+ }
24
+ .logo {
25
+ font-weight: 800;
26
+ font-size: 1.25rem;
27
+ color: #ffffff;
28
+ text-decoration: none;
29
+ display: flex;
30
+ align-items: center;
31
+ gap: 0.5rem;
32
+ letter-spacing: -0.025em;
33
+ }
34
+ .logo span {
35
+ color: #6366f1;
36
+ }
37
+ .nav-links {
38
+ display: none;
39
+ }
40
+ .nav-link {
41
+ color: #94a3b8;
42
+ text-decoration: none;
43
+ margin-left: 2rem;
44
+ font-size: 0.95rem;
45
+ font-weight: 500;
46
+ transition: color 0.2s;
47
+ }
48
+ .nav-link:hover {
49
+ color: #fff;
50
+ }
51
+ .nav-link.active {
52
+ color: #10b981;
53
+ }
54
+ @media (min-width: 768px) {
55
+ .nav-links {
56
+ display: block;
57
+ }
58
+ }
59
+ </style>
60
+ <nav>
61
+ <a href="#" class="logo">
62
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-primary-500"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon></svg>
63
+ Wage<span>Warrior</span>
64
+ </a>
65
+ <div class="nav-links">
66
+ <a href="#framework" class="nav-link">Framework</a>
67
+ <a href="#calculator" class="nav-link">Calculator</a>
68
+ <a href="#jobs" class="nav-link">Hunt Jobs</a>
69
+ </div>
70
+ </nav>
71
+ `;
72
+ }
73
+ }
74
+ customElements.define('nav-warrior', NavbarWarrior);
components/salary-calculator.js ADDED
@@ -0,0 +1,243 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class SalaryCalculator extends HTMLElement {
2
+ connectedCallback() {
3
+ this.attachShadow({ mode: 'open' });
4
+ this.shadowRoot.innerHTML = `
5
+ <style>
6
+ :host {
7
+ display: block;
8
+ width: 100%;
9
+ }
10
+ .card {
11
+ background: #1e293b;
12
+ border-radius: 1rem;
13
+ padding: 2rem;
14
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.5);
15
+ border: 1px solid rgba(255,255,255,0.05);
16
+ }
17
+ .form-grid {
18
+ display: grid;
19
+ grid-template-columns: 1fr;
20
+ gap: 1.5rem;
21
+ margin-bottom: 2rem;
22
+ }
23
+ @media (min-width: 768px) {
24
+ .form-grid {
25
+ grid-template-columns: 1fr 1fr;
26
+ }
27
+ }
28
+ label {
29
+ display: block;
30
+ color: #94a3b8;
31
+ margin-bottom: 0.5rem;
32
+ font-size: 0.9rem;
33
+ }
34
+ input, select {
35
+ width: 100%;
36
+ background: #0f172a;
37
+ border: 1px solid #334155;
38
+ color: white;
39
+ padding: 0.75rem;
40
+ border-radius: 0.5rem;
41
+ font-size: 1rem;
42
+ box-sizing: border-box;
43
+ }
44
+ input:focus, select:focus {
45
+ outline: none;
46
+ border-color: #6366f1;
47
+ box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.2);
48
+ }
49
+ .btn {
50
+ width: 100%;
51
+ background: #10b981;
52
+ color: white;
53
+ border: none;
54
+ padding: 1rem;
55
+ border-radius: 0.5rem;
56
+ font-weight: bold;
57
+ font-size: 1rem;
58
+ cursor: pointer;
59
+ transition: background 0.2s;
60
+ }
61
+ .btn:hover {
62
+ background: #059669;
63
+ }
64
+ .result {
65
+ margin-top: 2rem;
66
+ padding: 1.5rem;
67
+ background: #0f172a;
68
+ border-radius: 0.5rem;
69
+ border-left: 4px solid #6366f1;
70
+ display: none;
71
+ }
72
+ .result.active {
73
+ display: block;
74
+ animation: fadeIn 0.5s ease;
75
+ }
76
+ h4 {
77
+ margin: 0 0 0.5rem 0;
78
+ color: #e2e8f0;
79
+ }
80
+ .value {
81
+ font-size: 1.5rem;
82
+ font-weight: bold;
83
+ }
84
+ .value.positive { color: #10b981; }
85
+ .value.negative { color: #ef4444; }
86
+ .desc {
87
+ font-size: 0.9rem;
88
+ color: #94a3b8;
89
+ margin-top: 0.5rem;
90
+ }
91
+ @keyframes fadeIn {
92
+ from { opacity: 0; transform: translateY(10px); }
93
+ to { opacity: 1; transform: translateY(0); }
94
+ }
95
+ </style>
96
+
97
+ <div class="card">
98
+ <h3 style="color: white; font-size: 1.25rem; margin-bottom: 1.5rem;">Underpayment Analysis</h3>
99
+ <div class="form-grid">
100
+ <div>
101
+ <label>Your Annual Salary ($)</label>
102
+ <input type="number" id="mySalary" placeholder="e.g. 65000">
103
+ </div>
104
+ <div>
105
+ <label>Industry Average for Role ($)</label>
106
+ <input type="number" id="marketSalary" placeholder="e.g. 85000">
107
+ </div>
108
+ <div>
109
+ <label>Peer Salary (Lazy Coworker) ($)</label>
110
+ <input type="number" id="peerSalary" placeholder="e.g. 90000">
111
+ </div>
112
+ <div>
113
+ <label>Respect Level at Work</label>
114
+ <select id="respectLevel">
115
+ <option value="high">High (Valued)</option>
116
+ <option value="medium">Medium (Ignored)</option>
117
+ <option value="low">Low (Disrespected)</option>
118
+ </select>
119
+ </div>
120
+ </div>
121
+ <button class="btn" id="calcBtn">Analyze Worth</button>
122
+ <div class="result" id="resultBox">
123
+ <h4>Analysis Result</h4>
124
+ <div class="value" id="gapValue"></div>
125
+ <p class="desc" id="adviceText"></p>
126
+
127
+ <!-- Feature 2: Email Generator -->
128
+ <div style="margin-top: 1.5rem; border-top: 1px solid #334155; padding-top: 1rem;">
129
+ <button id="genEmailBtn" style="background: #4f46e5; color: white; border: none; padding: 0.5rem 1rem; border-radius: 0.375rem; font-size: 0.875rem; cursor: pointer; display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.75rem;">
130
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path><polyline points="22,6 12,13 2,6"></polyline></svg>
131
+ Generate Negotiation Email
132
+ </button>
133
+ <textarea id="emailDraft" readonly style="width: 100%; background: #0f172a; border: 1px solid #334155; color: #cbd5e1; padding: 0.75rem; border-radius: 0.5rem; font-size: 0.85rem; font-family: monospace; resize: vertical; min-height: 120px; display: none;"></textarea>
134
+ </div>
135
+ </div>
136
+ </div>
137
+ `;
138
+
139
+ const btn = this.shadowRoot.getElementById('calcBtn');
140
+ btn.addEventListener('click', () => this.calculate());
141
+ }
142
+
143
+ calculate() {
144
+ const mySalary = parseFloat(this.shadowRoot.getElementById('mySalary').value) || 0;
145
+ const marketSalary = parseFloat(this.shadowRoot.getElementById('marketSalary').value) || 0;
146
+ const peerSalary = parseFloat(this.shadowRoot.getElementById('peerSalary').value) || 0;
147
+ const respect = this.shadowRoot.getElementById('respectLevel').value;
148
+ const resultBox = this.shadowRoot.getElementById('resultBox');
149
+ const gapValue = this.shadowRoot.getElementById('gapValue');
150
+ const adviceText = this.shadowRoot.getElementById('adviceText');
151
+
152
+ let message = "";
153
+ let gap = 0;
154
+ let colorClass = "";
155
+
156
+ // Logic: If peer makes more and does less, big issue.
157
+ // If market is higher, issue.
158
+
159
+ const peerGap = mySalary - peerSalary;
160
+ const marketGap = mySalary - marketSalary;
161
+
162
+ if (peerGap < 0) {
163
+ gap = Math.abs(peerGap);
164
+ message = "Your lazy peer makes $" + gap.toLocaleString() + " more than you. This is unacceptable.";
165
+ colorClass = "negative";
166
+ } else if (marketGap < 0) {
167
+ gap = Math.abs(marketGap);
168
+ message = "The market pays $" + gap.toLocaleString() + " more for your role.";
169
+ colorClass = "negative";
170
+ } else {
171
+ gap = peerGap; // Positive
172
+ message = "You are doing surprisingly well financially.";
173
+ colorClass = "positive";
174
+ }
175
+
176
+ // Respect modifier
177
+ if (respect === 'low' && colorClass === 'negative') {
178
+ message += " Combined with the disrespect, you should leave immediately.";
179
+ }
180
+
181
+ gapValue.textContent = (colorClass === 'negative' ? "-$" : "+$") + gap.toLocaleString();
182
+ gapValue.className = "value " + colorClass;
183
+ adviceText.textContent = message;
184
+
185
+ // Setup Email Generator Button
186
+ const genBtn = this.shadowRoot.getElementById('genEmailBtn');
187
+ genBtn.style.display = 'flex';
188
+ genBtn.onclick = () => {
189
+ const draftArea = this.shadowRoot.getElementById('emailDraft');
190
+ draftArea.style.display = 'block';
191
+ draftArea.value = this.generateEmailDraft(gap, colorClass, respect);
192
+ genBtn.textContent = 'Email Draft Ready';
193
+ genBtn.disabled = true;
194
+ genBtn.style.opacity = '0.7';
195
+ };
196
+
197
+ resultBox.classList.add('active');
198
+ }
199
+
200
+ generateEmailDraft(gap, type, respect) {
201
+ const date = new Date().toLocaleDateString();
202
+ if (type === 'positive' && gap > 5000) {
203
+ return `Subject: Performance Review & Compensation Adjustment
204
+
205
+ Hi [Manager's Name],
206
+
207
+ I hope you're having a great week.
208
+
209
+ I've been reflecting on my contributions over the past year, specifically regarding [Project X] and [Project Y].
210
+
211
+ Based on current market data and my performance metrics, I believe my compensation is no longer aligned with the value I'm bringing to the team. The market rate for my role is approximately ${gap.toLocaleString()} higher than my current salary.
212
+
213
+ I would love to discuss adjusting my salary to reflect these contributions. I'm committed to the team's success and want to ensure we are aligned on my value here.
214
+
215
+ Can we schedule a brief time to chat this week?
216
+
217
+ Best,
218
+ [Your Name]`;
219
+ } else if (type === 'negative') {
220
+ return `Subject: Resignation - [Your Name]
221
+
222
+ Dear [Manager's Name],
223
+
224
+ Please accept this letter as formal notification that I am resigning from my position as [Your Position]. My last day will be [Date].
225
+
226
+ I appreciate the opportunities I've had here, but I have accepted a position that offers a compensation package better aligned with my market value and professional growth.
227
+
228
+ I will do everything possible to wrap up my duties and train other team members during the transition period.
229
+
230
+ Best regards,
231
+ [Your Name]`;
232
+ }
233
+ return `Subject: Career Development Discussion
234
+
235
+ Hi [Manager's Name],
236
+
237
+ I'd like to schedule a time to discuss my career path and future goals with the company.
238
+
239
+ Best,
240
+ [Your Name]`;
241
+ }
242
+ }
243
+ customElements.define('salary-calculator', SalaryCalculator);
index.html CHANGED
@@ -1,19 +1,201 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en" class="scroll-smooth">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Wage Warrior πŸ’Έ | Hunt Your Worth</title>
7
+ <link rel="icon" type="image/x-icon" href="https://cdn-icons-png.flaticon.com/512/3135/3135715.png">
8
+ <link rel="stylesheet" href="style.css">
9
+ <script src="https://cdn.tailwindcss.com"></script>
10
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
11
+ <script src="https://unpkg.com/feather-icons"></script>
12
+
13
+ <!-- Custom Config for "Undefined" Colors mapped to Indigo/Emerald -->
14
+ <script>
15
+ tailwind.config = {
16
+ darkMode: 'class',
17
+ theme: {
18
+ extend: {
19
+ colors: {
20
+ primary: {
21
+ 500: '#6366f1', // Indigo-500
22
+ 600: '#4f46e5', // Indigo-600
23
+ 900: '#312e81', // Indigo-900
24
+ },
25
+ secondary: {
26
+ 500: '#10b981', // Emerald-500
27
+ 600: '#059669', // Emerald-600
28
+ }
29
+ }
30
+ }
31
+ }
32
+ }
33
+ </script>
34
+
35
+ <!-- Web Components -->
36
+ <script src="components/navbar.js"></script>
37
+ <script src="components/footer.js"></script>
38
+ <script src="components/salary-calculator.js"></script>
39
+ <script src="components/job-card.js"></script>
40
+ </head>
41
+ <body class="bg-slate-950 text-slate-200 font-sans antialiased selection:bg-primary-500 selection:text-white">
42
+
43
+ <!-- Navbar Component -->
44
+ <nav-warrior></nav-warrior>
45
+
46
+ <!-- Hero Section -->
47
+ <header class="relative pt-20 pb-32 overflow-hidden">
48
+ <div class="absolute inset-0 z-0 opacity-20 bg-[url('http://static.photos/technology/1200x630/88')] bg-cover bg-center"></div>
49
+ <div class="absolute inset-0 z-0 bg-gradient-to-b from-slate-950/50 via-slate-950 to-slate-950"></div>
50
+
51
+ <div class="container mx-auto px-6 relative z-10 text-center">
52
+ <span class="inline-block py-1 px-3 rounded-full bg-primary-900/50 border border-primary-500/30 text-primary-300 text-sm font-semibold tracking-wide mb-6 animate-pulse">
53
+ v2.0: Context Hungry Engine
54
+ </span>
55
+ <h1 class="text-5xl md:text-7xl font-extrabold tracking-tight mb-6 bg-clip-text text-transparent bg-gradient-to-r from-white via-slate-200 to-slate-400">
56
+ Stop Rocking the Boat. <br/>
57
+ <span class="text-primary-500">Sink the Ship.</span>
58
+ </h1>
59
+ <p class="text-xl md:text-2xl text-slate-400 mb-10 max-w-3xl mx-auto leading-relaxed">
60
+ Constantly hunt for upgrades. Stop accepting disrespect. Get paid more than the peers who do less. The ultimate tool for the unappreciated.
61
+ </p>
62
+ <div class="flex flex-col sm:flex-row justify-center gap-4">
63
+ <a href="#calculator" class="px-8 py-4 bg-primary-600 hover:bg-primary-500 text-white font-bold rounded-lg transition-all transform hover:scale-105 shadow-lg shadow-primary-500/20 flex items-center justify-center gap-2">
64
+ <i data-feather="crosshair"></i> Calculate Your Worth
65
+ </a>
66
+ <a href="#jobs" class="px-8 py-4 bg-slate-800 hover:bg-slate-700 border border-slate-700 text-white font-bold rounded-lg transition-all transform hover:scale-105 flex items-center justify-center gap-2">
67
+ <i data-feather="briefcase"></i> Hunt Market Data
68
+ </a>
69
+ </div>
70
+ </div>
71
+ </header>
72
+
73
+ <!-- Framework / Pseudocode Section -->
74
+ <section id="framework" class="py-20 bg-slate-900/50 border-y border-slate-800">
75
+ <div class="container mx-auto px-6">
76
+ <div class="grid md:grid-cols-2 gap-12 items-center">
77
+ <div>
78
+ <h2 class="text-3xl font-bold text-white mb-4">The Upgrade Algorithm</h2>
79
+ <p class="text-slate-400 mb-6">
80
+ We don't just list jobs. We provide a <strong>context-hungry framework</strong> to analyze your current position.
81
+ If your inputs meet specific criteria, the system advises an aggressive career pivot.
82
+ </p>
83
+ <ul class="space-y-4">
84
+ <li class="flex items-start">
85
+ <i data-feather="check-circle" class="text-secondary-500 mt-1 mr-3"></i>
86
+ <span class="text-slate-300">Analyze peer performance vs. your output.</span>
87
+ </li>
88
+ <li class="flex items-start">
89
+ <i data-feather="check-circle" class="text-secondary-500 mt-1 mr-3"></i>
90
+ <span class="text-slate-300">Detect "Rocking the Boat" suppression tactics.</span>
91
+ </li>
92
+ <li class="flex items-start">
93
+ <i data-feather="check-circle" class="text-secondary-500 mt-1 mr-3"></i>
94
+ <span class="text-slate-300">Execute the Exit Strategy Protocol.</span>
95
+ </li>
96
+ </ul>
97
+ </div>
98
+ <div class="bg-slate-950 rounded-xl p-6 shadow-2xl border border-slate-800 font-mono text-sm overflow-hidden relative group">
99
+ <div class="absolute top-0 right-0 p-2 opacity-50">
100
+ <div class="w-3 h-3 rounded-full bg-red-500 inline-block mr-1"></div>
101
+ <div class="w-3 h-3 rounded-full bg-yellow-500 inline-block mr-1"></div>
102
+ <div class="w-3 h-3 rounded-full bg-green-500 inline-block"></div>
103
+ </div>
104
+ <pre class="text-slate-300"><code><span class="text-purple-400">function</span> <span class="text-blue-400">assessLoyalty</span>(salary, respect) {
105
+ <span class="text-purple-400">if</span> (salary < marketValue && respect == <span class="text-orange-400">false</span>) {
106
+ <span class="text-slate-500">// Stop rocking the boat</span>
107
+ <span class="text-purple-400">return</span> <span class="text-green-400">INITIATE_HUNT</span>;
108
+ }
109
+ <span class="text-purple-400">if</span> (peerOutput < myOutput && peerSalary > mySalary) {
110
+ <span class="text-slate-500">// Maximize tool use</span>
111
+ <span class="text-purple-400">return</span> <span class="text-red-400">RAGE_QUIT_PROBABLY</span>;
112
+ }
113
+ <span class="text-purple-400">return</span> <span class="text-slate-500">"Stay and grind (for now)"</span>;
114
+ }</code></pre>
115
+ <div class="absolute bottom-4 right-4 opacity-0 group-hover:opacity-100 transition-opacity text-xs text-primary-500">Executing...</div>
116
+ </div>
117
+ </div>
118
+ </div>
119
+ </section>
120
+
121
+ <!-- Salary Calculator Component -->
122
+ <section id="calculator" class="py-20 relative">
123
+ <div class="container mx-auto px-6">
124
+ <h2 class="text-3xl font-bold text-center mb-12">Reality Check Calculator</h2>
125
+ <salary-calculator></salary-calculator>
126
+ </div>
127
+ </section>
128
+ <!-- Job Hunter API Section -->
129
+ <section id="jobs" class="py-20 bg-slate-900/30">
130
+ <div class="container mx-auto px-6">
131
+ <div class="flex flex-col md:flex-row justify-between items-end mb-10 gap-4">
132
+ <div>
133
+ <h2 class="text-3xl font-bold text-white mb-2">Active Targets</h2>
134
+ <p class="text-slate-400">Real-time feed from the market. Filter for upgrade opportunities.</p>
135
+ </div>
136
+ <div class="hidden md:flex items-center gap-3">
137
+ <span class="flex items-center text-sm text-secondary-500 bg-secondary-900/20 px-3 py-1 rounded-full border border-secondary-500/20">
138
+ <span class="w-2 h-2 bg-secondary-500 rounded-full mr-2 animate-pulse"></span>
139
+ Live API Feed
140
+ </span>
141
+ </div>
142
+ </div>
143
+
144
+ <!-- Feature 1: Smart Search & Filter -->
145
+ <div class="bg-slate-800/50 p-4 rounded-xl border border-slate-700 mb-8 flex flex-col md:flex-row gap-4">
146
+ <div class="flex-grow">
147
+ <label class="block text-xs text-slate-400 mb-1">Keyword Search</label>
148
+ <input type="text" id="jobSearch" placeholder="e.g. React, Senior, Remote..."
149
+ class="w-full bg-slate-950 border border-slate-700 text-white px-4 py-2 rounded-lg focus:outline-none focus:border-primary-500 transition-colors">
150
+ </div>
151
+ <div class="w-full md:w-64">
152
+ <label class="block text-xs text-slate-400 mb-1">Category</label>
153
+ <select id="categoryFilter" class="w-full bg-slate-950 border border-slate-700 text-white px-4 py-2 rounded-lg focus:outline-none focus:border-primary-500 transition-colors">
154
+ <option value="">All Categories</option>
155
+ <option value="software-dev">Software Development</option>
156
+ <option value="customer-support">Customer Support</option>
157
+ <option value="design">Design</option>
158
+ <option value="marketing">Marketing</option>
159
+ <option value="product">Product</option>
160
+ </select>
161
+ </div>
162
+ </div>
163
+ <!-- Job Grid -->
164
+ <div id="job-grid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
165
+ <!-- Content injected by script.js via Web Component -->
166
+ <div class="col-span-full text-center py-12">
167
+ <i data-feather="loader" class="animate-spin mx-auto text-primary-500 mb-4"></i>
168
+ <p class="text-slate-500">Scanning market for upgrades...</p>
169
+ </div>
170
+ </div>
171
+ </div>
172
+ </section>
173
+ <!-- Feature 3: Application Tracker (Saved Targets) -->
174
+ <section id="tracker" class="py-20 border-t border-slate-800">
175
+ <div class="container mx-auto px-6">
176
+ <div class="flex items-center gap-3 mb-8">
177
+ <div class="w-10 h-10 rounded-full bg-gradient-to-br from-primary-500 to-purple-600 flex items-center justify-center">
178
+ <i data-feather="target" class="text-white"></i>
179
+ </div>
180
+ <div>
181
+ <h2 class="text-3xl font-bold text-white">My Hitlist</h2>
182
+ <p class="text-slate-400 text-sm">Saved opportunities you're actively hunting.</p>
183
+ </div>
184
+ </div>
185
+
186
+ <div id="saved-jobs-list" class="grid grid-cols-1 gap-4">
187
+ <!-- Saved jobs injected here -->
188
+ <div class="text-center py-12 bg-slate-900/50 rounded-xl border border-dashed border-slate-700">
189
+ <p class="text-slate-500">No targets locked yet. Click the heart on job cards to save them.</p>
190
+ </div>
191
+ </div>
192
+ </div>
193
+ </section>
194
+
195
+ <!-- Footer Component -->
196
+ <footer-warrior></footer-warrior>
197
+ <script src="script.js"></script>
198
+ <script>feather.replace();</script>
199
+ <script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
200
+ </body>
201
+ </html>
script.js ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ document.addEventListener('DOMContentLoaded', () => {
3
+ loadJobs();
4
+ loadSavedJobs();
5
+ setupEventListeners();
6
+ });
7
+
8
+ // Feature 1 & 3: Global State & Event Listeners
9
+ function setupEventListeners() {
10
+ const searchInput = document.getElementById('jobSearch');
11
+ const categorySelect = document.getElementById('categoryFilter');
12
+
13
+ searchInput.addEventListener('input', debounce(() => {
14
+ loadJobs(searchInput.value, categorySelect.value);
15
+ }, 500));
16
+
17
+ categorySelect.addEventListener('change', () => {
18
+ loadJobs(searchInput.value, categorySelect.value);
19
+ });
20
+
21
+ // Listen for save events from job cards
22
+ document.addEventListener('job-saved', (e) => {
23
+ saveJob(e.detail);
24
+ });
25
+
26
+ // Listen for remove events
27
+ document.addEventListener('job-removed', (e) => {
28
+ removeJob(e.detail.id);
29
+ });
30
+ }
31
+
32
+ // Feature 3: Save Job Logic
33
+ function saveJob(jobData) {
34
+ let saved = JSON.parse(localStorage.getItem('warriorSavedJobs')) || [];
35
+
36
+ // Avoid duplicates
37
+ if (saved.some(j => j.url === jobData.url)) {
38
+ alert('Target already in Hitlist.');
39
+ return;
40
+ }
41
+
42
+ jobData.savedAt = new Date().toISOString();
43
+ saved.push(jobData);
44
+ localStorage.setItem('warriorSavedJobs', JSON.stringify(saved));
45
+ loadSavedJobs(); // Refresh UI
46
+ }
47
+
48
+ function removeJob(url) {
49
+ let saved = JSON.parse(localStorage.getItem('warriorSavedJobs')) || [];
50
+ saved = saved.filter(j => j.url !== url);
51
+ localStorage.setItem('warriorSavedJobs', JSON.stringify(saved));
52
+ loadSavedJobs(); // Refresh UI
53
+ }
54
+
55
+ function loadSavedJobs() {
56
+ const container = document.getElementById('saved-jobs-list');
57
+ const saved = JSON.parse(localStorage.getItem('warriorSavedJobs')) || [];
58
+
59
+ if (saved.length === 0) {
60
+ container.innerHTML = `
61
+ <div class="text-center py-12 bg-slate-900/50 rounded-xl border border-dashed border-slate-700">
62
+ <p class="text-slate-500">No targets locked yet. Click the heart on job cards to save them.</p>
63
+ </div>`;
64
+ return;
65
+ }
66
+
67
+ container.innerHTML = '';
68
+ saved.forEach(job => {
69
+ const el = document.createElement('div');
70
+ el.className = 'bg-slate-800 p-4 rounded-lg border border-slate-700 flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4';
71
+ el.innerHTML = `
72
+ <div class="flex-grow">
73
+ <h4 class="text-white font-bold">${job.title}</h4>
74
+ <p class="text-slate-400 text-sm">${job.company}</p>
75
+ </div>
76
+ <div class="flex items-center gap-3 w-full sm:w-auto">
77
+ <span class="text-xs text-slate-500 hidden sm:block">Added: ${new Date(job.savedAt).toLocaleDateString()}</span>
78
+ <a href="${job.url}" target="_blank" class="px-4 py-2 bg-primary-600 hover:bg-primary-500 text-white text-sm rounded-lg font-medium">Apply</a>
79
+ <button onclick="removeJob('${job.url}')" class="p-2 text-red-400 hover:bg-red-900/20 rounded-lg">
80
+ <i data-feather="trash-2" class="w-4 h-4"></i>
81
+ </button>
82
+ </div>
83
+ `;
84
+ container.appendChild(el);
85
+ });
86
+ feather.replace();
87
+ }
88
+
89
+ // Feature 1: Enhanced Load Jobs with Filtering
90
+ async function loadJobs(searchTerm = '', category = '') {
91
+ const grid = document.getElementById('job-grid');
92
+
93
+ // Show loading state if it's empty
94
+ if (grid.innerHTML.trim() === '') {
95
+ grid.innerHTML = `<div class="col-span-full text-center py-12"><i data-feather="loader" class="animate-spin mx-auto text-primary-500 mb-4"></i><p class="text-slate-500">Scanning market...</p></div>`;
96
+ feather.replace();
97
+ }
98
+
99
+ try {
100
+ const response = await fetch('https://remotive.com/api/remote-jobs?limit=12');
101
+ const data = await response.json();
102
+
103
+ grid.innerHTML = '';
104
+
105
+ if(data.jobs && data.jobs.length > 0) {
106
+ const filtered = data.jobs.filter(job => {
107
+ // Category Filter Logic
108
+ if (category && job.category !== category) return false;
109
+
110
+ // Search Logic
111
+ if (searchTerm) {
112
+ const term = searchTerm.toLowerCase();
113
+ const title = job.title.toLowerCase();
114
+ const company = job.company_name.toLowerCase();
115
+ return title.includes(term) || company.includes(term);
116
+ }
117
+ return true;
118
+ });
119
+
120
+ if (filtered.length === 0) {
121
+ grid.innerHTML = '<p class="col-span-full text-center text-slate-500 py-10">No targets match your filters.</p>';
122
+ return;
123
+ }
124
+
125
+ filtered.forEach(job => {
126
+ // Check if already saved
127
+ const saved = JSON.parse(localStorage.getItem('warriorSavedJobs')) || [];
128
+ const isSaved = saved.some(j => j.url === job.url);
129
+
130
+ const card = document.createElement('job-card');
131
+ card.setAttribute('title', job.title);
132
+ card.setAttribute('company', job.company_name);
133
+ card.setAttribute('salary', job.salary || 'Competitive');
134
+ card.setAttribute('type', job.job_type);
135
+ card.setAttribute('url', job.url);
136
+ card.setAttribute('category', job.category);
137
+ card.setAttribute('saved', isSaved); // Pass state
138
+
139
+ grid.appendChild(card);
140
+ });
141
+ }
142
+ } catch (error) {
143
+ console.error('Error:', error);
144
+ grid.innerHTML = `<div class="col-span-full text-center p-6 border border-red-900/50 bg-red-900/10 rounded-lg"><p class="text-red-400">Connection lost.</p></div>`;
145
+ }
146
+ }
147
+
148
+ // Utility: Debounce search input
149
+ function debounce(func, wait) {
150
+ let timeout;
151
+ return function executedFunction(...args) {
152
+ const later = () => {
153
+ clearTimeout(timeout);
154
+ func(...args);
155
+ };
156
+ clearTimeout(timeout);
157
+ timeout = setTimeout(later, wait);
158
+ };
159
+ }
160
+ async function loadJobs() {
161
+ const grid = document.getElementById('job-grid');
162
+
163
+ try {
164
+ // Using Remotive API for remote jobs (Public, No Key needed usually)
165
+ const response = await fetch('https://remotive.com/api/remote-jobs?limit=9');
166
+ const data = await response.json();
167
+
168
+ grid.innerHTML = ''; // Clear loading state
169
+
170
+ if(data.jobs && data.jobs.length > 0) {
171
+ data.jobs.forEach(job => {
172
+ // Create a job-card element
173
+ const card = document.createElement('job-card');
174
+
175
+ // Set attributes (Passing data to component)
176
+ card.setAttribute('title', job.title);
177
+ card.setAttribute('company', job.company_name);
178
+ card.setAttribute('salary', job.salary || 'Competitive');
179
+ card.setAttribute('type', job.job_type);
180
+ card.setAttribute('url', job.url);
181
+ card.setAttribute('category', job.category);
182
+
183
+ grid.appendChild(card);
184
+ });
185
+ } else {
186
+ grid.innerHTML = '<p class="col-span-full text-center text-slate-500">No targets found at this moment.</p>';
187
+ }
188
+ } catch (error) {
189
+ console.error('Error fetching jobs:', error);
190
+ grid.innerHTML = `
191
+ <div class="col-span-full text-center p-6 border border-red-900/50 bg-red-900/10 rounded-lg">
192
+ <p class="text-red-400">Connection lost to the network.</p>
193
+ <button onclick="location.reload()" class="mt-2 text-sm underline text-slate-400">Retry</button>
194
+ </div>
195
+ `;
196
+ }
197
+ }
style.css CHANGED
@@ -1,28 +1,33 @@
1
- body {
2
- padding: 2rem;
3
- font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
4
  }
5
-
6
- h1 {
7
- font-size: 16px;
8
- margin-top: 0;
9
  }
10
-
11
- p {
12
- color: rgb(107, 114, 128);
13
- font-size: 15px;
14
- margin-bottom: 10px;
15
- margin-top: 5px;
16
  }
17
 
18
- .card {
19
- max-width: 620px;
20
- margin: 0 auto;
21
- padding: 16px;
22
- border: 1px solid lightgray;
23
- border-radius: 16px;
24
  }
25
 
26
- .card p:last-child {
27
- margin-bottom: 0;
 
 
 
 
28
  }
 
 
 
 
 
 
 
1
+ /* Custom Scrollbar */
2
+ ::-webkit-scrollbar {
3
+ width: 10px;
4
  }
5
+ ::-webkit-scrollbar-track {
6
+ background: #0f172a;
 
 
7
  }
8
+ ::-webkit-scrollbar-thumb {
9
+ background: #334155;
10
+ border-radius: 5px;
11
+ }
12
+ ::-webkit-scrollbar-thumb:hover {
13
+ background: #475569;
14
  }
15
 
16
+ /* Base transitions */
17
+ a, button, .transition-all {
18
+ transition: all 0.3s ease;
 
 
 
19
  }
20
 
21
+ /* Glassmorphism utility */
22
+ .glass {
23
+ background: rgba(15, 23, 42, 0.7);
24
+ backdrop-filter: blur(10px);
25
+ -webkit-backdrop-filter: blur(10px);
26
+ border: 1px solid rgba(255, 255, 255, 0.05);
27
  }
28
+
29
+ /* Text selection handled by Tailwind, enforcing fallback */
30
+ ::selection {
31
+ background: #4f46e5;
32
+ color: white;
33
+ }