All checks were successful
Build and deploy / Validate source (push) Successful in 6s
Build and deploy / Integration suite on a real stack (push) Successful in 2m30s
Build and deploy / Secret scan and release gate (push) Successful in 5s
Build and deploy / Publish images (push) Successful in 57s
Reading a large sheet repainted the list and "Sua folha" on every progress step, so the preview flickered; progress now moves the bar in place and "Sua folha" shows a skeleton until the preview is ready. A sheet printed N times is shown N times (up to six, then a count). The payment page shows skeletons while the order loads and until the card form is ready. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
379 lines
18 KiB
JavaScript
379 lines
18 KiB
JavaScript
/* Site DTF — Masks, the nesting engine, and drawing the assembled film.
|
||
Extracted verbatim from the single inline script in web/index.html.
|
||
Loaded as classic scripts in the order listed there: they share one global
|
||
scope and run top to bottom, exactly as the original did. */
|
||
// ── imagens e prévia
|
||
function carregarImagem(file){
|
||
return new Promise(res=>{
|
||
if(!RENDERIZA.test(file.name)) return res(null);
|
||
const fr=new FileReader();
|
||
fr.onload=()=>{ const im=new Image(); im.onload=()=>res(im); im.onerror=()=>res(null); im.src=fr.result; };
|
||
fr.onerror=()=>res(null);
|
||
fr.readAsDataURL(file);
|
||
});
|
||
}
|
||
// A folha precisa parecer uma folha: borda, largura marcada e régua de metros.
|
||
// Sem isso o cliente não tem noção de escala e acha que está mal encaixado.
|
||
function molduraFolha(ctx,W,H,larguraCm,metrosReais){
|
||
const REG=34; // faixa da régua, à direita
|
||
ctx.save();
|
||
// fundo da régua
|
||
ctx.fillStyle='#FAFAF8'; ctx.fillRect(W,0,REG,H);
|
||
ctx.strokeStyle='#D5DAE3'; ctx.lineWidth=1;
|
||
ctx.beginPath(); ctx.moveTo(W+.5,0); ctx.lineTo(W+.5,H); ctx.stroke();
|
||
// marcas a cada 10 cm, número a cada metro
|
||
const pxPorM = H/Math.max(metrosReais,0.01);
|
||
ctx.font='9px "Roboto", sans-serif'; ctx.textAlign='left';
|
||
for(let cm=0; cm<=metrosReais*100; cm+=10){
|
||
const y=cm/100*pxPorM;
|
||
if(y>H) break;
|
||
const metro = cm%100===0;
|
||
ctx.strokeStyle = metro? '#B4BAC5' : '#E1E5EC';
|
||
ctx.beginPath(); ctx.moveTo(W+1,y+.5); ctx.lineTo(W+(metro?12:6),y+.5); ctx.stroke();
|
||
if(metro && cm>0){
|
||
ctx.fillStyle='#8A8F98';
|
||
ctx.fillText((cm/100)+' m', W+14, y+3);
|
||
}
|
||
}
|
||
// borda da folha
|
||
ctx.strokeStyle='#B4BAC5'; ctx.lineWidth=1;
|
||
ctx.strokeRect(.5,.5,W-1,H-1);
|
||
// cota da largura, no topo
|
||
ctx.fillStyle='#FFFFFFDD'; ctx.fillRect(0,0,W,18);
|
||
ctx.strokeStyle='#8A8F98'; ctx.lineWidth=1;
|
||
ctx.beginPath();
|
||
ctx.moveTo(8,9); ctx.lineTo(W-8,9);
|
||
ctx.moveTo(8,5); ctx.lineTo(8,13);
|
||
ctx.moveTo(W-8,5); ctx.lineTo(W-8,13);
|
||
ctx.stroke();
|
||
const t=String(larguraCm).replace('.',',')+' cm';
|
||
ctx.font='600 10px "Roboto", sans-serif'; ctx.textAlign='center';
|
||
const tw=ctx.measureText(t).width;
|
||
ctx.fillStyle='#FAFAF8'; ctx.fillRect(W/2-tw/2-6,2,tw+12,14);
|
||
ctx.fillStyle='#5A6570'; ctx.fillText(t,W/2,13);
|
||
ctx.restore();
|
||
}
|
||
|
||
const LOGO_URL='https://cdn.vnda.com.br/dropstar/2025/12/17/logo-header-15125700-16129080.png?v=1766009286';
|
||
const logoImg=new Image(); logoImg.crossOrigin='anonymous'; logoImg.src=LOGO_URL;
|
||
function marcaDagua(ctx,w,h){
|
||
ctx.save(); ctx.globalAlpha=.14;
|
||
const passo=Math.max(90,w/2.1);
|
||
ctx.translate(w/2,h/2); ctx.rotate(-Math.PI/7); ctx.translate(-w/2,-h/2);
|
||
if(logoImg.complete && logoImg.naturalWidth){
|
||
const lw=Math.max(70,w/3.4), lh=lw*(logoImg.naturalHeight/logoImg.naturalWidth);
|
||
for(let y=-h;y<h*2;y+=passo) for(let x=-w;x<w*2;x+=passo*1.7)
|
||
ctx.drawImage(logoImg,x,y,lw,lh);
|
||
}else{
|
||
ctx.fillStyle='#111';
|
||
ctx.font='700 '+Math.max(13,Math.round(w/13))+'px Inter, sans-serif'; ctx.textAlign='center';
|
||
for(let y=-h;y<h*2;y+=passo) for(let x=-w;x<w*2;x+=passo*1.5) ctx.fillText('PRÉVIA',x,y);
|
||
}
|
||
ctx.restore();
|
||
}
|
||
const CEL=GAP_CM; // célula da máscara, em cm = a folga de 5 mm
|
||
// Dilata 1 célula para a direita e para baixo. Como toda peça é dilatada igual,
|
||
// duas vizinhas ficam separadas por exatamente 1 célula — os 5 mm da regra.
|
||
function dilatar(bruto,cw,ch,cheias){
|
||
const cw2=cw+1, ch2=ch+1;
|
||
const out=new Uint8Array(cw2*ch2);
|
||
for(let y=0;y<ch;y++) for(let x=0;x<cw;x++){
|
||
if(!bruto[y*cw+x]) continue;
|
||
out[y*cw2+x]=1; out[y*cw2+x+1]=1; out[(y+1)*cw2+x]=1; out[(y+1)*cw2+x+1]=1;
|
||
}
|
||
return {cw:cw2,ch:ch2,bits:out,cheias}; // cheias = área de arte, sem a folga
|
||
}
|
||
function mascara(img,w,h,rot,esp=false){
|
||
const cw=Math.max(1,Math.ceil(w/CEL)), ch=Math.max(1,Math.ceil(h/CEL));
|
||
const cv=document.createElement('canvas');
|
||
cv.width=cw; cv.height=ch;
|
||
const ctx=cv.getContext('2d',{willReadFrequently:true});
|
||
let bruto, cheias;
|
||
if(!img){ // sem imagem: caixa cheia
|
||
bruto=new Uint8Array(cw*ch).fill(1); cheias=cw*ch;
|
||
return dilatar(bruto,cw,ch,cheias);
|
||
}
|
||
ctx.save();
|
||
ctx.translate(cw/2,ch/2);
|
||
ctx.rotate(rot*Math.PI/180);
|
||
if(esp) ctx.scale(-1,1);
|
||
const dw=rot%180===90?ch:cw, dh=rot%180===90?cw:ch;
|
||
ctx.drawImage(img,-dw/2,-dh/2,dw,dh);
|
||
ctx.restore();
|
||
const d=ctx.getImageData(0,0,cw,ch).data;
|
||
bruto=new Uint8Array(cw*ch); cheias=0;
|
||
for(let i=0,j=3;i<bruto.length;i++,j+=4){ bruto[i] = d[j]>16 ? 1 : 0; cheias+=bruto[i]; }
|
||
return dilatar(bruto,cw,ch,cheias);
|
||
}
|
||
|
||
// Encaixe pela forma, como o motor do servidor: mapa de ocupação real,
|
||
// máscara por arte e candidatos numa grade ao longo da largura.
|
||
// pecas em centímetros: {w,h,img}. W é a largura do filme em cm.
|
||
function encaixar(pecas,W){
|
||
const cols=Math.ceil(W/CEL)+1; // +1 = a coluna de folga da dilatação
|
||
let linhas=0; const mapa=[];
|
||
function garantir(ate){ while(linhas<ate){ mapa.push(new Uint8Array(cols)); linhas++; } }
|
||
|
||
function colide(m,cx,cy){
|
||
if(cx<0||cy<0||cx+m.cw>cols) return true;
|
||
for(let y=0;y<m.ch;y++){
|
||
const gy=cy+y;
|
||
if(gy>=linhas) continue; // vazio abaixo do que já existe
|
||
const L=mapa[gy], off=y*m.cw;
|
||
for(let x=0;x<m.cw;x++)
|
||
if(m.bits[off+x] && L[cx+x]) return true;
|
||
}
|
||
return false;
|
||
}
|
||
function ocupar(m,cx,cy){
|
||
garantir(cy+m.ch);
|
||
for(let y=0;y<m.ch;y++){
|
||
const L=mapa[cy+y], off=y*m.cw;
|
||
for(let x=0;x<m.cw;x++) if(m.bits[off+x]) L[cx+x]=1;
|
||
}
|
||
}
|
||
|
||
const postas=[];
|
||
if(pecas.some(p=>!Number.isFinite(p.w) || p.w<=0 || p.w>W))
|
||
throw new RangeError('A largura solicitada não cabe no filme.');
|
||
const ordem=[...pecas].sort((a,b)=>(b.w*b.h)-(a.w*a.h));
|
||
|
||
ordem.forEach(p=>{
|
||
const oris=[{w:p.w,h:p.h,rot:0}];
|
||
if(!p.mPronta && !p.travado && Math.abs(p.w-p.h)>1 && p.h<=W) oris.push({w:p.h,h:p.w,rot:90});
|
||
|
||
let melhor=null;
|
||
oris.forEach(o=>{
|
||
if(o.w>W) return;
|
||
// a máscara segue a medida da orientação escolhida · girada, largura e altura trocam
|
||
const m = (p.mPronta && o.rot===0) ? p.mPronta : mascara(p.img, o.w, o.h,
|
||
o.rot+(p.a?.giro||0), p.a?.esp);
|
||
const xs=new Set([0]), ys=new Set([0]);
|
||
postas.forEach(q=>{ xs.add(q.cx+q.m.cw); xs.add(q.cx); ys.add(q.cy+q.m.ch); ys.add(q.cy); });
|
||
const passoX=Math.max(1,Math.round(cols/34));
|
||
for(let x=0;x+m.cw<=cols;x+=passoX) xs.add(x);
|
||
xs.add(cols-m.cw);
|
||
const passoY=Math.max(1,Math.round(Math.max(linhas,1)/50));
|
||
for(let y=0;y<=linhas;y+=passoY) ys.add(y);
|
||
const XS=[...xs].filter(x=>x>=0 && x+m.cw<=cols && x*CEL+o.w<=W+0.01).sort((a,b)=>a-b);
|
||
const YS=[...ys].filter(y=>y>=0).sort((a,b)=>a-b);
|
||
|
||
for(const cy of YS){
|
||
if(melhor && cy*CEL > melhor.y + CEL) break;
|
||
for(const cx of XS){
|
||
if(cx*CEL + o.w > W + 0.01) continue; // não deixa a peça sair do filme
|
||
if(colide(m,cx,cy)) continue;
|
||
const cand={cx,cy,m,x:cx*CEL,y:cy*CEL,w:o.w,h:o.h,rot:o.rot,ref:p};
|
||
// menor y, depois menor x · em empate, mantém a orientação original.
|
||
// Desempatar por largura gira tudo, e texto deitado na prévia parece erro.
|
||
const ganha = !melhor || cand.y<melhor.y ||
|
||
(cand.y===melhor.y && cand.x<melhor.x) ||
|
||
(cand.y===melhor.y && cand.x===melhor.x && cand.rot===0 && melhor.rot!==0);
|
||
if(ganha) melhor=cand;
|
||
break;
|
||
}
|
||
}
|
||
});
|
||
if(!melhor){
|
||
const m=mascara(p.img,p.w,p.h,p.a?.giro||0,p.a?.esp);
|
||
melhor={cx:0,cy:linhas,m,x:0,y:linhas*CEL,w:p.w,h:p.h,rot:0,ref:p};
|
||
}
|
||
// a folga só existe entre peças, não é folha cobrada
|
||
ocupar(melhor.m,melhor.cx,melhor.cy);
|
||
postas.push(melhor);
|
||
});
|
||
|
||
const altura=Math.max(...postas.map(p=>p.y+p.h),1);
|
||
return {pos:postas, altura};
|
||
}
|
||
|
||
function desenhaMontagem(area,lista,mts,W,fora,aoTerminar){
|
||
const versao=area.montagemVersao=(area.montagemVersao||0)+1;
|
||
const filme=larguraFilme(), PX_CM=W/filme;
|
||
const itens=lista.map((a,sourceIndex)=>({...a,sourceIndex}));
|
||
if(fora) fora.innerHTML='';
|
||
if(!itens.length){
|
||
area.innerHTML='<div class="semmont"><b>A montagem aparece aqui</b>'+
|
||
'<span>informe a largura de cada arte e a folha se desenha sozinha</span></div>';
|
||
if(aoTerminar) aoTerminar({alturaCm:0, uso:0, girou:0});
|
||
return;
|
||
}
|
||
|
||
Promise.all(itens.map(a=>carregarImagem(a.f).then(img=>({a,img})))).then(imagens=>{
|
||
if(area.montagemVersao!==versao) return;
|
||
const cargas=imagens.flatMap(c=>Array.from({length:c.a.q||1},(_,copyIndex)=>({...c,copyIndex})));
|
||
cargas.forEach(c=>{
|
||
c.w = c.a.cm; // o motor trabalha em centímetros
|
||
c.h = c.w * (c.img ? (c.a.giro? c.img.width/c.img.height : c.img.height/c.img.width) : 1);
|
||
c.travado = !!c.a.giro; // giro do cliente manda no encaixe
|
||
});
|
||
const enc=encaixar(cargas,filme);
|
||
const alturaCm=enc.altura;
|
||
const pos=enc.pos.map(p=>({...p, x:p.x*PX_CM, y:p.y*PX_CM, w:p.w*PX_CM, h:p.h*PX_CM}));
|
||
const altura=alturaCm*PX_CM;
|
||
const usado=Math.max(altura,10);
|
||
const REG=34;
|
||
const cv=document.createElement('canvas');
|
||
cv.width=W+REG; cv.height=Math.round(usado);
|
||
const ctx=cv.getContext('2d');
|
||
ctx.fillStyle='#fff'; ctx.fillRect(0,0,cv.width,cv.height);
|
||
const pal=['#C3CEDD','#B7A9C8','#A9B7C8','#A8BFA9','#C8C0A0','#CBB6B6'];
|
||
let girou=0;
|
||
pos.forEach((p,j)=>{
|
||
const c=p.ref;
|
||
if(p.rot===90) girou++;
|
||
ctx.save();
|
||
const giro = (p.rot===90?90:0) + (c.a && c.a.giro? 90:0);
|
||
ctx.translate(p.x+p.w/2, p.y+p.h/2);
|
||
ctx.rotate(giro*Math.PI/180);
|
||
if(c.a && c.a.esp) ctx.scale(-1,1);
|
||
const dw = giro%180===90 ? p.h : p.w, dh = giro%180===90 ? p.w : p.h;
|
||
if(c.img) ctx.drawImage(c.img,-dw/2,-dh/2,dw,dh);
|
||
else{ ctx.fillStyle=pal[j%pal.length]; ctx.fillRect(-dw/2,-dh/2,dw,dh); }
|
||
ctx.restore();
|
||
if(!c.img){
|
||
ctx.fillStyle='#5A6570'; ctx.font='11px "Roboto", sans-serif'; ctx.textAlign='center';
|
||
ctx.fillText(c.a.f.name.split('.').pop().toUpperCase(),p.x+p.w/2,p.y+p.h/2+4);
|
||
}
|
||
});
|
||
molduraFolha(ctx,W,usado,filme,alturaCm/100);
|
||
marcaDagua(ctx,W,cv.height);
|
||
area.innerHTML=''; area.appendChild(cv);
|
||
|
||
// O que virou arte é a área pintada, não a soma das caixas: com encaixe por forma
|
||
// as caixas se sobrepõem de propósito e a soma delas passa de 100%.
|
||
const areaArteCm=enc.pos.reduce((s,p)=>
|
||
s + (p.m && p.m.cheias!=null ? p.m.cheias*CEL*CEL : p.w*p.h), 0);
|
||
const uso=Math.max(1,Math.min(100,
|
||
Math.round(areaArteCm/(filme*Math.max(alturaCm,0.1))*100)));
|
||
const el=document.createElement('div');
|
||
el.className = uso>=70? 'usoBom' : 'usoRuim';
|
||
el.innerHTML = (uso>=70
|
||
? '<b>'+uso+'% da folha virou arte</b> bom aproveitamento'
|
||
: '<b>'+uso+'% da folha virou arte</b> dá para melhorar: artes de larguras parecidas '+
|
||
'se encaixam melhor lado a lado')
|
||
+ (girou? ' · <b style="display:inline">'+girou+
|
||
(girou>1?' artes giradas':' arte girada')+' 90°</b> para caber melhor':'');
|
||
(fora||area).appendChild(el);
|
||
if(aoTerminar) aoTerminar({alturaCm, uso, girou,
|
||
placements:enc.pos.map(p=>({source_index:p.ref.a.sourceIndex,
|
||
copy_index:p.ref.copyIndex,x_cm:p.x,y_cm:p.y,
|
||
width_cm:+p.w.toFixed(4),length_cm:+p.h.toFixed(4),
|
||
rotation_degrees:(p.rot+(p.ref.a.giro||0))%360,
|
||
mirrored:!!p.ref.a.esp}))});
|
||
});
|
||
}
|
||
|
||
function previaArtes(){ desenhaMontagem($('pArea'), artes, metros, 560); }
|
||
|
||
// montagem ao vivo, ao lado da fila · redesenha 140 ms depois da ultima mexida
|
||
let tMont=null;
|
||
function previaAoVivo(){
|
||
clearTimeout(tMont);
|
||
montagemLayout=null;
|
||
$('vArea').montagemVersao=($('vArea').montagemVersao||0)+1;
|
||
if(ehFolha()){
|
||
$('vUso').innerHTML='';
|
||
const tot=folhaTotalM();
|
||
$('vMt').textContent = tot>0 ? fmtM(cobrar(tot))+' m' : '—';
|
||
const medidas=folhas.filter(x=>x.med);
|
||
// Sheets still being read show a placeholder; a sheet printed N times is
|
||
// shown N times (up to REPETE_MAX, then a count).
|
||
const REPETE_MAX=6;
|
||
const previews=folhas.filter(x=>x.previewSrc || (x.pct!=null && x.med && x.med.grande));
|
||
if(previews.length){
|
||
const painel=document.createElement('div'); painel.className='folhaPrevias';
|
||
previews.forEach((x,index)=>{
|
||
const figura=document.createElement('figure'); figura.className='folhaPrevia';
|
||
const legenda=document.createElement('figcaption');
|
||
const vezes=Math.max(1,x.rep||1);
|
||
legenda.textContent=(previews.length>1 ? (index+1)+'. ' : '')+x.f.name+
|
||
(x.med ? ' · '+n1(x.med.larg)+' × '+n1(x.med.alt)+' cm' : '')+(vezes>1 ? ' · '+vezes+' cópias' : '');
|
||
if(!x.previewSrc){
|
||
const esqueleto=document.createElement('div'); esqueleto.className='skel folhaSkel';
|
||
esqueleto.style.aspectRatio=x.med ? x.med.larg+' / '+Math.min(x.med.alt,x.med.larg*4) : '1 / 2';
|
||
esqueleto.append(Object.assign(document.createElement('span'),{textContent:'Gerando a prévia da folha…'}));
|
||
figura.append(esqueleto,legenda); painel.append(figura); return;
|
||
}
|
||
const pilha=document.createElement('div'); pilha.className='folhaPilha';
|
||
for(let k=0;k<Math.min(vezes,REPETE_MAX);k++){
|
||
const imagem=new Image(); imagem.src=x.previewSrc; imagem.alt=k? '' : x.f.name;
|
||
imagem.style.maxHeight=Math.floor(520/Math.min(vezes,REPETE_MAX))+'px'; pilha.append(imagem);
|
||
}
|
||
if(vezes>REPETE_MAX) pilha.append(Object.assign(document.createElement('div'),
|
||
{className:'folhaMais', textContent:'+ '+(vezes-REPETE_MAX)+' cópia'+(vezes-REPETE_MAX>1?'s':'')}));
|
||
figura.append(pilha,legenda); painel.append(figura);
|
||
});
|
||
$('vArea').replaceChildren(painel);
|
||
}else{
|
||
$('vArea').innerHTML = medidas.length
|
||
? '<div class="semmont"><b>'+(medidas.length>1
|
||
? medidas.length+' folhas · '+fmtM(tot)+' m'
|
||
: n1(medidas[0].med.larg)+' × '+n1(medidas[0].med.alt)+' cm')+'</b>'+
|
||
'<span>'+(medidas.length>1? 'medidas lidas de cada arquivo' : medidas[0].med.fonte)+
|
||
' · vão para a máquina do jeito que você montou</span></div>'
|
||
: '<div class="semmont"><b>Sua folha aparece aqui</b>'+
|
||
'<span>a medida é lida do próprio arquivo, não do peso dele</span></div>';
|
||
}
|
||
return;
|
||
}
|
||
tMont=setTimeout(()=>{
|
||
// o produto pode ter sido fechado nesses 140 ms (item foi para o carrinho)
|
||
if(!modo) return;
|
||
const prontas=artes.filter(a=>a.cm>0 && a.cm<=larguraFilme() && a.src);
|
||
const W=Math.round(300*ZOOMS[zoomI]);
|
||
$('vArea').classList.toggle('ampliado', zoomI>0);
|
||
desenhaMontagem($('vArea'), prontas, 0, W, $('vUso'), r=>{
|
||
montagemCm = r.alturaCm; // altura real da folha montada
|
||
montagemLayout=r.placements ? {height_cm:+r.alturaCm.toFixed(4),
|
||
placements:r.placements} : null;
|
||
$('vMt').textContent = r.alturaCm? fmtM(cobrar(r.alturaCm/100))+' m' : '—';
|
||
resumoArtes(); // o resumo lê a mesma folha
|
||
agendaAvaliacao(); // a nota só sai com a metragem pronta
|
||
});
|
||
$('vArea').scrollTop=0;
|
||
},140);
|
||
}
|
||
|
||
function motivoNota(){
|
||
if(!nota) return 'sem nota ainda · a conferência roda na sala antes de imprimir';
|
||
if(!ehFolha()){
|
||
const ruins=artes.filter(a=>a.cm>0 && dpiDe(a)<300);
|
||
if(!ruins.length) return 'nota '+nota+' · todas as artes em 300 DPI ou mais';
|
||
const pior=ruins.reduce((p,a)=>dpiDe(a)<dpiDe(p)?a:p);
|
||
return 'nota '+nota+' · '+ruins.length+(ruins.length>1?' artes abaixo':' arte abaixo')+
|
||
' de 300 DPI · a menor é "'+pior.f.name+'" com '+
|
||
Math.round(dpiDe(pior))+' DPI em '+pior.cm.toFixed(1).replace('.',',')+' cm';
|
||
}
|
||
return nota>=90 ? 'nota '+nota+' · resolução ótima em toda a folha'
|
||
: 'nota '+nota+' · a resolução é o único ponto — o resto corrigimos por você';
|
||
}
|
||
function previa(){
|
||
// Na folha pronta o painel não tem o que mostrar: a folha vem fechada, ninguém
|
||
// olhou dentro dela. Largura e metragem — o que de fato medimos — já aparecem
|
||
// na coluna ao lado e no carrinho.
|
||
if(ehFolha()){ $('prev').classList.remove('on'); return; }
|
||
const cob=cobrar(metros), sobra=+(cob-metros).toFixed(2);
|
||
$('pMt').innerHTML=fmtM(cob)+'<small> m</small>';
|
||
$('pSub').textContent='folha montada por nós com as artes que você enviou';
|
||
const linhas=[
|
||
['var(--verde)','✓','Largura',larguraFilme()+' cm · dentro do padrão da máquina'],
|
||
['var(--verde)','✓','Espaço entre artes','5 mm garantidos'],
|
||
[nota>=75?'var(--verde)':'var(--laranja)', nota>=75?'✓':'!','Qualidade da folha',motivoNota()],
|
||
['var(--verde)','✓','Metragem proporcional',
|
||
'sua folha tem '+fmtM(metros)+' m e você paga '+fmtM(cob)+
|
||
' m · arredondamos só até os 10 cm mais próximos'],
|
||
];
|
||
linhas.push(['var(--verde)','+','Identificação do pedido',
|
||
'aplicamos seu nome e o número do pedido no fim da folha · por nossa conta']);
|
||
$('pInfo').innerHTML=linhas.map(l=>
|
||
'<div class="li"><span class="c" style="background:'+l[0]+
|
||
(l[0]==='var(--laranja)'?';color:#241703':'')+'">'+l[1]+'</span>'+
|
||
'<div><b>'+escapeHTML(l[2])+'</b><span>'+escapeHTML(l[3])+'</span></div></div>').join('');
|
||
$('prev').classList.add('on');
|
||
$('pArea').innerHTML='<div class="carregando">montando a prévia…</div>';
|
||
try{ previaArtes(); }
|
||
catch(e){ $('pArea').innerHTML='<div class="semprev"><b>Prévia indisponível</b>'+
|
||
'O arquivo será processado normalmente.</div>'; }
|
||
}
|