diff --git a/Prompt Engineering b/Prompt Engineering
deleted file mode 100644
index 8b13789..0000000
--- a/Prompt Engineering
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/Round 1 - Vague prompt/index.html/index.html b/Round 1 - Vague prompt/index.html/index.html
new file mode 100644
index 0000000..54368d8
--- /dev/null
+++ b/Round 1 - Vague prompt/index.html/index.html
@@ -0,0 +1,91 @@
+
+
+
+
+ Workspace
+ Settings
+ Manage your profile, preferences, and notifications from one place.
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Round 2 - Detailed prompt/index.html b/Round 2 - Detailed prompt/index.html
new file mode 100644
index 0000000..4a8894d
--- /dev/null
+++ b/Round 2 - Detailed prompt/index.html
@@ -0,0 +1,36 @@
+
+
+
+
+
+ Settings
+ Update your profile details.
+
+
+
+
+
+
+
+
diff --git a/Round 2 - Detailed prompt/settings.css b/Round 2 - Detailed prompt/settings.css
new file mode 100644
index 0000000..70ba4a9
--- /dev/null
+++ b/Round 2 - Detailed prompt/settings.css
@@ -0,0 +1,94 @@
+:root {
+ font-family: Arial, sans-serif;
+ color: #1f2937;
+ background: #f3f4f6;
+}
+
+body {
+ margin: 0;
+}
+
+.settings-page {
+ display: grid;
+ min-height: 100vh;
+ place-items: center;
+ padding: 1.5rem;
+}
+
+.settings-card {
+ width: min(100%, 28rem);
+ padding: 2rem;
+ border-radius: 0.75rem;
+ background: #fff;
+ box-shadow: 0 8px 24px rgb(31 41 55 / 12%);
+}
+
+h1 {
+ margin: 0;
+}
+
+.settings-description {
+ margin: 0.5rem 0 1.5rem;
+ color: #4b5563;
+}
+
+.form-field {
+ margin-bottom: 1.25rem;
+}
+
+label {
+ display: block;
+ margin-bottom: 0.5rem;
+ font-weight: 600;
+}
+
+input {
+ box-sizing: border-box;
+ width: 100%;
+ padding: 0.7rem 0.75rem;
+ border: 1px solid #9ca3af;
+ border-radius: 0.375rem;
+ font: inherit;
+}
+
+input:focus {
+ outline: 3px solid #bfdbfe;
+ border-color: #2563eb;
+}
+
+input[aria-invalid="true"] {
+ border-color: #b91c1c;
+}
+
+.field-error {
+ min-height: 1.25rem;
+ margin: 0.35rem 0 0;
+ color: #b91c1c;
+ font-size: 0.875rem;
+}
+
+button {
+ padding: 0.7rem 1.1rem;
+ border: 0;
+ border-radius: 0.375rem;
+ background: #2563eb;
+ color: #fff;
+ cursor: pointer;
+ font: inherit;
+ font-weight: 600;
+}
+
+button:hover {
+ background: #1d4ed8;
+}
+
+button:focus-visible {
+ outline: 3px solid #93c5fd;
+ outline-offset: 2px;
+}
+
+.success-message {
+ min-height: 1.25rem;
+ margin: 1rem 0 0;
+ color: #047857;
+}
diff --git a/Round 2 - Detailed prompt/settings.js b/Round 2 - Detailed prompt/settings.js
new file mode 100644
index 0000000..c0fbbb8
--- /dev/null
+++ b/Round 2 - Detailed prompt/settings.js
@@ -0,0 +1,26 @@
+import { getSettingsSubmitResult } from "./validation.mjs";
+
+const form = document.querySelector("#settings-form");
+const nameInput = document.querySelector("#name");
+const emailInput = document.querySelector("#email");
+const nameError = document.querySelector("#name-error");
+const emailError = document.querySelector("#email-error");
+const successMessage = document.querySelector("#form-success");
+
+function showError(input, errorElement, message) {
+ input.setAttribute("aria-invalid", String(Boolean(message)));
+ errorElement.textContent = message || "";
+}
+
+form.addEventListener("submit", (event) => {
+ event.preventDefault();
+ const result = getSettingsSubmitResult({ name: nameInput.value, email: emailInput.value });
+
+ showError(nameInput, nameError, result.errors.name);
+ showError(emailInput, emailError, result.errors.email);
+ successMessage.textContent = result.submitted ? "Settings saved successfully." : "";
+
+ if (!result.submitted) {
+ (result.errors.name ? nameInput : emailInput).focus();
+ }
+});
diff --git a/Round 2 - Detailed prompt/tests/validation.test.mjs b/Round 2 - Detailed prompt/tests/validation.test.mjs
new file mode 100644
index 0000000..8c64d47
--- /dev/null
+++ b/Round 2 - Detailed prompt/tests/validation.test.mjs
@@ -0,0 +1,23 @@
+import test from "node:test";
+import assert from "node:assert/strict";
+import { getSettingsSubmitResult, validateSettings } from "../validation.mjs";
+
+test("requires a name", () => {
+ assert.deepEqual(validateSettings({ name: " ", email: "alex@example.com" }), { name: "Name is required." });
+});
+
+test("requires an email", () => {
+ assert.deepEqual(validateSettings({ name: "Alex", email: "" }), { email: "Email is required." });
+});
+
+test("rejects an invalid email", () => {
+ assert.deepEqual(validateSettings({ name: "Alex", email: "not-an-email" }), { email: "Enter a valid email address." });
+});
+
+test("does not submit when validation fails", () => {
+ assert.equal(getSettingsSubmitResult({ name: "", email: "bad" }).submitted, false);
+});
+
+test("submits valid settings without errors", () => {
+ assert.deepEqual(getSettingsSubmitResult({ name: "Alex Johnson", email: "alex@example.com" }), { errors: {}, submitted: true });
+});
diff --git a/Round 2 - Detailed prompt/validation.mjs b/Round 2 - Detailed prompt/validation.mjs
new file mode 100644
index 0000000..b49dba6
--- /dev/null
+++ b/Round 2 - Detailed prompt/validation.mjs
@@ -0,0 +1,26 @@
+const EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
+
+export function validateSettings({ name, email }) {
+ const errors = {};
+
+ if (!name.trim()) {
+ errors.name = "Name is required.";
+ }
+
+ if (!email.trim()) {
+ errors.email = "Email is required.";
+ } else if (!EMAIL_PATTERN.test(email.trim())) {
+ errors.email = "Enter a valid email address.";
+ }
+
+ return errors;
+}
+
+export function getSettingsSubmitResult(values) {
+ const errors = validateSettings(values);
+
+ return {
+ errors,
+ submitted: Object.keys(errors).length === 0,
+ };
+}