Skip to content

Commit 119ff7d

Browse files
Made few changes for mobile responsiveness, enhancing user experience
1 parent 28f6b4f commit 119ff7d

4 files changed

Lines changed: 184 additions & 52 deletions

File tree

public/css/style.css

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -932,3 +932,123 @@ button:disabled .lock-overlay {
932932

933933
.high-contrast .unlock-row .unlock-status-done { color: #000 !important; }
934934
.high-contrast .unlock-row .unlock-bar-fill { background: #000 !important; }
935+
936+
/* ============================================================
937+
📱 MOBILE FIXES — font & audio bars + general layout
938+
============================================================ */
939+
@media (max-width: 600px) {
940+
/* Font size control bar — full-width strip above audio bar */
941+
#fontControlBar {
942+
top: auto !important;
943+
bottom: 56px !important;
944+
right: 0 !important;
945+
left: 0 !important;
946+
width: 100% !important;
947+
border-radius: 0 !important;
948+
border-left: none !important;
949+
border-right: none !important;
950+
border-top: 1px solid var(--neon-cyan) !important;
951+
border-bottom: none !important;
952+
justify-content: center !important;
953+
padding: 5px 12px !important;
954+
gap: 12px !important;
955+
box-sizing: border-box !important;
956+
}
957+
958+
#fontControlBar button {
959+
padding: 5px 14px !important;
960+
font-size: 13px !important;
961+
min-width: 38px !important;
962+
min-height: 34px !important;
963+
clip-path: none !important;
964+
}
965+
966+
/* Audio control bar — full-width strip at very bottom */
967+
#audioControlBar {
968+
bottom: 0 !important;
969+
right: 0 !important;
970+
left: 0 !important;
971+
width: 100% !important;
972+
border-radius: 0 !important;
973+
border-left: none !important;
974+
border-right: none !important;
975+
justify-content: center !important;
976+
padding: 5px 12px !important;
977+
gap: 10px !important;
978+
box-sizing: border-box !important;
979+
}
980+
981+
#audioControlBar #volumeSlider {
982+
width: 110px !important;
983+
flex-shrink: 1 !important;
984+
}
985+
986+
#audioControlBar button {
987+
padding: 5px 10px !important;
988+
font-size: 14px !important;
989+
min-height: 34px !important;
990+
clip-path: none !important;
991+
}
992+
993+
/* Extra bottom padding so content isn't hidden behind the two bars */
994+
.container {
995+
padding-bottom: 130px !important;
996+
}
997+
998+
/* Chat box — shorter on small screens */
999+
.chat-box {
1000+
height: 260px;
1001+
}
1002+
1003+
/* Input group — stack on mobile */
1004+
.input-group {
1005+
flex-direction: column;
1006+
}
1007+
1008+
.input-group input {
1009+
border-right: 1px solid #333;
1010+
border-radius: 5px;
1011+
margin-bottom: 8px;
1012+
}
1013+
1014+
.input-group button {
1015+
border-radius: 5px;
1016+
width: 100%;
1017+
}
1018+
1019+
/* Log box — shorter */
1020+
.log-box {
1021+
height: 140px;
1022+
font-size: 11px;
1023+
}
1024+
1025+
/* Badge list — wrap on small screens */
1026+
.badge-list {
1027+
flex-wrap: wrap;
1028+
gap: 10px;
1029+
}
1030+
1031+
/* Unlock row bar — wider on mobile */
1032+
.unlock-row .unlock-bar {
1033+
width: 60px;
1034+
}
1035+
1036+
/* Tour card — full width */
1037+
#tour-card {
1038+
width: calc(100vw - 30px) !important;
1039+
left: 15px !important;
1040+
}
1041+
1042+
/* Auth box */
1043+
.auth-box {
1044+
width: 95%;
1045+
padding: 25px 15px;
1046+
}
1047+
1048+
/* Tables — allow horizontal scroll */
1049+
table {
1050+
display: block;
1051+
overflow-x: auto;
1052+
-webkit-overflow-scrolling: touch;
1053+
}
1054+
}

