Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions Frontend-Projects/Terminal-Clock-SE-Jihad/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# 💻 Advanced Terminal Clock

> A fully responsive, hacker-style terminal digital clock built with pure HTML, CSS, and Vanilla JavaScript.

### 🔗 [Live Preview Here](https://sejihad.github.io/terminal-clock)

## ✨ Features

- **Retro Terminal Vibe:** Authentic Linux/MacOS terminal workspace interface.
- **Boot Sequence Animation:** Realistic JS typing effect before the clock initializes.
- **CRT & Neon Glow:** Vintage scanlines and hacker-green text glow effects.
- **100% Responsive:** Fluid typography scaling (`clamp()`) for perfect mobile view without media queries.
- **Clean Code:** Modular, fail-safe, and well-structured Vanilla JS.

## 🛠️ Tech Stack

- **HTML5** (Semantic structure)
- **CSS3** (Custom Properties, Flexbox/Grid, Animations)
- **JavaScript** (ES6+, DOM Manipulation, Time Logic)

## 🚀 How to Run Locally

1. Clone the repository:
```bash
git clone https://github.com/sejihad/terminal-clock.git
44 changes: 44 additions & 0 deletions Frontend-Projects/Terminal-Clock-SE-Jihad/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Advanced Terminal Clock</title>
<link rel="stylesheet" href="style.css">
</head>

<body>
<div class="scanlines"></div>

<main class="term-wrapper">
<header class="term-header">
<div class="window-controls">
<span></span>
<span></span>
<span></span>
</div>
<div class="window-title">bash - root@sejihad:~</div>
</header>

<section class="term-content">
<div class="input-line">
<span class="path">root@sejihad:~$</span>
<span id="cmd-text" class="cmd"></span><span id="cmd-cursor" class="block-cursor"></span>
</div>

<div id="clock-container" class="output-block hidden">
<div id="sys-date" class="date-text"></div>
<div id="sys-time" class="time-text">00:00:00</div>
</div>

<div id="new-prompt" class="input-line mt hidden">
<span class="path">root@sejihad:~$</span>
<span class="block-cursor"></span>
</div>
</section>
</main>
<script src="script.js"></script>
</body>

</html>
76 changes: 76 additions & 0 deletions Frontend-Projects/Terminal-Clock-SE-Jihad/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Add leading zero to numbers
const padZero = (num) => num.toString().padStart(2, "0");

// Get current date and time
const getDateTimeData = () => {
const now = new Date();

let rawHours = now.getHours();
const isPM = rawHours >= 12;
const ampmStr = isPM ? "PM" : "AM";

const hours = padZero(rawHours % 12 || 12);
const minutes = padZero(now.getMinutes());
const seconds = padZero(now.getSeconds());

const dateOptions = {
weekday: "short",
year: "numeric",
month: "long",
day: "2-digit",
};
const formattedDate = now.toLocaleDateString("en-US", dateOptions);

return {
timeString: `${hours}:${minutes}:${seconds}`,
ampm: ampmStr,
dateString: formattedDate,
};
};

// Update the DOM elements
const renderClock = () => {
const timeEl = document.getElementById("sys-time");
const dateEl = document.getElementById("sys-date");

if (!timeEl || !dateEl) return;

const data = getDateTimeData();
timeEl.innerHTML = `${data.timeString} <span class="ampm">${data.ampm}</span>`;
dateEl.textContent = `[*] Current System Date: ${data.dateString}`;
};

// Pro-level Typing Animation
const runBootSequence = () => {
const cmdText = "./start_clock.sh";
const cmdElement = document.getElementById("cmd-text");
const cursor = document.getElementById("cmd-cursor");
const clockContainer = document.getElementById("clock-container");
const newPrompt = document.getElementById("new-prompt");

let i = 0;

// Typing effect logic
const typingInterval = setInterval(() => {
if (i < cmdText.length) {
cmdElement.textContent += cmdText.charAt(i);
i++;
} else {
clearInterval(typingInterval);

// Wait a moment, then "execute" the command
setTimeout(() => {
cursor.style.display = "none"; // Hide upper cursor
clockContainer.classList.remove("hidden");
newPrompt.classList.remove("hidden");

// Start the clock engine
renderClock();
setInterval(renderClock, 1000);
}, 500);
}
}, 100); // Typing speed
};

// Start everything when DOM loads
document.addEventListener("DOMContentLoaded", runBootSequence);
195 changes: 195 additions & 0 deletions Frontend-Projects/Terminal-Clock-SE-Jihad/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
@import url("https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;700&display=swap");

:root {
--bg-main: #050505;
--bg-term: rgba(15, 15, 18, 0.95);
--term-border: #27272a;
--text-primary: #00ff41;
--text-secondary: #888;
--text-path: #3b82f6;
--font-mono: "Fira Code", monospace;
--glow: 0 0 10px rgba(0, 255, 65, 0.4), 0 0 20px rgba(0, 255, 65, 0.2);
}

* {
box-sizing: border-box;
margin: 0;
padding: 0;
}

body {
background-color: var(--bg-main);
display: grid;
place-items: center;
min-height: 100vh;
font-family: var(--font-mono);
overflow: hidden;
padding: 1rem;
}

/* CRT Scanline Effect */
.scanlines {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background:
linear-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.25) 50%),
linear-gradient(
90deg,
rgba(255, 0, 0, 0.06),
rgba(0, 255, 0, 0.02),
rgba(0, 0, 255, 0.06)
);
background-size:
100% 4px,
3px 100%;
pointer-events: none;
z-index: 50;
}

/* Responsive Wrapper */
.term-wrapper {
width: 100%;
max-width: 650px;
background-color: var(--bg-term);
border-radius: 10px;
border: 1px solid #333;
box-shadow:
0 20px 60px rgba(0, 255, 65, 0.05),
inset 0 0 20px rgba(0, 0, 0, 0.5);
backdrop-filter: blur(5px);
z-index: 10;
}

.term-header {
background-color: #121214;
padding: 0.8rem 1.2rem;
display: flex;
align-items: center;
border-bottom: 1px solid var(--term-border);
}

.window-controls {
display: flex;
gap: 6px;
flex-shrink: 0;
}

.window-controls span {
display: inline-block;
width: 13px;
height: 13px;
border-radius: 50%;
}
.window-controls span:nth-child(1) {
background: #ff5f56;
box-shadow: 0 0 5px #ff5f56;
}
.window-controls span:nth-child(2) {
background: #ffbd2e;
box-shadow: 0 0 5px #ffbd2e;
}
.window-controls span:nth-child(3) {
background: #27c93f;
box-shadow: 0 0 5px #27c93f;
}

.window-title {
color: var(--text-secondary);
/* Fluid typography for title */
font-size: clamp(0.7rem, 2vw, 0.85rem);
flex-grow: 1;
text-align: center;
/* Remove strict padding so it centers nicely on mobile */
padding-right: 45px;
}

/* Fluid Padding for different screens */
.term-content {
padding: clamp(1rem, 5vw, 2rem);
}

/* Fluid Typography for text elements */
.input-line {
font-size: clamp(0.85rem, 3vw, 1rem);
margin-bottom: 1.5rem;
word-wrap: break-word;
}

.path {
color: var(--text-path);
font-weight: 700;
margin-right: 0.5rem;
}
.cmd {
color: #fff;
text-shadow: 0 0 5px rgba(255, 255, 255, 0.5);
}

.output-block {
border-left: 2px solid rgba(0, 255, 65, 0.3);
padding-left: clamp(0.8rem, 3vw, 1.5rem);
margin-bottom: 1.5rem;
transition: opacity 0.5s ease-in;
}

.date-text {
color: var(--text-secondary);
font-size: clamp(0.75rem, 2.5vw, 1rem);
margin-bottom: 0.5rem;
}

.time-text {
color: var(--text-primary);
/* Magic part: Font size scales smoothly from 2.5rem (mobile) to 4rem (desktop) */
font-size: clamp(2.5rem, 8vw, 4rem);
font-weight: 700;
text-shadow: var(--glow);
letter-spacing: 2px;
line-height: 1.2;
}

.time-text span.ampm {
font-size: clamp(1rem, 3vw, 1.5rem);
color: var(--text-secondary);
text-shadow: none;
}

.block-cursor {
display: inline-block;
width: clamp(6px, 2vw, 10px);
height: 1.1em;
background-color: var(--text-primary);
vertical-align: middle;
animation: blinker 1s step-end infinite;
box-shadow: var(--glow);
}

.mt {
margin-top: 2rem;
}
.hidden {
display: none;
opacity: 0;
}

@keyframes blinker {
50% {
opacity: 0;
}
}

/* Extra check for very small screens (like iPhone SE) */
@media (max-width: 400px) {
.path {
display: block; /* Username path will sit above the command */
margin-bottom: 0.3rem;
}
.window-title {
padding-right: 0;
text-align: left;
padding-left: 15px;
}
}