TV GRANNY - MODELO 1987
<html style="margin:0;padding:0;">
<link href="https://fonts.googleapis.com/css2?family=Urbanist:wght@400;500;600;700&family=Special+Elite&display=swap" rel="stylesheet">
<script src="https://cdn.tailwindcss.com"></script>
<script>
(function(){
var s = document.createElement('style');
s.textContent = `
:root{
--bg:#1a1410;
--card:#2a1f17;
--text:#e8dcc8;
--muted:#8a7a65;
--accent:#8b2500;
--accent-soft:rgba(139,37,0,.25);
--accent2:#c9a227;
--accent2-soft:rgba(201,162,39,.2);
--border:rgba(232,220,200,.12);
--wood-dark:#3a2818;
--wood-mid:#4a3422;
--wood-light:#5c4230;
}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);font-family:'Urbanist',sans-serif;color:var(--text);overflow-x:hidden}
/* Wood texture using gradients */
.wood-frame{
background:
repeating-linear-gradient(90deg, transparent 0px, transparent 2px, rgba(0,0,0,.08) 2px, rgba(0,0,0,.08) 3px),
repeating-linear-gradient(0deg, transparent 0px, transparent 40px, rgba(255,255,255,.02) 40px, rgba(255,255,255,.02) 41px),
linear-gradient(135deg, var(--wood-dark) 0%, var(--wood-mid) 30%, var(--wood-dark) 50%, var(--wood-mid) 70%, var(--wood-dark) 100%);
border:4px solid #2a1a0e;
box-shadow:
inset 0 0 40px rgba(0,0,0,.6),
inset 0 2px 4px rgba(255,255,255,.05),
0 10px 40px rgba(0,0,0,.7),
0 2px 8px rgba(0,0,0,.5);
}
/* CRT Screen effect */
.crt-screen{
position:relative;
background:#000;
border:6px solid #1a0f08;
border-radius:8px;
box-shadow:
inset 0 0 60px rgba(0,0,0,.9),
inset 0 0 20px rgba(0,0,0,.8),
0 0 2px rgba(0,0,0,.8);
overflow:hidden;
}
.crt-screen::before{
content:'';
position:absolute;
inset:0;
background:repeating-linear-gradient(0deg, rgba(0,0,0,.15) 0px, rgba(0,0,0,.15) 1px, transparent 1px, transparent 3px);
pointer-events:none;
z-index:10;
}
.crt-screen::after{
content:'';
position:absolute;
inset:0;
background:radial-gradient(ellipse at center, transparent 40%, rgba(0,0,0,.5) 100%);
pointer-events:none;
z-index:11;
}
.crt-glow{
box-shadow:0 0 30px rgba(255,200,100,.15), inset 0 0 40px rgba(255,200,100,.05);
}
/* Static noise */
.static-canvas{position:absolute;inset:0;width:100%;height:100%;z-index:5}
/* LED indicator */
.led-off{
background:#3a0a00;
box-shadow:inset 0 1px 2px rgba(0,0,0,.8);
}
.led-on{
background:#ff2a00;
box-shadow:0 0 8px #ff2a00, 0 0 16px #ff4500, inset 0 0 4px rgba(255,255,255,.3);
animation:ledPulse 2s ease-in-out infinite;
}
@keyframes ledPulse{0%,100%{opacity:1}50%{opacity:.7}}
/* Knobs */
.knob{
width:44px;height:44px;border-radius:50%;cursor:pointer;
background:radial-gradient(circle at 35% 30%, #6a5540, #3a2818 70%);
border:3px solid #1a0f08;
box-shadow:0 3px 8px rgba(0,0,0,.6), inset 0 1px 2px rgba(255,255,255,.1);
position:relative;
transition:transform .1s;
}
.knob:hover{transform:scale(1.05)}
.knob:active{transform:scale(.95)}
.knob::after{
content:'';position:absolute;top:4px;left:50%;transform:translateX(-50%);
width:3px;height:12px;background:var(--accent2);border-radius:2px;
}
/* Speaker grille */
.speaker-grille{
background:
repeating-linear-gradient(90deg, #1a0f08 0px, #1a0f08 2px, #2a1a0e 2px, #2a1a0e 4px),
repeating-linear-gradient(0deg, transparent 0px, transparent 3px, rgba(0,0,0,.3) 3px, rgba(0,0,0,.3) 4px);
border:2px solid #1a0f08;
border-radius:4px;
}
/* Antenna */
.antenna{
position:absolute;top:-30px;
width:3px;height:40px;background:linear-gradient(180deg,#888,#444);
border-radius:2px;
box-shadow:0 0 2px rgba(0,0,0,.5);
}
/* Control buttons */
.ctrl-btn{
padding:8px 14px;border-radius:6px;font-size:12px;font-weight:600;
cursor:pointer;transition:all .15s;border:1px solid var(--border);
background:linear-gradient(180deg,var(--wood-light),var(--wood-dark));
color:var(--text);
box-shadow:0 2px 6px rgba(0,0,0,.4), inset 0 1px 0 rgba(255,255,255,.08);
font-family:'Urbanist',sans-serif;
letter-spacing:.03em;
}
.ctrl-btn:hover{
background:linear-gradient(180deg,var(--wood-mid),var(--wood-dark));
transform:translateY(-1px);
box-shadow:0 3px 10px rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.1);
}
.ctrl-btn:active{transform:translateY(1px);box-shadow:0 1px 3px rgba(0,0,0,.4)}
.ctrl-btn.active{
background:linear-gradient(180deg,var(--accent),#5a1800);
border-color:var(--accent);
color:#fff;
}
/* Channel buttons */
.ch-btn{
width:36px;height:36px;border-radius:50%;cursor:pointer;
background:radial-gradient(circle at 35% 30%, #5a4530, #2a1808 70%);
border:2px solid #1a0f08;color:var(--text);
font-weight:700;font-size:14px;
box-shadow:0 2px 6px rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.08);
transition:all .15s;display:flex;align-items:center;justify-content:center;
}
.ch-btn:hover{transform:scale(1.08)}
.ch-btn:active{transform:scale(.92)}
.ch-btn.active{
background:radial-gradient(circle at 35% 30%, var(--accent2), #8a6a10 70%);
color:#1a0f08;
box-shadow:0 0 12px rgba(201,162,39,.4), 0 2px 6px rgba(0,0,0,.5);
}
/* Input field */
.url-input{
flex:1;padding:10px 14px;border-radius:6px;
background:#0f0a06;border:2px solid #2a1a0e;
color:var(--text);font-family:'Urbanist',sans-serif;font-size:13px;
outline:none;transition:border-color .2s;
}
.url-input:focus{border-color:var(--accent2)}
.url-input::placeholder{color:var(--muted)}
/* Censor overlay */
.censor-overlay{
position:absolute;inset:0;z-index:20;
background:rgba(0,0,0,.85);
backdrop-filter:blur(8px);
display:flex;align-items:center;justify-content:center;
color:var(--muted);font-size:14px;letter-spacing:.2em;text-transform:uppercase;
}
/* Power off screen */
.power-off{
position:absolute;inset:0;background:#000;z-index:6;
display:flex;align-items:center;justify-content:center;
}
/* Channel label */
.channel-label{
position:absolute;top:10px;right:10px;z-index:15;
background:rgba(0,0,0,.7);color:var(--accent2);
padding:4px 10px;border-radius:4px;font-size:12px;
font-weight:700;letter-spacing:.1em;
border:1px solid rgba(201,162,39,.3);
font-family:'Special Elite',monospace;
}
/* Volume indicator */
.vol-bar{
height:4px;background:#1a0f08;border-radius:2px;overflow:hidden;
border:1px solid #0a0604;
}
.vol-fill{
height:100%;background:linear-gradient(90deg,var(--accent2),#e8c84a);
transition:width .2s;
}
/* Scratches on wood */
.scratches{
position:absolute;inset:0;pointer-events:none;opacity:.3;
background:
linear-gradient(115deg, transparent 48%, rgba(255,255,255,.03) 49%, transparent 50%),
linear-gradient(65deg, transparent 60%, rgba(0,0,0,.08) 61%, transparent 62%);
}
/* Dust particles */
@keyframes flicker{0%,100%{opacity:.97}50%{opacity:1}}
.flicker{animation:flicker .15s infinite}
/* Fullscreen mode */
.fullscreen-mode{
position:fixed !important;inset:20px !important;z-index:9999;
width:calc(100vw - 40px) !important;height:calc(100vh - 40px) !important;
}
/* Reveal animation */
.reveal{opacity:0;transform:translateY(20px);animation:fadeUp .6s ease forwards}
.reveal:nth-child(2){animation-delay:.1s}
@keyframes fadeUp{to{opacity:1;transform:translateY(0)}}
/* Scrollbar */
::-webkit-scrollbar{width:8px;height:8px}
::-webkit-scrollbar-track{background:var(--bg)}
::-webkit-scrollbar-thumb{background:var(--wood-mid);border-radius:4px}
::-webkit-scrollbar-thumb:hover{background:var(--wood-light)}
`;
document.head.appendChild(s);
})();
</script>
<div style="background:radial-gradient(ellipse at 50% 30%, #2a1f15 0%, #1a1410 60%, #0f0b08 100%);min-height:100%;padding:24px 16px 48px;">
<div class="max-w-5xl mx-auto">
<!-- Title -->
<div class="reveal text-center mb-6">
<h1 style="font-family:'Special Elite',monospace;font-size:28px;color:var(--text);margin-bottom:6px;letter-spacing:.05em">TV GRANNY — MODELO 1987</h1>
<p style="color:var(--muted);font-size:13px">Sala de estar — Móvel de madeira escura</p>
</div>
<!-- TV Container -->
<div class="reveal" id="tvContainer">
<div class="wood-frame rounded-2xl p-5 md:p-7 relative" style="position:relative">
<div class="scratches rounded-2xl"></div>
<!-- Antennas -->
<div class="antenna" style="left:25%;transform:rotate(-15deg)"></div>
<div class="antenna" style="left:30%;transform:rotate(10deg);height:50px"></div>
<!-- Brand label -->
<div style="text-align:center;margin-bottom:10px">
<span style="font-family:'Special Elite',monospace;font-size:10px;color:var(--muted);letter-spacing:.3em;text-transform:uppercase">Granny Electronics Co.</span>
</div>
<!-- Main TV body -->
<div style="display:flex;flex-direction:column;gap:16px">
<!-- Screen -->
<div class="crt-screen" id="crtScreen" style="aspect-ratio:16/9;width:100%;max-width:100%;cursor:pointer" onclick="toggleFullscreen()">
<!-- Channel label -->
<div class="channel-label" id="channelLabel">CH 01 — OFF</div>
<!-- Power off overlay -->
<div class="power-off" id="powerOff">
<div style="text-align:center;color:#333;font-family:'Special Elite',monospace">
<div style="font-size:11px;letter-spacing:.2em">SEMINAROO</div>
</div>
</div>
<!-- Static canvas -->
<canvas class="static-canvas" id="staticCanvas" style="display:none"></canvas>
<!-- YouTube iframe -->
<iframe id="ytPlayer" style="position:absolute;inset:0;width:100%;height:100%;border:none;z-index:4;display:none"
src="" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<!-- Censor overlay -->
<div class="censor-overlay" id="censorOverlay" style="display:none">
<span style="font-family:'Special Elite',monospace">— CENSURADO —</span>
</div>
</div>
<!-- Bottom panel: speakers + knobs -->
<div style="display:flex;gap:16px;align-items:center;flex-wrap:wrap">
<!-- Left speaker -->
<div class="speaker-grille" style="flex:1;min-width:80px;height:50px"></div>
<!-- Knobs area -->
<div style="display:flex;gap:20px;align-items:center;padding:0 10px">
<div style="text-align:center">
<div class="knob" id="volKnob" onclick="cycleVolume()" title="Volume"></div>
<div style="font-size:9px;color:var(--muted);margin-top:4px;letter-spacing:.1em;text-transform:uppercase">VOL</div>
</div>
<div style="text-align:center">
<div class="knob" id="chKnob" onclick="nextChannel()" title="Canal"></div>
<div style="font-size:9px;color:var(--muted);margin-top:4px;letter-spacing:.1em;text-transform:uppercase">CH</div>
</div>
</div>
<!-- Right speaker -->
<div class="speaker-grille" style="flex:1;min-width:80px;height:50px"></div>
<!-- LED indicator -->
<div style="display:flex;align-items:center;gap:8px;padding:0 8px">
<div id="ledIndicator" class="led-off" style="width:12px;height:12px;border-radius:50%;border:2px solid #0a0604"></div>
<span style="font-size:9px;color:var(--muted);letter-spacing:.1em;text-transform:uppercase">PWR</span>
</div>
</div>
</div>
</div>
</div>
<!-- Control Panel -->
<div class="reveal mt-6 rounded-xl p-5" style="background:var(--card);border:1px solid var(--border);box-shadow:0 4px 20px rgba(0,0,0,.4)">
<div style="font-family:'Special Elite',monospace;font-size:12px;color:var(--accent2);letter-spacing:.2em;text-transform:uppercase;margin-bottom:14px">PAINEL DE CONTROLE</div>
<!-- URL input -->
<div style="display:flex;gap:10px;flex-wrap:wrap;margin-bottom:16px">
<input type="text" class="url-input" id="urlInput" placeholder="Cole o link do YouTube aqui..."
onkeypress="if(event.key==='Enter')loadVideo()">
<button class="ctrl-btn" onclick="loadVideo()" style="background:linear-gradient(180deg,var(--accent2),#8a6a10);color:#1a0f08;border-color:#8a6a10">
CARREGAR
</button>
</div>
<!-- Main buttons row 1 -->
<div style="display:flex;flex-wrap:wrap;gap:10px;margin-bottom:12px">
<button class="ctrl-btn" id="powerBtn" onclick="togglePower()">
<span id="powerIcon">⏻</span> LIGAR
</button>
<button class="ctrl-btn" onclick="volumeUp()">
▲ VOL +
</button>
<button class="ctrl-btn" onclick="volumeDown()">
▼ VOL −
</button>
<button class="ctrl-btn" id="muteBtn" onclick="toggleMute()">
MUDO
</button>
</div>
<!-- Main buttons row 2 -->
<div style="display:flex;flex-wrap:wrap;gap:10px;margin-bottom:16px">
<button class="ctrl-btn" onclick="copyLink()">
COPIAR LINK
</button>
<button class="ctrl-btn" onclick="clearScreen()">
LIMPAR TELA
</button>
<button class="ctrl-btn" id="censorBtn" onclick="toggleCensor()">
CENSURAR
</button>
<button class="ctrl-btn" onclick="toggleFullscreen()">
TELA CHEIA
</button>
</div>
<!-- Channel selector -->
<div style="display:flex;align-items:center;gap:12px;flex-wrap:wrap;padding-top:14px;border-top:1px solid var(--border)">
<span style="font-size:11px;color:var(--muted);letter-spacing:.15em;text-transform:uppercase">Canais:</span>
<div style="display:flex;gap:10px;flex-wrap:wrap">
<button class="ch-btn active" id="ch1" onclick="setChannel(1)" title="Desligado / Estática">1</button>
<button class="ch-btn" id="ch2" onclick="setChannel(2)" title="Sprunki Music">2</button>
<button class="ch-btn" id="ch3" onclick="setChannel(3)" title="Curtas & Animações">3</button>
<button class="ch-btn" id="ch4" onclick="setChannel(4)" title="Seu link YouTube">4</button>
</div>
<div style="margin-left:auto;display:flex;align-items:center;gap:8px;min-width:120px">
<span style="font-size:10px;color:var(--muted);letter-spacing:.1em;text-transform:uppercase">VOL</span>
<div class="vol-bar" style="flex:1;width:80px"><div class="vol-fill" id="volFill" style="width:70%"></div></div>
<span id="volPct" style="font-size:10px;color:var(--accent2);font-weight:700;font-family:'Special Elite',monospace;min-width:28px">70%</span>
</div>
</div>
<!-- Status -->
<div id="statusMsg" style="margin-top:14px;padding:10px 14px;border-radius:6px;background:rgba(0,0,0,.3);border:1px solid var(--border);font-size:12px;color:var(--muted);font-family:'Special Elite',monospace;min-height:38px;display:flex;align-items:center">
TV desligada. Pressione LIGAR para começar...
</div>
</div>
<!-- Instructions -->
<div class="reveal mt-6 rounded-xl p-5" style="background:var(--card);border:1px solid var(--border)">
<div style="font-family:'Special Elite',monospace;font-size:12px;color:var(--accent2);letter-spacing:.2em;text-transform:uppercase;margin-bottom:10px">INSTRUÇÕES</div>
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:10px;font-size:12px;color:var(--muted);line-height:1.6">
<div><span style="color:var(--text);font-weight:600">1.</span> Clique em LIGAR para ligar a TV</div>
<div><span style="color:var(--text);font-weight:600">2.</span> Cole um link do YouTube e clique CARREGAR</div>
<div><span style="color:var(--text);font-weight:600">3.</span> Use os botões de CANAL para mudar</div>
<div><span style="color:var(--text);font-weight:600">4.</span> Ajuste o volume ou ative o MUDO</div>
<div><span style="color:var(--text);font-weight:600">5.</span> Clique na tela para TELA CHEIA</div>
<div><span style="color:var(--text);font-weight:600">6.</span> Use CENSURAR para ocultar a imagem</div>
</div>
<div style="margin-top:12px;padding-top:12px;border-top:1px solid var(--border);font-size:11px;color:var(--muted)">
<span style="color:var(--accent2);font-weight:600">Canais pré-configurados:</span> CH1=Estática | CH2=Sprunki Music | CH3=Curtas | CH4=Seu link
</div>
</div>
</div>
</div>
<script>
(function(){
// State
window.tvState = {
powered: false,
channel: 1,
volume: 70,
muted: false,
censored: false,
fullscreen: false,
currentUrl: '',
currentVideoId: '',
staticInterval: null
};
// Predefined channels
window.channels = {
2: { name: 'Sprunki Music', videoId: 'dQw4w9WgXcQ' }, // placeholder - will use search
3: { name: 'Curtas & Animações', videoId: '9bZkp7q19f0' } // placeholder
};
// DOM elements
window.els = {
crtScreen: document.getElementById('crtScreen'),
powerOff: document.getElementById('powerOff'),
staticCanvas: document.getElementById('staticCanvas'),
ytPlayer: document.getElementById('ytPlayer'),
censorOverlay: document.getElementById('censorOverlay'),
ledIndicator: document.getElementById('ledIndicator'),
powerBtn: document.getElementById('powerBtn'),
powerIcon: document.getElementById('powerIcon'),
muteBtn: document.getElementById('muteBtn'),
censorBtn: document.getElementById('censorBtn'),
channelLabel: document.getElementById('channelLabel'),
urlInput: document.getElementById('urlInput'),
statusMsg: document.getElementById('statusMsg'),
volFill: document.getElementById('volFill'),
volPct: document.getElementById('volPct'),
tvContainer: document.getElementById('tvContainer')
};
// Static noise generator
window.initStatic = function() {
var canvas = els.staticCanvas;
var ctx = canvas.getContext('2d');
function resize(){
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
}
resize();
window.addEventListener('resize', resize);
function drawStatic(){
if(!tvState.powered || tvState.channel !== 1) return;
var w = canvas.width, h = canvas.height;
var imgData = ctx.createImageData(w, h);
var data = imgData.data;
for(var i=0;i<data.length;i+=4){
var v = Math.random()*255;
data[i] = v; data[i+1] = v; data[i+2] = v; data[i+3] = 255;
}
ctx.putImageData(imgData, 0, 0);
}
if(tvState.staticInterval) clearInterval(tvState.staticInterval);
tvState.staticInterval = setInterval(drawStatic, 80);
};
// Play click sound via Web Audio
window.playClick = function(type){
try{
var AC = window.AudioContext || window.webkitAudioContext;
if(!AC) return;
var ctx = new AC();
var osc = ctx.createOscillator();
var gain = ctx.createGain();
osc.connect(gain); gain.connect(ctx.destination);
if(type==='power'){
osc.frequency.setValueAtTime(80, ctx.currentTime);
osc.frequency.exponentialRampToValueAtTime(2000, ctx.currentTime+0.05);
osc.frequency.exponentialRampToValueAtTime(100, ctx.currentTime+0.2);
gain.gain.setValueAtTime(0.2, ctx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime+0.25);
osc.start(); osc.stop(ctx.currentTime+0.25);
} else if(type==='static'){
// white noise burst
var bufferSize = ctx.sampleRate * 0.15;
var buffer = ctx.createBuffer(1, bufferSize, ctx.sampleRate);
var data = buffer.getChannelData(0);
for(var i=0;i<bufferSize;i++) data[i] = Math.random()*2-1;
var noise = ctx.createBufferSource();
noise.buffer = buffer;
var ng = ctx.createGain();
ng.gain.setValueAtTime(0.15, ctx.currentTime);
ng.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime+0.15);
noise.connect(ng); ng.connect(ctx.destination);
noise.start();
} else {
osc.frequency.setValueAtTime(600, ctx.currentTime);
osc.frequency.exponentialRampToValueAtTime(200, ctx.currentTime+0.08);
gain.gain.setValueAtTime(0.1, ctx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime+0.1);
osc.start(); osc.stop(ctx.currentTime+0.1);
}
} catch(e){}
};
// Extract YouTube video ID
window.extractVideoId = function(url){
if(!url) return null;
var patterns = [
/(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([a-zA-Z0-9_-]{11})/,
/youtube\.com\/shorts\/([a-zA-Z0-9_-]{11})/
];
for(var i=0;i<patterns.length;i++){
var m = url.match(patterns[i]);
if(m) return m[1];
}
return null;
};
// Update status
window.setStatus = function(msg){
els.statusMsg.textContent = msg;
};
// Update channel label
window.updateChannelLabel = function(){
var names = {1:'OFF / ESTÁTICA', 2:'SPRUNKI MUSIC', 3:'CURTAS & ANIMAÇÕES', 4:'SEU LINK YT'};
var ch = tvState.channel;
els.channelLabel.textContent = 'CH 0' + ch + ' — ' + names[ch];
// Update channel buttons
for(var i=1;i<=4;i++){
var btn = document.getElementById('ch'+i);
if(btn) btn.classList.toggle('active', i===ch);
}
};
// Update volume display
window.updateVolumeDisplay = function(){
var v = tvState.muted ? 0 : tvState.volume;
els.volFill.style.width = v + '%';
els.volPct.textContent = v + '%';
els.muteBtn.classList.toggle('active', tvState.muted);
};
// Toggle power
window.togglePower = function(){
tvState.powered = !tvState.powered;
playClick('power');
if(tvState.powered){
els.powerOff.style.display = 'none';
els.ledIndicator.className = 'led-on';
els.powerIcon.textContent = '⏻';
els.powerBtn.querySelector('span').textContent = '⏻';
els.powerBtn.childNodes[1].textContent = ' DESLIGAR';
els.crtScreen.classList.add('crt-glow','flicker');
setStatus('TV ligada! Selecione um canal ou cole um link do YouTube.');
setChannel(tvState.channel);
initStatic();
} else {
els.powerOff.style.display = 'flex';
els.staticCanvas.style.display = 'none';
els.ytPlayer.style.display = 'none';
els.ytPlayer.src = '';
els.ledIndicator.className = 'led-off';
els.powerBtn.querySelector('span').textContent = '⏻';
els.powerBtn.childNodes[1].textContent = ' LIGAR';
els.crtScreen.classList.remove('crt-glow','flicker');
if(tvState.staticInterval){ clearInterval(tvState.staticInterval); tvState.staticInterval=null; }
setStatus('TV desligada.');
}
};
// Set channel
window.setChannel = function(ch){
if(!tvState.powered){
setStatus('Ligue a TV primeiro!');
return;
}
tvState.channel = ch;
updateChannelLabel();
playClick('static');
// Brief static flash
els.staticCanvas.style.display = 'block';
els.ytPlayer.style.display = 'none';
setTimeout(function(){
if(ch === 1){
// Static only
els.staticCanvas.style.display = 'block';
els.ytPlayer.style.display = 'none';
setStatus('Canal 1 — Apenas estática. Nenhum sinal.');
} else if(ch === 4){
// User's link
els.staticCanvas.style.display = 'none';
if(tvState.currentVideoId){
loadVideoById(tvState.currentVideoId);
setStatus('Canal 4 — Reproduzindo seu link do YouTube.');
} else {
els.ytPlayer.style.display = 'none';
setStatus('Canal 4 — Nenhum link carregado. Cole um URL do YouTube acima.');
}
} else {
// Predefined channels
els.staticCanvas.style.display = 'none';
var chData = channels[ch];
if(chData){
loadVideoById(chData.videoId);
setStatus('Canal ' + ch + ' — ' + chData.name);
}
}
}, 400);
};
// Next channel
window.nextChannel = function(){
if(!tvState.powered) return;
var next = (tvState.channel % 4) + 1;
setChannel(next);
};
// Load video by ID
window.loadVideoById = function(videoId){
if(!videoId) return;
tvState.currentVideoId = videoId;
var muteParam = tvState.muted ? '&mute=1' : '';
els.ytPlayer.src = 'https://www.youtube.com/embed/' + videoId + '?autoplay=1&rel=0' + muteParam;
els.ytPlayer.style.display = 'block';
els.staticCanvas.style.display = 'none';
};
// Load video from input
window.loadVideo = function(){
if(!tvState.powered){
setStatus('Ligue a TV primeiro!');
return;
}
var url = els.urlInput.value.trim();
if(!url){
setStatus('Por favor, cole um link do YouTube.');
return;
}
var videoId = extractVideoId(url);
if(!videoId){
setStatus('Link inválido! Use um URL válido do YouTube (youtube.com/watch?v=... ou youtu.be/...).');
return;
}
tvState.currentUrl = url;
tvState.currentVideoId = videoId;
playClick('click');
setChannel(4);
setStatus('Vídeo carregado com sucesso! Reproduzindo no Canal 4.');
};
// Volume controls
window.volumeUp = function(){
if(tvState.volume < 100){
tvState.volume = Math.min(100, tvState.volume + 10);
if(tvState.muted) tvState.muted = false;
updateVolumeDisplay();
playClick('click');
setStatus('Volume: ' + tvState.volume + '%');
}
};
window.volumeDown = function(){
if(tvState.volume > 0){
tvState.volume = Math.max(0, tvState.volume - 10);
if(tvState.muted) tvState.muted = false;
updateVolumeDisplay();
playClick('click');
setStatus('Volume: ' + tvState.volume + '%');
}
};
window.cycleVolume = function(){
volumeUp();
};
window.toggleMute = function(){
tvState.muted = !tvState.muted;
updateVolumeDisplay();
playClick('click');
// Reload player with mute param
if(tvState.currentVideoId && tvState.powered && tvState.channel !== 1){
loadVideoById(tvState.currentVideoId);
}
setStatus(tvState.muted ? 'Mudo ativado.' : 'Mudo desativado. Volume: ' + tvState.volume + '%');
};
// Toggle censor
window.toggleCensor = function(){
tvState.censored = !tvState.censored;
els.censorOverlay.style.display = tvState.censored ? 'flex' : 'none';
els.censorBtn.classList.toggle('active', tvState.censored);
playClick('click');
setStatus(tvState.censored ? 'Tela censurada.' : 'Censura removida.');
};
// Copy link
window.copyLink = function(){
var text = tvState.currentUrl || (tvState.currentVideoId ? 'https://www.youtube.com/watch?v=' + tvState.currentVideoId : '');
if(!text){
setStatus('Nenhum link para copiar.');
return;
}
if(navigator.clipboard){
navigator.clipboard.writeText(text).then(function(){
setStatus('Link copiado para a área de transferência!');
}).catch(function(){
fallbackCopy(text);
});
} else {
fallbackCopy(text);
}
playClick('click');
};
function fallbackCopy(text){
var ta = document.createElement('textarea');
ta.value = text; document.body.appendChild(ta); ta.select();
try{ document.execCommand('copy'); setStatus('Link copiado!'); }
catch(e){ setStatus('Não foi possível copiar automaticamente.'); }
document.body.removeChild(ta);
}
// Clear screen
window.clearScreen = function(){
els.urlInput.value = '';
tvState.currentUrl = '';
tvState.currentVideoId = '';
els.ytPlayer.src = '';
els.ytPlayer.style.display = 'none';
if(tvState.powered){
els.staticCanvas.style.display = 'block';
setChannel(1);
}
playClick('click');
setStatus('Tela limpa. Link e vídeo removidos.');
};
// Toggle fullscreen
window.toggleFullscreen = function(){
tvState.fullscreen = !tvState.fullscreen;
els.tvContainer.classList.toggle('fullscreen-mode', tvState.fullscreen);
playClick('click');
setStatus(tvState.fullscreen ? 'Modo tela cheia ativado. Clique novamente para sair.' : 'Modo normal.');
};
// Init
updateChannelLabel();
updateVolumeDisplay();
})();
</script>
</html>
Public Last updated: 2026-08-13 04:28:03 PM