public/js/adaptive.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,16 @@ export async function getAdaptiveContent(category) {
5151
const xp = userData?.xp || 0;
5252

5353
let difficulty = "Novice";
54-
let timerSeconds = 10;
54+
let timerSeconds = 30;
5555
let extraSteps = false;
5656

5757
if (xp >= 500) {
5858
difficulty = "Elite Guardian";
59-
timerSeconds = 5;
59+
timerSeconds = 25;
6060
extraSteps = true;
6161
} else if (xp >= 100) {
6262
difficulty = "Specialist";
63-
timerSeconds = 7;
63+
timerSeconds = 27;
6464
extraSteps = true;
6565
}
6666

public/js/smishing.js

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ function renderQRCode(qr) {
6767
<rect x="58" y="68" width="6" height="6" fill="#00f3ff"/>
6868
<rect x="68" y="68" width="6" height="6" fill="#00f3ff"/>
6969
</svg>
70-
<div class="qr-tap-hint">📷 Tap to Scan</div>
70+
<div class="qr-tap-hint">🔍 Click to reveal hidden URL</div>
7171
</div>
7272
<div class="qr-url-reveal" id="qrUrlReveal" style="display:none;">
7373
<span style="color:#f87171;font-size:11px;">🔗 Redirects to:</span><br>
@@ -98,10 +98,6 @@ function loadMessage() {
9898
<div>${msg.text} ${linkHtml}</div>
9999
${qrHtml}
100100
</div>
101-
<div style="margin-top:auto;">
102-
<button class="primary-btn" onclick="handleDecision(true)" style="width:100%; margin-bottom:10px; background:#f87171; color:white;" aria-label="Flag as Scam">🚨 Flag as Scam</button>
103-
<button class="secondary-btn" onclick="handleDecision(false)" style="width:100%;" aria-label="Mark as Safe">Mark Safe</button>
104-
</div>
105101
`;
106102

107103
const bubble = document.getElementById('smsBubble');
@@ -110,6 +106,10 @@ function loadMessage() {
110106
e.dataTransfer.effectAllowed = 'move';
111107
});
112108
bubble.addEventListener('dragend', () => bubble.classList.remove('dragging'));
109+
110+
// Show the bins panel
111+
document.getElementById('binsPanel').style.display = 'flex';
112+
feedback.innerHTML = '';
113113
}
114114

115115
window.handleDrop = (flaggedAsScam) => handleDecision(flaggedAsScam);
@@ -118,18 +118,18 @@ window.handleDecision = (flaggedAsScam) => {
118118
const msg = messages[currentIndex];
119119
if (flaggedAsScam === msg.isPhishing) {
120120
const extra = msg.qrCode?.warning ? `<br><small style="color:#fbbf24;">💡 ${msg.qrCode.warning}</small>` : '';
121-
feedback.innerHTML = `<span style="color:lightgreen;" role="alert">✅ [CORRECT] Good call!</span>${extra}`;
121+
feedback.innerHTML = `<span style="color:lightgreen;" role="alert">✅ Correct! Good call!</span>${extra}`;
122122
updateXP(10, 'smishing');
123123
totalXP += 10;
124124
correctCount++;
125125
} else {
126126
const hint = msg.qrCode ? ' (QR codes can hide malicious URLs — always verify before scanning!)' : '';
127-
feedback.innerHTML = `<span style="color:red;" role="alert">❌ [WRONG] That was a ${msg.isPhishing ? 'scam' : 'safe message'}.${hint}</span>`;
127+
feedback.innerHTML = `<span style="color:#f87171;" role="alert">❌ Wrong! That was a ${msg.isPhishing ? 'scam' : 'safe message'}.${hint}</span>`;
128128
}
129129

130130
currentIndex++;
131131
setTimeout(() => {
132-
feedback.innerHTML = "";
132+
feedback.innerHTML = '';
133133
loadMessage();
134134
}, 2500);
135135
};
@@ -141,27 +141,32 @@ function showCompletion() {
141141
if (pct >= 80) grade = "🛡️ Smishing Defender";
142142
else if (pct >= 50) grade = "🔍 Aware User";
143143

144-
phoneScreen.innerHTML = "";
145-
feedback.innerHTML = `
144+
document.getElementById('gameArea').style.display = 'none';
145+
document.getElementById('gameSubtitle').style.display = 'none';
146+
document.getElementById('pageTitle').textContent = '📱 Smishing Simulation Complete';
147+
const completionArea = document.getElementById('completionArea');
148+
completionArea.style.display = 'block';
149+
completionArea.innerHTML = `
146150
<div style="text-align:left;">
147-
<h2>📱 Simulation Complete!</h2>
148-
<p>Score: <strong style="color:var(--neon-cyan);">${correctCount} / ${total}</strong> &nbsp;|&nbsp; XP Earned: <strong style="color:var(--neon-green);">${totalXP}</strong></p>
149-
<p style="font-size:18px;">${grade}</p>
150-
151-
<div class="deep-dive" style="margin-top:20px; padding:15px; background:rgba(0,0,0,0.3); border-radius:10px;">
152-
<h3>📖 Cyber Deep Dive: Smishing & Quishing</h3>
153-
<p>SMS-based phishing (smishing) bypasses email filters entirely, reaching victims directly on their most personal device.</p>
154-
<ul>
155-
<li><strong>FluBot (2021):</strong> An Android smishing campaign that spread to millions of devices across Europe by sending fake parcel delivery SMS messages containing malware download links.</li>
156-
<li><strong>USPS/FedEx Scam Wave:</strong> Ongoing campaigns impersonating delivery services with fake "customs fee" or "address update" links — one of the most reported smishing types globally.</li>
157-
<li><strong>Quishing:</strong> QR code phishing bypasses text-based link scanners. Attackers place fake QR stickers over legitimate ones in restaurants, parking meters, and public posters.</li>
158-
</ul>
159-
<p><em>Stat:</em> Smishing attacks increased by 328% in 2020 alone (Source: Proofpoint).</p>
160-
</div>
151+
<p style="margin:0 0 4px;">Score: <strong style="color:var(--neon-cyan);">${correctCount} / ${total}</strong> &nbsp;|&nbsp; XP Earned: <strong style="color:var(--neon-green);">${totalXP}</strong></p>
152+
<p style="font-size:18px;margin:0 0 12px;">${grade}</p>
153+
154+
<details style="margin-bottom:12px;">
155+
<summary style="cursor:pointer;color:var(--neon-cyan);font-size:13px;margin-bottom:6px;">📖 Cyber Deep Dive: Smishing &amp; Quishing</summary>
156+
<div style="padding:12px;background:rgba(0,0,0,0.3);border-radius:8px;font-size:12px;">
157+
<p style="margin:0 0 6px;">SMS-based phishing bypasses email filters entirely, reaching victims on their most personal device.</p>
158+
<ul style="margin:0 0 6px;padding-left:16px;">
159+
<li><strong>FluBot (2021):</strong> Spread to millions across Europe via fake parcel delivery SMS containing malware links.</li>
160+
<li><strong>USPS/FedEx Scam Wave:</strong> Fake "customs fee" or "address update" links — one of the most reported smishing types globally.</li>
161+
<li><strong>Quishing:</strong> QR code phishing bypasses text-based scanners. Attackers place fake QR stickers over legitimate ones in public spaces.</li>
162+
</ul>
163+
<p style="margin:0;"><em>Stat:</em> Smishing attacks increased by 328% in 2020 (Source: Proofpoint).</p>
164+
</div>
165+
</details>
161166
162167
<div id="safetyArea"></div>
163168
164-
<div style="margin-top:20px; display:flex; gap:15px; flex-wrap:wrap;">
169+
<div style="margin-top:12px;display:flex;gap:12px;flex-wrap:wrap;">
165170
<button class="primary-btn" onclick="location.reload()">🔁 Play Again</button>
166171
<button class="secondary-btn" onclick="goHome()">🏠 Back to Home</button>
167172
</div>

public/smishing.html

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
<style>
99
.phone-frame {
1010
width: 300px;
11-
height: 500px;
1211
border: 12px solid #30363d;
1312
border-radius: 30px;
1413
margin: 0 auto;
@@ -18,9 +17,9 @@
1817
}
1918
.phone-screen {
2019
padding: 20px;
21-
height: 100%;
2220
display: flex;
2321
flex-direction: column;
22+
gap: 8px;
2423
}
2524
.sms-bubble {
2625
background: #1f2937;
@@ -108,33 +107,41 @@
108107
<body>
109108
<div class="container">
110109
<button class="back-btn" onclick="goHome()">← Back</button>
111-
<h2>📱 Smishing Simulator</h2>
112-
<p>Drag the SMS into the correct bin, or use the buttons below.</p>
110+
<h2 id="pageTitle" style="margin:0 0 4px;">📱 Smishing Simulator</h2>
111+
<p id="gameSubtitle" style="margin:0 0 12px;font-size:13px;">Drag the SMS into the correct bin, or use the buttons on the right.</p>
113112

114-
<div class="phone-frame">
115-
<div class="phone-screen" id="phoneScreen">
116-
<!-- Messages will load here -->
117-
</div>
118-
</div>
113+
<div id="gameArea" style="display:flex;gap:30px;align-items:flex-start;justify-content:center;flex-wrap:wrap;">
119114

120-
<div class="drop-bins">
121-
<div class="drop-bin scam-bin" id="scamBin"
122-
role="button" aria-label="Drop here to flag as scam"
123-
ondragover="event.preventDefault(); this.classList.add('drag-over');"
124-
ondragleave="this.classList.remove('drag-over');"
125-
ondrop="handleDrop(true); this.classList.remove('drag-over');">
126-
🚨 Scam
115+
<!-- Left: Phone -->
116+
<div class="phone-frame">
117+
<div class="phone-screen" id="phoneScreen">
118+
<!-- Messages will load here -->
119+
</div>
127120
</div>
128-
<div class="drop-bin safe-bin" id="safeBin"
129-
role="button" aria-label="Drop here to mark as safe"
130-
ondragover="event.preventDefault(); this.classList.add('drag-over');"
131-
ondragleave="this.classList.remove('drag-over');"
132-
ondrop="handleDrop(false); this.classList.remove('drag-over');">
133-
✅ Safe
121+
122+
<!-- Right: Bins + Feedback -->
123+
<div id="binsPanel" style="display:flex;flex-direction:column;gap:16px;justify-content:center;min-width:200px;flex:1;max-width:320px;">
124+
<div class="drop-bin scam-bin" id="scamBin"
125+
role="button" aria-label="Drop here to flag as scam"
126+
ondragover="event.preventDefault(); this.classList.add('drag-over');"
127+
ondragleave="this.classList.remove('drag-over');"
128+
ondrop="handleDrop(true); this.classList.remove('drag-over');">
129+
🚨 Scam
130+
</div>
131+
<div class="drop-bin safe-bin" id="safeBin"
132+
role="button" aria-label="Drop here to mark as safe"
133+
ondragover="event.preventDefault(); this.classList.add('drag-over');"
134+
ondragleave="this.classList.remove('drag-over');"
135+
ondrop="handleDrop(false); this.classList.remove('drag-over');">
136+
✅ Safe
137+
</div>
138+
<div id="feedback" style="min-height:44px;" aria-live="polite"></div>
134139
</div>
140+
135141
</div>
136-
137-
<div id="feedback" style="margin-top:20px;" aria-live="polite"></div>
142+
143+
<!-- Completion screen — outside the two-column layout -->
144+
<div id="completionArea" style="display:none;"></div>
138145
</div>
139146

140147
<script type="module">

0 commit comments

Comments
 (0)