Rim Country Media · station operations — who's at the desk?
Nobody has an account yet. The first person to sign up becomes the administrator and can add everyone else.
Southwest Broadcastingv 260829-0210
off the clock
Cast',
tag:"Voice-track copy for tomorrow's air Today · Tonight · Tomorrow",
swap:[['Weathercast','Future Cast'],['Nowcast','Now Cast']] },
'app-wgo':{ title:"What's Going On — Southwest Broadcasting" },
'app-qir':{ title:'Quarterly Issues — Southwest Broadcasting' },
'app-runtimes':{ title:'Run Times — Southwest Broadcasting' },
'app-eas':{ title:'Station & EAS Log — Southwest Broadcasting' },
'app-timer':{ title:'Copy Timer — Southwest Broadcasting' },
'app-restyle':{ title:'Copy Restyler — Southwest Broadcasting' },
'app-calc':{ title:'Calculator — Southwest Broadcasting' },
'app-spot':{ title:'Spot Writer — Southwest Broadcasting' },
'app-border':{ title:'Broadcast Order — Southwest Broadcasting' }, /* was missing, so it kept its own palette */
'app-nowcast':{ title:'Now Cast — Southwest Broadcasting', mark:'Now Cast',
tag:'Current conditions for live on-air Companion to Future Cast',
swap:[['Weathercast','Future Cast'],['Nowcast','Now Cast']] }
};
function themeCss(v){
const dim=(hex,a)=>{ const h=hex.replace('#',''); const n=h.length===3?h.split('').map(c=>c+c).join(''):h;
return 'rgba('+parseInt(n.slice(0,2),16)+','+parseInt(n.slice(2,4),16)+','+parseInt(n.slice(4,6),16)+','+a+')'; };
return ':root,:host{'+
'--accent:'+v.accent+' !important;--accent2:'+v.accent2+' !important;--accent-2:'+v.accent2+' !important;'+
'--accent-dim:'+dim(v.accent,'.14')+' !important;--accentDark:'+v.accentDark+' !important;'+
'--blue:'+v.accent+' !important;--blue2:'+v.accent2+' !important;--blueDark:'+v.accentDark+' !important;'+
'--link:'+v.accent2+' !important;--brand:'+v.accent+' !important;--primary:'+v.accent+' !important;'+
'--live:'+v.accent+' !important;--hi:'+v.accent2+' !important;'+
'--bg:'+v.bg+' !important;--bg2:'+v.bg2+' !important;--bg3:'+v.panel2+' !important;'+
'--panel:'+v.panel+' !important;--panel2:'+v.panel2+' !important;--card:'+v.panel+' !important;'+
'--line:'+v.line+' !important;--line2:'+v.line2+' !important;--border:'+v.line+' !important;'+
'--fg:'+v.ink+' !important;--fg2:'+v.dim+' !important;--fg3:'+v.faint+' !important;'+
'--ink:'+v.ink+' !important;--dim:'+v.dim+' !important;--dimmer:'+v.faint+' !important;--faint:'+v.faint+' !important;'+
'--text:'+v.ink+' !important;--text2:'+v.dim+' !important;--muted:'+v.dim+' !important;'+
'--accent-hi:'+v.accent2+' !important;--panel-2:'+v.panel2+' !important;--line-hi:'+v.line2+' !important;'+
'--ok:'+v.green+' !important;--good:'+v.green+' !important;--bad:'+v.red+' !important;--warn:'+v.amber+' !important;'+
'}'+
/* an app that moves itself into a shadow root leaves the page behind it unpainted,
which shows as a white edge around the frame */
'html,body{background:'+v.bg+' !important;color:'+v.ink+' !important}'+
'a{color:'+v.accent2+'}';
}
/* tell every frame already on screen about a theme change */
function themeToFrames(){
statusRepaint(); /* the status widget is another site, so it reloads */
const T=(window.OPS_THEMES&&window.OPS_THEMES[window.OPS_THEME||'midnight']);
if(!T)return;
const css=themeCss(T.v);
Object.keys(appBlob).forEach(()=>{});
$$('iframe.appframe').forEach(fr=>{ try{ fr.contentWindow.postMessage({opsThemeCss:css},'*'); }catch(e){} });
}
function skinApp(html,id){
const sk=APP_SKIN[id]; if(!sk)return html;
/* the dashboard already prints the page name above the frame — drop the app's own
banner so the studio screen isn't spending 90px saying it twice */
/* the embedded apps carry their own palettes; push the house colours in through
the variable names they use, so a framed app matches the dashboard around it */
const T=(window.OPS_THEMES&&window.OPS_THEMES[window.OPS_THEME||'midnight'])||null;
const V=T?T.v:{accent:'#3987e5',accent2:'#5ea0ef',accentDark:'#1c4f8f',bg:'#0b0f14',bg2:'#0e141b',
panel2:'#141e2a',panel:'#111923',line:'#1e2a38',line2:'#243244',ink:'#e6edf5',dim:'#8fa1b5',
faint:'#5b6b7d',green:'#1fbf7a',red:'#e5533d',amber:'#e0a72e'};
const theme='';
html=html.replace(/<\/head>/i, theme+'');
/* and a listener so switching theme repaints the framed apps without reloading them */
const themeHook='