diff options
| author | Craig Jennings <c@cjennings.net> | 2026-07-12 22:40:22 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-07-12 22:40:22 -0500 |
| commit | 066bdac1c195fa27d4b71f2ba53ee9265ee7c833 (patch) | |
| tree | 451f613874801c291b9fb692c8ed6da3d731dce9 /docs/prototypes/panel-widget-gallery.html | |
| parent | 4064de53a9abfa7620d9d7e3f95e867ba0bf54e3 (diff) | |
| download | archsetup-066bdac1c195fa27d4b71f2ba53ee9265ee7c833.tar.gz archsetup-066bdac1c195fa27d4b71f2ba53ee9265ee7c833.zip | |
refactor(gallery): extract indicators R10, R11, R25, R26, R30, R31 into GW builders
Diffstat (limited to 'docs/prototypes/panel-widget-gallery.html')
| -rw-r--r-- | docs/prototypes/panel-widget-gallery.html | 226 |
1 files changed, 14 insertions, 212 deletions
diff --git a/docs/prototypes/panel-widget-gallery.html b/docs/prototypes/panel-widget-gallery.html index 2d7bcb9..f81b60b 100644 --- a/docs/prototypes/panel-widget-gallery.html +++ b/docs/prototypes/panel-widget-gallery.html @@ -1850,22 +1850,22 @@ card(I,'N28','Patch-bay jack field', (st,rd)=>GW.patchBay(st,{onChange:(v,t)=>rd(t)}), '<b>routing shown as patches.</b> A grid of jacks with cables between connected pairs. Click one jack then another to add/remove a cable.'); card(I,'R10','Data matrix readout', - `<svg id="dmx" class="rsvg press" viewBox="0 0 190 74" width="190" height="74"></svg>`, + (st,rd)=>GW.dataMatrix(st,{onChange:(v,t)=>rd(t)}), '<b>a page of amber fields.</b> The console data block — several labeled values on one lit matrix. Click to cycle pages; readout names the page. After a cockpit data readout.'); card(I,'R11','Warning flag window', - `<svg id="wflag" class="rsvg press" viewBox="0 0 120 64" width="120" height="64"></svg>`, + (st,rd)=>GW.warningFlag(st,{onChange:(v,t)=>rd(t)}), '<b>the mechanical alarm flag.</b> A striped barber-pole slides into a window when the condition trips — not a lamp, a flag. Click to trip and clear it. After the VIB flag on an altimeter.'); card(I,'R25','Fourteen-segment display', - `<svg id="seg14" class="rsvg press" viewBox="0 0 130 54" width="130" height="54"></svg>`, + (st,rd)=>GW.seg14(st,{onChange:(v,t)=>rd(t)}), '<b>segments that spell.</b> The starburst alphanumeric — diagonals and split bars let it write words, not just digits. Click to cycle the word. After a pedal preset display.'); card(I,'R26','Response graph', - `<svg id="rgraph" class="rsvg" viewBox="0 0 190 110" width="190" height="110"></svg>`, + (st,rd)=>GW.responseGraph(st,{onChange:(v,t)=>rd(t)}), '<b>a curve on labeled axes.</b> Log frequency across, dB up the side, and the amber peak is yours to place — drag it anywhere on the plot. After the response display of a mastering processor.'); card(I,'R30','Telegraph indicator', - `<svg id="telind" class="rsvg press" viewBox="0 0 110 110" width="110" height="110"></svg>`, + (st,rd)=>GW.telegraphIndicator(st,{onChange:(v,t)=>rd(t)}), '<b>state on a pie of sectors.</b> The pointer and its little flag name the active state, engine-telegraph style. Click to step the state. After an electric indicator dial.'); card(I,'R31','Radar sweep', - `<svg id="radar" class="rsvg press" viewBox="0 0 130 130" width="130" height="130"></svg>`, + (st,rd)=>GW.radarSweep(st,{onChange:(v,t)=>rd(t)}), '<b>the rotating scan.</b> A sweep beam circles the bearing ring, contacts bloom as it passes and fade after. Click to mark the current bearing. After a radar PPI scope.'); card(I,'R35','Day-date disc calendar', `<svg id="daydate" class="rsvg press" viewBox="0 0 130 130" width="130" height="130"></svg>`, @@ -1916,215 +1916,17 @@ function tickMcVu(){const a=lvl();const target=Math.min(1.02,a*1.12); /* R07-R09 extracted to widgets.js (GW.*) */ -/* R10 data matrix readout */ -const DMX_PAGES=[ - ['SYS',()=>['CPU 42 MEM 61','DSK 58 TMP 47C','ARCH 6.18 LTS']], - ['NET',()=>['WIFI @HYATT 300M','VPN UP DNS OK','BT 2 PAIRED']], - ['TIME',()=>{const d=new Date(),p=n=>String(n).padStart(2,'0'); - return [`${d.getFullYear()}-${p(d.getMonth()+1)}-${p(d.getDate())}`, - `${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}`, - 'UP 14D 06:12'];}]]; -let dmxI=0,dmxLines=[]; -(function(){const s=$('dmx'); - const defs=svgEl(s,'defs',{}); - const fl=svgEl(defs,'filter',{id:'dmxGlow',x:'-30%',y:'-30%',width:'160%',height:'160%'}); - svgEl(fl,'feGaussianBlur',{in:'SourceGraphic',stdDeviation:1.1}); - const bg=svgEl(defs,'linearGradient',{id:'dmxBg',x1:0,y1:0,x2:0,y2:1}); - svgEl(bg,'stop',{offset:'0','stop-color':'var(--scr-bg1,#140d06)'}); - svgEl(bg,'stop',{offset:'1','stop-color':'var(--scr-bg2,#0a0705)'}); - svgEl(s,'rect',{x:1,y:1,width:188,height:72,rx:5,fill:'url(#dmxBg)',stroke:'#2c261d'}); - for(let r=0;r<3;r++){ - const glow=svgEl(s,'text',{x:12,y:24+r*18,'font-size':9,'letter-spacing':'.15em', - 'font-family':'var(--mono)',fill:'var(--scr-hi,var(--gold-hi))',opacity:.6,filter:'url(#dmxGlow)'}); - const crisp=svgEl(s,'text',{x:12,y:24+r*18,'font-size':9,'letter-spacing':'.15em', - 'font-family':'var(--mono)',fill:'var(--scr-hi,var(--gold-hi))'}); - dmxLines.push([glow,crisp]);} - $('dmx').onclick=()=>setDmx((dmxI+1)%DMX_PAGES.length);})(); -function setDmx(i){dmxI=i;const [name,rowsFn]=DMX_PAGES[i]; - rowsFn().forEach((txt,r)=>{dmxLines[r][0].textContent=txt;dmxLines[r][1].textContent=txt;}); - setRd('R10','page '+name);} -setDmx(0); -if(!matchMedia('(prefers-reduced-motion: reduce)').matches) - setInterval(()=>{if(DMX_PAGES[dmxI][0]==='TIME')setDmx(dmxI);},1000); - -/* R11 warning flag window */ -let flagOn=false,flagStripes=null; -(function(){const s=$('wflag'); - const defs=svgEl(s,'defs',{}); - const pat=svgEl(defs,'pattern',{id:'barber',width:10,height:10,patternUnits:'userSpaceOnUse', - patternTransform:'rotate(45)'}); - svgEl(pat,'rect',{x:0,y:0,width:10,height:10,fill:'#17130c'}); - svgEl(pat,'rect',{x:0,y:0,width:5,height:10,fill:'var(--gold)'}); - const clip=svgEl(defs,'clipPath',{id:'flagWin'}); - svgEl(clip,'rect',{x:14,y:20,width:56,height:24}); - svgEl(s,'rect',{x:11,y:17,width:62,height:30,rx:3,fill:'#0a0908',stroke:'#2c261d','stroke-width':2}); - const g=svgEl(s,'g',{'clip-path':'url(#flagWin)'}); - flagStripes=svgEl(g,'rect',{x:14,y:20,width:56,height:24,fill:'url(#barber)'}); - flagStripes.style.transition='transform .18s';flagStripes.style.transform='translateX(-58px)'; - svgEl(s,'text',{x:92,y:35,'text-anchor':'middle','font-size':7,'letter-spacing':'.14em', - 'font-family':'var(--mono)',fill:'var(--steel)'}).textContent='VIB'; - $('wflag').onclick=()=>setFlag(!flagOn);})(); -function setFlag(on){flagOn=on;flagStripes.style.transform=on?'translateX(0)':'translateX(-58px)'; - setRd('R11',on?'FLAG':'clear');} -setFlag(false); +/* R10, R11 extracted to widgets.js (GW.*) */ + /* R13, R17 extracted to widgets.js (GW.*) */ -/* R30 telegraph indicator: the pointer names the state on labeled sectors */ -const TELIND_STATES=['OK','TEST','BUSY','STOP','ATTN','FAULT']; -let telI=0,telPtr=null; -(function(){const s=$('telind'),cx=55,cy=55,N=TELIND_STATES.length; - svgEl(s,'circle',{cx,cy,r:50,fill:'#171412',stroke:'#060505','stroke-width':2}); - svgEl(s,'circle',{cx,cy,r:43,fill:'var(--cream)',stroke:'#b7b29a','stroke-width':1}); - TELIND_STATES.forEach((st,i)=>{ - const a=i*360/N-90+180/N; - const [lx1,ly1]=polar(cx,cy,9,i*360/N),[lx2,ly2]=polar(cx,cy,43,i*360/N); - svgEl(s,'line',{x1:lx1,y1:ly1,x2:lx2,y2:ly2,stroke:'#2b2418','stroke-width':1}); - const g=svgEl(s,'g',{transform:`rotate(${a+90},${cx},${cy})`}); - svgEl(g,'text',{x:cx,y:cy-28,'text-anchor':'middle','font-size':7,'font-weight':700, - 'font-family':'var(--mono)',fill:'#2b2418'}).textContent=st;}); - telPtr=svgEl(s,'g',{});telPtr.style.transition='transform .18s';telPtr.style.transformOrigin=`${cx}px ${cy}px`; - svgEl(telPtr,'polygon',{points:`${cx-2.5},${cy} ${cx},${cy-38} ${cx+2.5},${cy}`,fill:'var(--fail)',stroke:'#7a2a1a','stroke-width':.5}); - svgEl(telPtr,'rect',{x:cx+1,y:cy-16,width:10,height:7,rx:1,fill:'var(--gold)',stroke:'#7d5c16','stroke-width':.6}); - svgEl(s,'circle',{cx,cy,r:8,fill:'#171412',stroke:'#000'}); - $('telind').onclick=()=>setTelind((telI+1)%TELIND_STATES.length);})(); -function setTelind(i){telI=i;const N=TELIND_STATES.length; - telPtr.style.transform=`rotate(${i*360/N+180/N}deg)`; - setRd('R30',TELIND_STATES[i]);} -setTelind(0); - -/* R31 radar sweep: rotating beam, blooming contacts, click to mark */ -let radarA=210,radarSweep=null,radarBlips=[],radarMark=null; -const RADAR_CONTACTS=[[60,.55],[205,.7],[318,.4]]; -(function(){const s=$('radar'),cx=65,cy=65; - const defs=svgEl(s,'defs',{}); - const clip=svgEl(defs,'clipPath',{id:'radarClip'}); - svgEl(clip,'circle',{cx,cy,r:46}); - svgEl(s,'circle',{cx,cy,r:62,fill:'#1a1714',stroke:'#060505','stroke-width':2}); - svgEl(s,'circle',{cx,cy,r:52,fill:'var(--scr-bg1,#120b05)',stroke:'var(--scr-brd,#3a2a12)','stroke-width':1}); - for(let d=0;d<360;d+=30){const a=d; - const [x1,y1]=polar(cx,cy,51,a),[x2,y2]=polar(cx,cy,47,a); - svgEl(s,'line',{x1,y1,x2,y2,stroke:'var(--scr-ink,var(--gold))','stroke-width':1,opacity:.8}); - const g=svgEl(s,'g',{transform:`rotate(${a},${cx},${cy})`}); - svgEl(g,'text',{x:cx,y:cy-47.5,'text-anchor':'middle','font-size':4.6,'font-family':'var(--mono)', - fill:'var(--scr-ink,var(--gold))',opacity:.9}).textContent=String(d).padStart(3,'0');} - for(let d=0;d<360;d+=10){if(d%30===0)continue; - const [x1,y1]=polar(cx,cy,51,d),[x2,y2]=polar(cx,cy,49,d); - svgEl(s,'line',{x1,y1,x2,y2,stroke:'var(--scr-ink,var(--gold))','stroke-width':.6,opacity:.5});} - const g=svgEl(s,'g',{'clip-path':'url(#radarClip)'}); - svgEl(g,'circle',{cx,cy,r:46,fill:'var(--scr-bg2,#0d0803)'}); - for(const r of [15,30,45]) - svgEl(g,'circle',{cx,cy,r,fill:'none',stroke:'var(--scr-ink,var(--gold))','stroke-opacity':.18,'stroke-width':.7}); - radarSweep=svgEl(g,'g',{}); - for(let t=0;t<5;t++){const a0=-14+t*2.8,a1=a0+2.8; - const [x1,y1]=polar(cx,cy,46,a0),[x2,y2]=polar(cx,cy,46,a1); - svgEl(radarSweep,'path',{d:`M ${cx} ${cy} L ${x1} ${y1} A 46 46 0 0 1 ${x2} ${y2} Z`, - fill:'var(--scr-ink,var(--gold))','fill-opacity':(0.04+t*0.045).toFixed(3)});} - svgEl(radarSweep,'line',{x1:cx,y1:cy,x2:cx,y2:cy-46,stroke:'var(--scr-hi,var(--gold-hi))','stroke-width':1.4, - transform:`rotate(0,${cx},${cy})`,opacity:.95}); - RADAR_CONTACTS.forEach(([bd,rf])=>{const [x,y]=polar(cx,cy,46*rf,bd); - radarBlips.push(svgEl(g,'circle',{cx:x,cy:y,r:2.2,fill:'var(--scr-hi,var(--gold-hi))',opacity:0}));}); - svgEl(s,'circle',{cx,cy,r:3,fill:'var(--scr-ink,var(--gold))',opacity:.8}); - radarMark=svgEl(s,'text',{x:cx,y:124,'text-anchor':'middle','font-size':6,'letter-spacing':'.12em', - 'font-family':'var(--mono)',fill:'var(--steel)'}); - radarMark.textContent='BEARING —'; - $('radar').onclick=()=>{radarMark.textContent='MARK '+String(Math.round(radarA)%360).padStart(3,'0'); - setRd('R31','mark '+String(Math.round(radarA)%360).padStart(3,'0'));};})(); -function tickRadar(){radarA=(radarA+2.6)%360; - radarSweep.setAttribute('transform',`rotate(${radarA},65,65)`); - RADAR_CONTACTS.forEach(([bd],i)=>{ - let d=(radarA-bd+360)%360; // degrees since beam passed - radarBlips[i].setAttribute('opacity',d<200?Math.max(0,.95-d/200):0);}); - radarMark.textContent=radarMark.textContent.startsWith('MARK')?radarMark.textContent: - 'BEARING '+String(Math.round(radarA)%360).padStart(3,'0');} -tickRadar();setRd('R31','sweeping'); -if(!matchMedia('(prefers-reduced-motion: reduce)').matches)setInterval(tickRadar,50); - -/* R25 fourteen-segment display: the starburst that spells */ -const SEG14_WORDS=['ZOOM','ECHO','TAPE','MOOD','HALL','COMP']; -const SEG14_MAP={A:['a','b','c','e','f','g1','g2'],C:['a','d','e','f'], - D:['a','b','c','d','i','l'],E:['a','d','e','f','g1','g2'],H:['b','c','e','f','g1','g2'], - L:['d','e','f'],M:['b','c','e','f','h','j'],O:['a','b','c','d','e','f'], - P:['a','b','e','f','g1','g2'],T:['a','i','l'],Z:['a','d','j','k']}; -let seg14I=0,seg14Cells=[]; -(function(){const s=$('seg14'); - svgEl(s,'rect',{x:1,y:1,width:128,height:52,rx:5,fill:'#0a0f08',stroke:'#1c2a16','stroke-width':2}); - // segment shapes in a 22x36 local box (x0,y0 top-left) - const TH=2.6,W=22,H=36,mid=H/2; - const segs={ - a:[[2,0],[W-2,0],[W-4,TH],[4,TH]], - d:[[2,H],[W-2,H],[W-4,H-TH],[4,H-TH]], - f:[[0,2],[TH,4],[TH,mid-2],[0,mid-1]], - e:[[0,H-2],[TH,H-4],[TH,mid+2],[0,mid+1]], - b:[[W,2],[W-TH,4],[W-TH,mid-2],[W,mid-1]], - c:[[W,H-2],[W-TH,H-4],[W-TH,mid+2],[W,mid+1]], - g1:[[2,mid],[4,mid-TH/2],[W/2-1,mid-TH/2],[W/2-1,mid+TH/2],[4,mid+TH/2]], - g2:[[W-2,mid],[W-4,mid-TH/2],[W/2+1,mid-TH/2],[W/2+1,mid+TH/2],[W-4,mid+TH/2]], - i:[[W/2-TH/2,3],[W/2+TH/2,3],[W/2+TH/2,mid-2],[W/2-TH/2,mid-2]], - l:[[W/2-TH/2,H-3],[W/2+TH/2,H-3],[W/2+TH/2,mid+2],[W/2-TH/2,mid+2]], - h:[[3,3],[5.5,3],[W/2-2,mid-3],[W/2-4.5,mid-3]], - j:[[W-3,3],[W-5.5,3],[W/2+2,mid-3],[W/2+4.5,mid-3]], - k:[[3,H-3],[5.5,H-3],[W/2-2,mid+3],[W/2-4.5,mid+3]], - m:[[W-3,H-3],[W-5.5,H-3],[W/2+2,mid+3],[W/2+4.5,mid+3]]}; - for(let d=0;d<4;d++){const x0=13+d*28,y0=9,cell={}; - for(const k in segs){ - cell[k]=svgEl(s,'polygon',{points:segs[k].map(p=>`${x0+p[0]},${y0+p[1]}`).join(' '), - fill:'var(--sevoff)'});} - seg14Cells.push(cell);} - $('seg14').onclick=()=>setSeg14((seg14I+1)%SEG14_WORDS.length);})(); -function setSeg14(i){seg14I=i;const word=SEG14_WORDS[i].padEnd(4,' '); - seg14Cells.forEach((cell,d)=>{const lit=SEG14_MAP[word[d]]||[]; - for(const k in cell){const on=lit.includes(k); - cell[k].setAttribute('fill',on?'var(--sevgrn)':'var(--sevoff)'); - cell[k].setAttribute('style',on?'filter:drop-shadow(0 0 2.5px rgba(87,211,87,.6))':'');}}); - setRd('R25',SEG14_WORDS[i]);} -setSeg14(0); - -/* R26 response graph: log-frequency axes, a draggable amber peak */ -const RG={x0:30,x1:182,y0:8,y1:86,fLo:Math.log10(32),fHi:Math.log10(16000),db:12}; -let rgFc=1200,rgGain=6.5,rgCurve=null,rgGlowLine=null,rgHandle=null; -(function(){const s=$('rgraph'); - svgEl(s,'rect',{x:1,y:1,width:188,height:108,rx:5,fill:'#0d1410',stroke:'#22301f','stroke-width':2}); - const FREQS=[32,64,128,250,500,1000,2000,4000,8000,16000]; - FREQS.forEach(f=>{const x=RG.x0+(Math.log10(f)-RG.fLo)/(RG.fHi-RG.fLo)*(RG.x1-RG.x0); - svgEl(s,'line',{x1:x,y1:RG.y0,x2:x,y2:RG.y1,stroke:'#22301f','stroke-width':.6}); - svgEl(s,'text',{x,y:RG.y1+9,'text-anchor':'middle','font-size':4.8,'font-family':'var(--mono)', - fill:'var(--steel)'}).textContent=f<1000?f:(f/1000)+'k';}); - for(const db of [12,6,0,-6,-12]){const y=RG.y0+(RG.db-db)/(2*RG.db)*(RG.y1-RG.y0); - svgEl(s,'line',{x1:RG.x0,y1:y,x2:RG.x1,y2:y,stroke:'#22301f','stroke-width':db===0?1:.6}); - svgEl(s,'text',{x:RG.x0-4,y:y+2,'text-anchor':'end','font-size':4.8,'font-family':'var(--mono)', - fill:'var(--steel)'}).textContent=(db>0?'+':'')+db;} - rgGlowLine=svgEl(s,'polyline',{points:'',fill:'none',stroke:'var(--gold-hi)','stroke-width':3, - opacity:.35,filter:'url(#avGlow)'}); - rgCurve=svgEl(s,'polyline',{points:'',fill:'none',stroke:'var(--gold)','stroke-width':1.6}); - rgHandle=svgEl(s,'circle',{r:4,fill:'var(--gold-hi)',stroke:'#7d5c16','stroke-width':1}); - rgHandle.style.cursor='move'; - // 2D drag: the handle (and the plot) place the peak in both axes at once - s.style.touchAction='none'; - s.addEventListener('pointerdown',e=>{s.setPointerCapture(e.pointerId); - const move=ev=>{const r=s.getBoundingClientRect(),sx=190/r.width,sy=110/r.height; - const px=(ev.clientX-r.left)*sx,py=(ev.clientY-r.top)*sy; - const lf=RG.fLo+Math.max(0,Math.min(1,(px-RG.x0)/(RG.x1-RG.x0)))*(RG.fHi-RG.fLo); - const g=RG.db-Math.max(0,Math.min(1,(py-RG.y0)/(RG.y1-RG.y0)))*2*RG.db; - setRgraph(Math.pow(10,lf),g);}; - move(e); - const up=()=>{s.removeEventListener('pointermove',move);s.removeEventListener('pointerup',up);s.removeEventListener('pointercancel',up);}; - s.addEventListener('pointermove',move);s.addEventListener('pointerup',up);s.addEventListener('pointercancel',up); - e.preventDefault();});})(); -function setRgraph(fc,gain){rgFc=Math.max(32,Math.min(16000,fc));rgGain=Math.max(-12,Math.min(12,gain)); - const xOf=f=>RG.x0+(Math.log10(f)-RG.fLo)/(RG.fHi-RG.fLo)*(RG.x1-RG.x0); - const yOf=db=>RG.y0+(RG.db-db)/(2*RG.db)*(RG.y1-RG.y0); - const sigma=0.28;let pts=''; - for(let i=0;i<=76;i++){const lf=RG.fLo+i/76*(RG.fHi-RG.fLo); - const db=rgGain*Math.exp(-Math.pow(lf-Math.log10(rgFc),2)/(2*sigma*sigma)); - pts+=`${xOf(Math.pow(10,lf)).toFixed(1)},${yOf(db).toFixed(1)} `;} - rgCurve.setAttribute('points',pts.trim());rgGlowLine.setAttribute('points',pts.trim()); - rgHandle.setAttribute('cx',xOf(rgFc));rgHandle.setAttribute('cy',yOf(rgGain)); - const fLbl=rgFc<1000?Math.round(rgFc)+' Hz':(rgFc/1000).toFixed(1)+' kHz'; - setRd('R26',`${fLbl} · ${rgGain>=0?'+':''}${rgGain.toFixed(1)} dB`);} -setRgraph(1200,6.5); +/* R25, R26, R30, R31 extracted to widgets.js (GW.*) */ + + + /* ============ LIVE SIGNAL LOOPS ============ */ /* extracted meters: the page keeps the clock + demo signal, drives card handles */ @@ -2371,10 +2173,10 @@ let dkPos=0,dkCarry=0; /* ---- screen-family chips: first round, the clearly-screen widgets ---- Defaults match each widget's shipped color (var fallbacks), so no family is applied until a chip is clicked. The nixie stays chipless on purpose: neon is only ever orange, so alternates would be historically false. */ -screenChips('R10',$('dmx'),['amber','green','red','blue','vfd'],'amber'); +screenChips('R10',$('card-R10').gw.el,['amber','green','red','blue','vfd'],'amber'); screenChips('R17',$('card-R17').gw.el,['green','amber','red','blue','vfd'],'green'); screenChips('R19',$('card-R19').gw.el,['white','green','amber','blue','vfd'],'white'); -screenChips('R31',$('radar'),['amber','green','red','blue','vfd'],'amber'); +screenChips('R31',$('card-R31').gw.el,['amber','green','red','blue','vfd'],'amber'); screenChips('N11',$('card-N11').gw.el,['green','amber','red','blue','vfd'],'green'); BOOST.forEach(no=>{const rd=document.getElementById('rd-'+no); if(rd)rd.closest('.card').querySelector('.stagew').classList.add('boost');}); |
