v©"' "$8®:w½c#àí¨¬ cordQ text/html M><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>声æ´_Brave Little Leaf</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
color: #fff;
margin: 0;
padding: 0;
min-height: 100vh;
background: #000;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.wrapper {
position: relative;
width: 95%;
max-width: min(95vh, 95vw, 1200px);
margin: 0 auto;
aspect-ratio: 1/1;
overflow: hidden;
cursor: pointer;
}
.image-container {
position: relative;
width: 100%;
height: 100%;
}
.original-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 92%;
/* Image height limited to create bottom margin */
object-fit: contain;
filter: grayscale(100%);
z-index: 1;
/* Set layer order */
}
.color-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 92%;
/* Same height as image */
mix-blend-mode: color; /* Changed from soft-light to color */
opacity: 0;
transition: all 3s ease;
background-color: transparent;
z-index: 2;
/* Set layer order */
}
.active .color-overlay {
opacity: 1;
}
/* Info display area - completely separated from image area */
.info-container {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 8%;
/* Space for image */
padding: 0 10px;
background: rgba(0, 0, 0, 0.8);
/* Opaque background */
display: flex;
flex-direction: row;
/* Changed to horizontal */
align-items: center;
justify-content: center;
transition: opacity 0.3s ease;
z-index: 5;
/* Ensure layer order */
}
/* Info display text - consolidated to one line */
.info-text {
background: rgba(0, 0, 0, 0.6);
padding: 4px 12px;
border-radius: 4px;
font-size: clamp(10px, 1.5vw, 14px);
text-align: center;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
opacity: 0.7;
transition: opacity 0.3s ease;
cursor: pointer;
max-width: 90%;
}
.info-text:hover,
.info-text:active {
opacity: 1;
}
/* Hidden class to properly hide elements */
.hidden {
display: none !important;
}
.loader {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: clamp(30px, 5vw, 40px);
height: clamp(30px, 5vw, 40px);
border: 4px solid rgba(255, 255, 255, 0.3);
border-radius: 50%;
border-top-color: #fff;
animation: spin 1s ease-in-out infinite;
}
@keyframes spin {
to {
transform: translate(-50%, -50%) rotate(360deg);
}
}
.error-message {
position: absolute;
top: 10px;
left: 50%;
transform: translateX(-50%);
background: rgba(255, 0, 0, 0.6);
color: white;
padding: 8px 12px;
border-radius: 4px;
font-size: clamp(10px, 1.5vw, 12px);
text-align: center;
max-width: 90%;
z-index: 10;
}
/* Responsive adjustments for different screen sizes and orientations */
@media (min-width: 1400px) {
.wrapper {
max-width: min(90vh, 90vw, 1400px);
}
}
@media (max-width: 768px) {
.wrapper {
width: 98%;
max-width: min(98vh, 98vw, 800px);
}
/* Mobile settings adjustment */
.info-container {
height: 10%;
/* Larger info area for mobile */
background: rgba(0, 0, 0, 0.9);
/* Darker background for mobile */
}
/* Clearer separation of image and info container on mobile */
.original-image,
.color-overlay {
height: 90%;
}
}
@media (orientation: landscape) {
.wrapper {
max-height: 90vh;
}
}
@media (orientation: portrait) {
.wrapper {
max-width: 95vw;
}
}
@media (max-width: 480px) {
.info-text {
padding: 4px 8px;
}
/* Mobile size adjustments handled in JavaScript */
}
</style>
</head>
<body>
<div class="wrapper" id="artWrapper">
<div class="image-container">
<img class="original-image" src="https://ordfs.network/content/65f5499c3f2df56e8aa8f2b85f69a5c2551e42d0f99454d284291e67199a1049_0" alt="声æ´_Brave Little Leaf">
<div class="color-overlay" id="colorOverlay"></div>
<div class="info-container" id="infoContainer">
<div class="info-text" id="infoText">Original</div>
</div>
<div id="loader" class="loader"></div>
</div>
<div id="errorMessage" class="error-message" style="display: none;"></div>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
// Set artwork ID here - CHANGE THIS VALUE FOR EACH ARTWORK (1-16)
const artworkId = 8; // Change this to a value between 1 and 16 for each artwork
// Get elements
const artWrapper = document.getElementById('artWrapper');
const originalImage = document.querySelector('.original-image');
const colorOverlay = document.getElementById('colorOverlay');
const infoText = document.getElementById('infoText');
const infoContainer = document.getElementById('infoContainer');
const loader = document.getElementById('loader');
const errorMessageDisplay = document.getElementById('errorMessage');
// Initial state
let currentHash = '';
let currentColor = '';
let isActive = false; // false = Original, true = Colored
let displayMode = 0; // 0 = Mode display(Original/Colored), 1 = Hash, 2 = Color Matrix
let opacityTimeout; // Timeout for opacity change
const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
// Define clickable/tappable areas to distinguish between image area and text area
const imageArea = document.createElement('div');
imageArea.style.position = 'absolute';
imageArea.style.top = '0';
imageArea.style.left = '0';
imageArea.style.width = '100%';
imageArea.style.height = isMobile ? '90%' : '92%';
imageArea.style.zIndex = '3';
imageArea.style.cursor = 'pointer';
artWrapper.appendChild(imageArea);
// Toggle Original/Colored mode only in the image area
imageArea.addEventListener('click', (e) => {
toggleColorOverlay();
// Return to mode display
displayMode = 0;
updateInfoText();
});
// Toggle display mode by clicking/tapping on the info text
infoText.addEventListener('click', (e) => {
e.stopPropagation(); // Prevent event propagation
// Toggle display mode (0â1â2â0...)
displayMode = (displayMode + 1) % 3;
updateInfoText();
// Temporarily increase opacity after tap
infoText.style.opacity = '1';
// Set timeout to fade out
if (opacityTimeout) {
clearTimeout(opacityTimeout);
}
opacityTimeout = setTimeout(() => {
infoText.style.opacity = '0.7';
}, 2000); // After 2 seconds
});
// Event handling for touch devices
if (isMobile) {
document.addEventListener('touchend', (e) => {
// If tapping outside infoText, fade info display after 2 seconds
if (e.target !== infoText) {
if (opacityTimeout) {
clearTimeout(opacityTimeout);
}
opacityTimeout = setTimeout(() => {
infoText.style.opacity = '0.7';
}, 2000);
}
});
} else {
// Desktop hover effect
infoText.addEventListener('mouseenter', () => {
if (opacityTimeout) {
clearTimeout(opacityTimeout);
}
infoText.style.opacity = '1';
});
infoText.addEventListener('mouseleave', () => {
infoText.style.opacity = '0.7';
});
}
// Mode toggle (Original/Colored)
function toggleColorOverlay() {
isActive = !isActive;
if (isActive) {
artWrapper.classList.add('active');
} else {
artWrapper.classList.remove('active');
}
// Update display when mode changes
updateInfoText();
}
// Update display text
function updateInfoText() {
switch(displayMode) {
case 0: // Mode display
infoText.textContent = isActive ? 'Colored' : 'Original';
infoText.style.fontSize = 'clamp(10px, 1.5vw, 14px)'; // Normal size
break;
case 1: // Hash display
infoText.textContent = currentHash ? `Hash: ${getDisplayHash()}` : 'Hash: Loading...';
infoText.style.fontSize = 'clamp(8px, 1.2vw, 12px)'; // Smaller size
break;
case 2: // Color Matrix display
infoText.textContent = currentColor ? `Color Matrix: ${currentColor.hsla}` : 'Color Matrix: Loading...';
infoText.style.fontSize = 'clamp(8px, 1.2vw, 12px)'; // Smaller size
break;
}
}
// Adjust hash display according to screen size
function getDisplayHash() {
const width = window.innerWidth;
if (width < 480) {
// Shortened display for mobile
return currentHash.substring(0, 6) + '...' + currentHash.substring(currentHash.length - 6);
} else if (width < 768) {
// Medium display for tablets
return currentHash.substring(0, 10) + '...' + currentHash.substring(currentHash.length - 10);
} else {
// Full display for desktop
return currentHash;
}
}
// RGB to HSL conversion function
function rgbToHsl(r, g, b) {
r /= 255;
g /= 255;
b /= 255;
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
let h, s, l = (max + min) / 2;
if (max === min) {
h = s = 0; // achromatic
} else {
const d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return [h * 360, s, l];
}
// HSL to RGB conversion function
function hslToRgb(h, s, l) {
h /= 360;
let r, g, b;
if (s === 0) {
r = g = b = l; // achromatic
} else {
const hue2rgb = (p, q, t) => {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
const p = 2 * l - q;
r = hue2rgb(p, q, h + 1/3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1/3);
}
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
}
// Modified color generation function with color rotation
function generateColorFromHash(hash) {
if (!hash || hash.length < 6) return 'rgba(0, 0, 0, 0)';
// Split hash into sections
const sections = [];
for (let i = 0; i < hash.length; i += 8) {
if (i + 8 <= hash.length) {
sections.push(hash.substring(i, i + 8));
} else {
sections.push(hash.substring(i));
}
}
// Calculate values from each section
const sectionValues = sections.map(section => {
return parseInt(section, 16) || 0;
});
// Generate RGB values from hash
const r = sectionValues[3] % 256;
const g = sectionValues[4] % 256;
const b = sectionValues[5] % 256;
// Convert RGB to HSL
const [h, s, l] = rgbToHsl(r, g, b);
// Apply color rotation based on artwork ID
// Each artwork rotates the hue by (360/16) degrees
const rotationDegree = (360 / 16) * (artworkId - 1);
const newHue = (h + rotationDegree) % 360;
// Convert back to RGB with the rotated hue
const [newR, newG, newB] = hslToRgb(newHue, s, l);
// Add variation to opacity as well
const alpha = 0.6 + ((sectionValues[6] % 40) / 100); // Range 0.6-1.0
// RGBA color value
const colorValue = `rgba(${newR}, ${newG}, ${newB}, ${alpha.toFixed(2)})`;
return {
hsla: colorValue // Keep property name for compatibility
};
}
// Fetch latest block hash from WhatsOnChain API
async function fetchLatestBlockHash() {
setLoading(true);
try {
// Add headers to avoid CORS errors
const response = await fetch('https://api.whatsonchain.com/v1/bsv/main/chain/info', {
mode: 'cors',
headers: {
'Accept': 'application/json'
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
setLoading(false);
if (data && data.bestblockhash) {
console.log("Retrieved latest block hash:", data.bestblockhash);
updateWithHash(data.bestblockhash);
return data.bestblockhash;
} else {
throw new Error('No block hash found');
}
} catch (error) {
console.error("API connection error:", error.message);
setError(`API Error: ${error.message}`);
setLoading(false);
// Latest known block hash (as of May 4, 2025)
const latestKnownHash = '00000000000000000669d9c599a8be6b48a3907c56b10909308f7e5b0924b973';
console.log("Using fallback hash:", latestKnownHash);
updateWithHash(latestKnownHash);
return null;
}
}
// Update image color overlay with hash
function updateWithHash(hash) {
currentHash = hash;
const colorData = generateColorFromHash(hash);
currentColor = colorData;
colorOverlay.style.backgroundColor = colorData.hsla;
// Update info display
updateInfoText();
}
// Set loading state
function setLoading(isLoading) {
if (isLoading) {
loader.style.display = 'block';
} else {
loader.style.display = 'none';
}
}
// Set error message
function setError(message) {
if (message) {
errorMessageDisplay.textContent = message;
errorMessageDisplay.style.display = 'block';
setTimeout(() => {
errorMessageDisplay.style.display = 'none';
}, 5000); // Hide error after 5 seconds
} else {
errorMessageDisplay.style.display = 'none';
}
}
// Handle image loading errors
originalImage.onerror = () => {
setError('Failed to load image.');
};
// Listen for window resize events
window.addEventListener('resize', () => {
// Adjust image area size on resize
imageArea.style.height = isMobile ? '90%' : '92%';
// Update display text
updateInfoText();
});
// Auto fetch the latest block hash on page load
fetchLatestBlockHash();
// Fetch new block hash every 1 minute
// BSV blocks are generated approximately every 10 minutes, but we check more frequently to stay current
setInterval(fetchLatestBlockHash, 60 * 1000);
});
</script>
</body>
</html>hj"1PuQa7K62MiKCtssSLKy1kh56WWU7MtUR5SETappZoideNFTtypeordnameBrave Little LeafsubTypecollectionItemsubTypeDataL{"name":"Brave Little Leaf","collectionId":"0eee6b6c46d2eab113c2a0a06e53b2929d3e315cfe344ac96aa611faef3d5d42_0","mintNumber":"8","rarityLabel":"EXOTIC"} royaltiesLX[{"type":"address","destination":"1Kx1aTBAuXzDULVYQvWtwPY5uuipLQTrJ3","percentage":0.1}]|SIGMABSM"12KP5KzkBwtsc1UrTrsBCJzgqKn8UqaYQqA¹°«4ïéûÕüÅ(tYÍXñàC¡oï¡?'iç¹áÿ¾#&MÔU¨¸¬;IÓÀ´0
https://whatsonchain.com/tx/undefined