Initial Release

This commit is contained in:
2026-05-24 19:52:45 -07:00
commit 8242fdbbb3
181 changed files with 10119 additions and 0 deletions
@@ -0,0 +1,160 @@
:root {
--transition-time: 200ms;
--animation-time: 200ms;
--color-background: #1d1e2e;
--color-text-default: #f0f0f0;
--color-text-hint: #d0d0d0;
--color-disabled: #212335;
--color-inactive: #2d2f47;
--color-active: #a1a8ff;
}
body {
margin: 0;
background-color: var(--color-background);
padding: 0;
}
p,
a {
display: inline-block;
margin: 0;
padding: 0;
color: var(--color-text-default);
font-weight: normal;
font-size: 1em;
font-family: 'Poppins', sans-serif;
}
a {
cursor: pointer;
margin: 0 8px;
border: 2px solid var(--color-inactive);
border-radius: 8px;
padding: 4px 8px;
min-width: 120px;
}
a:hover,
a:focus-visible {
border-color: var(--color-active);
}
.text-tip {
font-size: small;
}
.text-hidden {
color: var(--color-text-hint);
}
/* Layout */
div.layout-container {
box-sizing: border-box;
margin: auto;
padding: 32px 16px;
width: fit-content;
}
div.layout-header {
display: grid;
gap: 8px;
text-align: center;
}
div.picross-row {
display: flex;
gap: 4px;
}
div.layout-content {
display: grid;
justify-content: center;
gap: 4px;
/* visually centered */
margin-left: -32px;
padding: 32px 0;
}
p.picross-hint {
width: 24px;
height: 24px;
color: var(--color-text-hint);
line-height: 24px;
text-align: center;
}
button.picross-button {
transition: var(--animation-time) ease-in-out background-color;
border: none;
background-color: var(--color-inactive);
width: 24px;
height: 24px;
}
button.state-active {
background-color: var(--color-active) !important;
}
button.state-ignore {
background-color: var(--color-disabled) !important;
}
div.layout-footer {
text-align: center;
}
p.layout-timer {
padding: 16px 0;
}
/* Certificate */
div.layout-document {
position: relative;
width: 11in;
height: 8.5in;
overflow: hidden;
}
div.layout-document span {
position: absolute;
background-color: white;
color: red;
}
div.layout-document span#name {
top: 3in;
left: 3.75in;
width: 3.5in;
font-size: 2em;
text-align: center;
}
div.layout-document span#time {
top: 4in;
left: 6in;
}
div.layout-document span#date {
top: 3.67in;
left: 4.8in;
padding: 0 32px;
}
div.layout-document img#background {
width: 100%;
height: 100%;
}
@media print {
@page {
size: letter landscape;
margin: 0;
}
.no-print {
display: none !important;
}
}
@@ -0,0 +1,72 @@
const elemTimer = document.querySelector<HTMLParagraphElement>('p.layout-timer')!
const elemCheck = document.querySelector<HTMLButtonElement>('a#action-send')!
const soundSet = document.querySelector<HTMLAudioElement>('audio#audio-set')!
const soundDel = document.querySelector<HTMLAudioElement>('audio#audio-del')!
let secondsElapsed = 0
function timestamp() {
const f = (s: number) => s.toString().padStart(2, '0')
const h = Math.floor(secondsElapsed / 3600)
const m = Math.floor((secondsElapsed % 3600) / 60)
const s = Math.floor(secondsElapsed % 60)
return `Time Spent: ${f(h)}:${f(m)}:${f(s)}`
}
setInterval(() => {
secondsElapsed++
elemTimer.textContent = timestamp()
}, 1000)
document.querySelector<HTMLDivElement>('div.layout-content')!.addEventListener(
// Prevent annoying context menu popup whenever you miss a grid tile by 1 pixel
'contextmenu',
(e) => e.preventDefault(),
)
document.querySelectorAll('button.picross-button').forEach((e) => {
// Initialize Buttons
e.addEventListener('click', () => {
e.classList.remove('state-ignore')
e.classList.toggle('state-active') ? soundSet.play() : soundDel.play()
})
e.addEventListener('contextmenu', (ev) => {
ev.preventDefault()
e.classList.remove('state-active')
e.classList.toggle('state-ignore')
soundDel.play()
})
})
elemCheck.addEventListener('click', () => {
// Calculate Answer
let given = 0
const rows = document.querySelectorAll<HTMLDivElement>('div.picross-row')
rows.forEach((childRow, rowIndex) => {
let childIndex = 0
for (const child of childRow.children) {
if (child.nodeName === 'BUTTON') {
if (child.classList.contains('state-active')) {
given += 1 << ((rowIndex - 3) * 9 + childIndex)
}
childIndex++
}
}
})
if (given !== 2560660350) {
alert('Nope! Try Again')
return
}
// Render Certificate
const time = timestamp()
const name = prompt('Congratulations you won! Please enter the name for your certificate:', 'Anon')
document.querySelector<HTMLDivElement>('div.layout-document')!.style.display = 'block'
document.querySelector<HTMLSpanElement>('span#date')!.textContent = new Date().toDateString()
document.querySelector<HTMLSpanElement>('span#time')!.textContent = time
document.querySelector<HTMLSpanElement>('span#name')!.textContent = name
print()
document.location.assign('/')
})