Faces & focus
+Add a bold subject area for a face or product cut-out.
+diff --git a/app.js b/app.js new file mode 100644 index 0000000..3e4096d --- /dev/null +++ b/app.js @@ -0,0 +1,197 @@ +const stylePresets = [ + { + name: "Vibrant", + gradient: ["#4c5cff", "#ff5b7c"], + textShadow: "0 10px 20px rgba(15, 23, 42, 0.4)", + }, + { + name: "Neon", + gradient: ["#00f5d4", "#9b5cff"], + textShadow: "0 8px 18px rgba(0, 0, 0, 0.35)", + }, + { + name: "Cinematic", + gradient: ["#111827", "#ef4444"], + textShadow: "0 6px 20px rgba(0, 0, 0, 0.55)", + }, +]; + +const palettes = [ + { name: "Cosmic", colors: ["#4c5cff", "#ff5b7c", "#ffffff"] }, + { name: "Sunset", colors: ["#ff8c42", "#ff3c6f", "#ffd66b"] }, + { name: "Ocean", colors: ["#0077ff", "#00c2ff", "#e0f7ff"] }, +]; + +const alignments = ["Left", "Center", "Right"]; + +const state = { + style: stylePresets[0], + palette: palettes[0], + alignment: alignments[0], +}; + +const previewCanvas = document.getElementById("previewCanvas"); +const previewText = document.getElementById("previewText"); +const previewTitle = document.getElementById("previewTitle"); +const previewSubtitle = document.getElementById("previewSubtitle"); +const previewKicker = document.getElementById("previewKicker"); +const styleBadge = document.getElementById("styleBadge"); +const swatches = document.getElementById("swatches"); + +const styleChips = document.getElementById("styleChips"); +const alignChips = document.getElementById("alignChips"); +const paletteOptions = document.getElementById("paletteOptions"); + +const videoTitle = document.getElementById("videoTitle"); +const videoHook = document.getElementById("videoHook"); +const videoSubtitle = document.getElementById("videoSubtitle"); + +const generateBtn = document.getElementById("generateBtn"); +const shuffleBtn = document.getElementById("shuffleBtn"); +const resetBtn = document.getElementById("resetBtn"); + +const createChip = (label, group, onSelect) => { + const chip = document.createElement("button"); + chip.type = "button"; + chip.className = "chip"; + chip.textContent = label; + chip.addEventListener("click", () => onSelect(label, chip)); + group.appendChild(chip); + return chip; +}; + +const updatePreview = () => { + const [first, second] = state.style.gradient; + previewCanvas.style.background = `linear-gradient(135deg, ${first}, ${second})`; + previewText.style.textAlign = state.alignment.toLowerCase(); + previewText.style.textShadow = state.style.textShadow; + styleBadge.textContent = state.style.name; + + swatches.innerHTML = ""; + state.palette.colors.forEach((color) => { + const swatch = document.createElement("span"); + swatch.className = "swatch"; + swatch.style.background = color; + swatches.appendChild(swatch); + }); +}; + +const setActiveChip = (group, activeChip) => { + group.querySelectorAll(".chip").forEach((chip) => chip.classList.remove("active")); + activeChip.classList.add("active"); +}; + +stylePresets.forEach((preset, index) => { + const chip = createChip(preset.name, styleChips, (label, clicked) => { + state.style = stylePresets.find((item) => item.name === label); + setActiveChip(styleChips, clicked); + updatePreview(); + }); + if (index === 0) { + chip.classList.add("active"); + } +}); + +alignments.forEach((alignment, index) => { + const chip = createChip(alignment, alignChips, (label, clicked) => { + state.alignment = label; + setActiveChip(alignChips, clicked); + updatePreview(); + }); + if (index === 0) { + chip.classList.add("active"); + } +}); + +palettes.forEach((palette, index) => { + const card = document.createElement("button"); + card.type = "button"; + card.className = "palette-option"; + + const samples = document.createElement("div"); + samples.className = "palette-samples"; + palette.colors.forEach((color) => { + const dot = document.createElement("span"); + dot.style.background = color; + samples.appendChild(dot); + }); + + const label = document.createElement("span"); + label.textContent = palette.name; + + card.appendChild(samples); + card.appendChild(label); + card.addEventListener("click", () => { + state.palette = palette; + paletteOptions + .querySelectorAll(".palette-option") + .forEach((option) => option.classList.remove("active")); + card.classList.add("active"); + updatePreview(); + }); + + if (index === 0) { + card.classList.add("active"); + } + + paletteOptions.appendChild(card); +}); + +const syncInputs = () => { + previewTitle.textContent = videoTitle.value.trim() || "Your video title"; + previewKicker.textContent = videoHook.value.trim() || "Hook"; + previewSubtitle.textContent = videoSubtitle.value.trim() || "Supporting line"; +}; + +const randomItem = (items) => items[Math.floor(Math.random() * items.length)]; + +const shuffle = () => { + state.style = randomItem(stylePresets); + state.palette = randomItem(palettes); + state.alignment = randomItem(alignments); + + styleChips + .querySelectorAll(".chip") + .forEach((chip) => chip.classList.toggle("active", chip.textContent === state.style.name)); + alignChips + .querySelectorAll(".chip") + .forEach((chip) => chip.classList.toggle("active", chip.textContent === state.alignment)); + paletteOptions + .querySelectorAll(".palette-option") + .forEach((option) => option.classList.toggle("active", option.textContent === state.palette.name)); + + updatePreview(); +}; + +const resetForm = () => { + videoTitle.value = "Create Thumbnails That Pop"; + videoHook.value = "AI Hacks"; + videoSubtitle.value = "Boost clicks with smart layouts"; + state.style = stylePresets[0]; + state.palette = palettes[0]; + state.alignment = alignments[0]; + shuffle(); + syncInputs(); +}; + +videoTitle.addEventListener("input", syncInputs); +videoHook.addEventListener("input", syncInputs); +videoSubtitle.addEventListener("input", syncInputs); + +const form = document.getElementById("thumbnailForm"); +form.addEventListener("submit", (event) => { + event.preventDefault(); + syncInputs(); + updatePreview(); +}); + +generateBtn.addEventListener("click", () => { + syncInputs(); + updatePreview(); +}); + +shuffleBtn.addEventListener("click", shuffle); +resetBtn.addEventListener("click", resetForm); + +syncInputs(); +updatePreview(); diff --git a/index.html b/index.html new file mode 100644 index 0000000..5a72e83 --- /dev/null +++ b/index.html @@ -0,0 +1,128 @@ + + +
+ + +AI YouTube Studio
++ Craft attention-grabbing thumbnails in minutes with smart presets, bold typography, and + creative layouts. +
+AI Hacks
+Boost clicks with smart layouts
+Tell the AI what your video is about, choose a style, and customize the layout.
+ +Add a bold subject area for a face or product cut-out.
+Pick a background palette with strong contrast to make text pop.
+Keep the hook under 3 words to create curiosity.
+Use arrows or rings around important focus points.
+