by adom
0603 SMD Green LED · 3.2 V drop · 25 mA max
← Commit history
Footprint per the manufacturer's land pattern (redrawn), derived viewers/lbr/hero rebuilt, lbr-hover on both viewers, README.md replaces README.html, assembly animation in docs/assembly.md, chip outline and symbol options
17 files changed
+972−190
CHANGES.md+11IN-S63BTG-fpview.html+25−21IN-S63BTG-symview.html+4−1IN-S63BTG.adom-lbr.json+129−70IN-S63BTG.insertion.glbIN-S63BTG.kicad_mod+13−20IN-S63BTG.lbr+30−28README.md+68−50docs/assembly.html+445docs/assembly.md+7docs/datasheet.md+33footprint-variants/IN-S63BTG-RR25.kicad_mod+18footprint-variants/IN-S63BTG-SQ.kicad_mod+18footprint-variants/IN-S63BTG.kicad_mod+18footprint-variants/IN-S63BTG.variants.json+28in-s63btg-hero.glbin-s63btg-hero.overlay.json+125CHANGES.md+11@@ -82,3 +82,14 @@ Boards use the STEP, so the STEP itself now has the datasheet height: 1.1 mm -> - Fixed in pass 4: the STEP height is now the datasheet 0.55 mm. - `IN-S63BTG.adom-lbr.json` pads match the current `IN-S63BTG.kicad_mod` (0.9 x 1.0 mm). - The 0603 land pattern (`.kicad_mod`: 0.9 x 1.0 mm pads at +-0.8 mm) differs from the datasheet's recommended solder pattern (IN-S63BT p.1, Figure 1: 0.6 x 0.9 mm pads, 0.8 mm gap). Not changed; reported.++# IN-S63BTG: footprint, hover and README pass (2026-10-03)++John: footprints follow the manufacturer's land pattern; README.md replaces README.html; the assembly animation moves to a sub-readme.++- Footprint: redrawn. Land pattern from Inolux IN-S63BT series datasheet V1.2, p.1 (Recommended Solder Pattern). Pads 0.6 x 0.9 mm, centre to centre 1.4 mm, corner radius 0.1 mm.+- Rebuilt from the footprint: `IN-S63BTG-fpview.html` (and the lbr-hover bus on both viewers), `IN-S63BTG.lbr`, `IN-S63BTG.adom-lbr.json`, the hero GLB, and the pads / solder / silk in `IN-S63BTG.insertion.glb`.+- Etched STEP: kept.+- README.html removed (it repeated the native Symbol & Footprint viewers); README.md rewritten; `docs/assembly.md` + `docs/assembly.html` carry the pick-and-place animation; `docs/datasheet.md` the datasheet pages.+- New: `docs/assembly.html`, `docs/assembly.md`, `docs/datasheet.md`, `footprint-variants/IN-S63BTG-RR25.kicad_mod`, `footprint-variants/IN-S63BTG-SQ.kicad_mod`, `footprint-variants/IN-S63BTG.kicad_mod`, `footprint-variants/IN-S63BTG.variants.json`, `in-s63btg-hero.overlay.json`+- Removed: `README.html`
IN-S63BTG-fpview.html+25−21@@ -312,7 +312,7 @@ <div class="toolbar"> <span class="title">IN-S63BTG</span> <span class="badge">Footprint</span>- <span class="badge" style="background:rgba(248,81,73,0.15);color:#f85149;border-color:rgba(248,81,73,0.3);">Local Render</span>+ <div class="spacer"></div> <div class="btn-group"> <button onclick="zoomOut()">−</button>@@ -345,15 +345,16 @@ <div class="canvas-wrap" id="canvas-wrap"> <div class="canvas" id="canvas">- <svg xmlns="http://www.w3.org/2000/svg" viewBox="-2.5 -1.75 5.0 3.5">-<rect x="-2.5" y="-1.75" width="5.0" height="3.5" fill="#0d1117"/>-<rect x="-1.5" y="-0.75" width="3.0" height="1.5" fill="none" stroke="#FF26E2" stroke-width="0.05" stroke-dasharray="0.2,0.1"/>-<rect x="-0.8" y="-0.4" width="1.6" height="0.8" fill="none" stroke="#6e7681" stroke-width="0.1"/>-<line x1="-1.46" y1="-0.71" x2="0.8" y2="-0.71" stroke="#00cccc" stroke-width="0.12" stroke-linecap="round"/><line x1="-1.46" y1="0.71" x2="0.8" y2="0.71" stroke="#00cccc" stroke-width="0.12" stroke-linecap="round"/><line x1="-1.46" y1="-0.71" x2="-1.46" y2="0.71" stroke="#00cccc" stroke-width="0.12" stroke-linecap="round"/><rect x="-1.25" y="-0.5" width="0.9" height="1.0" fill="#C83434" stroke="#ef5350" stroke-width="0.04"/>-<text x="-0.8" y="0.0" text-anchor="middle" dominant-baseline="central" font-size="0.405" fill="#fff" font-family="sans-serif">1</text>-<rect x="0.35000000000000003" y="-0.5" width="0.9" height="1.0" fill="#C83434" stroke="#ef5350" stroke-width="0.04"/>-<text x="0.8" y="0.0" text-anchor="middle" dominant-baseline="central" font-size="0.405" fill="#fff" font-family="sans-serif">2</text>-<text x="2.2" y="1.45" text-anchor="end" font-size="0.250" fill="#484f58" font-family="sans-serif" font-style="italic">Local render — KiCad service unavailable</text>+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 4.5 3.4">+<rect x="0" y="0" width="4.5" height="3.4" fill="#0d1117"/>+<rect x="1" y="1" width="2.5" height="1.4" fill="none" stroke="#FF26E2" stroke-width="0.05" stroke-dasharray="0.2,0.1"/>+<rect x="1.45" y="1.3" width="1.6" height="0.8" fill="none" stroke="#6e7681" stroke-width="0.1"/>+<line x1="1.7" y1="1.3" x2="1.7" y2="2.1" stroke="#6e7681" stroke-width="0.1"/>+<line x1="1.09" y1="1.14" x2="3.05" y2="1.14" stroke="#00cccc" stroke-width="0.12" stroke-linecap="round"/><line x1="1.09" y1="2.26" x2="3.05" y2="2.26" stroke="#00cccc" stroke-width="0.12" stroke-linecap="round"/><line x1="1.09" y1="1.14" x2="1.09" y2="2.26" stroke="#00cccc" stroke-width="0.12" stroke-linecap="round"/>+<rect x="1.25" y="1.25" width="0.6" height="0.9" rx="0.1" ry="0.1" fill="#C83434" stroke="#ef5350" stroke-width="0.04"/>+<text x="1.55" y="1.7" text-anchor="middle" dominant-baseline="central" font-size="0.270" fill="#fff" font-family="sans-serif">1</text>+<rect x="2.65" y="1.25" width="0.6" height="0.9" rx="0.1" ry="0.1" fill="#C83434" stroke="#ef5350" stroke-width="0.04"/>+<text x="2.95" y="1.7" text-anchor="middle" dominant-baseline="central" font-size="0.270" fill="#fff" font-family="sans-serif">2</text> </svg> </div> <a class="edit-btn" href="https://coder.john-service-wiki-a054078430ce38e4.containers.adom.inc/proxy/8785/wiki/components/in-s63btg/edit?field=content" target="_blank" title="Suggest corrections on Adom Wiki">@@ -371,7 +372,7 @@ <div class="info-row"> - <div class="info-item"><span class="info-label">Desc</span><span class="info-value">Inolux Corporation · Top View SMD LED · 0603 (1.6 × 0.8mm) · InGaN</span></div><div class="info-item"><span class="info-label">Pads</span><span class="info-value">2</span></div><div class="info-item"><span class="info-label">Body</span><span class="info-value">1.6 × 0.8 mm</span></div><div class="info-item"><span class="info-label">Courtyard</span><span class="info-value">3.0 × 1.5 mm</span></div>+ <div class="info-item"><span class="info-label">Desc</span><span class="info-value">Land pattern: Inolux datasheet p.1</span></div><div class="info-item"><span class="info-label">Pads</span><span class="info-value">2 · 0.6 × 0.9 mm, r 0.1 mm</span></div><div class="info-item"><span class="info-label">Body</span><span class="info-value">1.6 × 0.8 mm</span></div><div class="info-item"><span class="info-label">Courtyard</span><span class="info-value">2.5 × 1.4 mm</span></div> </div> <div class="info-divider"></div> <div class="coord-row">@@ -380,13 +381,13 @@ </div> <script>- const pads = [{"number": "1", "signal": "", "x": -0.8, "y": 0.0, "width": 0.9, "height": 1.0, "shape": "roundrect", "mountType": "smd", "rotation": 0, "desc": ""}, {"number": "2", "signal": "", "x": 0.8, "y": 0.0, "width": 0.9, "height": 1.0, "shape": "roundrect", "mountType": "smd", "rotation": 0, "desc": ""}];- const svgW = 5.0;- const svgH = 3.5;- const svgVbX = -2.5;- const svgVbY = -1.75;- const offsetX = 2.5;- const offsetY = 1.75;+ const pads = [{"number": "1", "signal": "", "x": -0.7, "y": 0.0, "width": 0.6, "height": 0.9, "shape": "roundrect", "mountType": "smd", "rotation": 0, "desc": ""}, {"number": "2", "signal": "", "x": 0.7, "y": 0.0, "width": 0.6, "height": 0.9, "shape": "roundrect", "mountType": "smd", "rotation": 0, "desc": ""}];+ const svgW = 4.5;+ const svgH = 3.4;+ const svgVbX = 0;+ const svgVbY = 0;+ const offsetX = 2.25;+ const offsetY = 1.7; const datasheetUrl = ""; const _partName = ""; const _fpName = "IN-S63BTG";@@ -500,8 +501,8 @@ const spanH = availH > 0 ? availH : 0; const stepX = nCols > 1 ? spanW / (nCols - 1) : 0; const stepY = nRows > 1 ? spanH / (nRows - 1) : 0;- const startX = -spanW / 2;- const startY = -spanH / 2;+ const startX = nCols > 1 ? -spanW / 2 : 0;+ const startY = nRows > 1 ? -spanH / 2 : 0; const cosR = Math.cos(rot); const sinR = Math.sin(rot); @@ -682,7 +683,10 @@ tooltip.style.top = ty + 'px'; } + /* lbr-hover-bus v1 */ window.addEventListener('message',function(e){var d=e.data||{};if(d.type!=='lbr-hover')return;clearHighlight();if(d.pin==null||!svgEl)return;svgEl.querySelectorAll('rect[data-pad]').forEach(function(r){if(r.getAttribute('data-pad')===String(d.pin)){r.setAttribute('stroke','#00b8b1');r.setAttribute('stroke-width','0.12');r.setAttribute('fill','rgba(0,184,177,0.2)');highlightedRects.push(r);}});}); function showPadTooltip(x, y, pad, rect) {+ try{parent.postMessage({type:'lbr-hover',pin:String(pad.number)},'*')}catch(_){}+ if (stickyPad !== null) return; // suppress hover while sticky clearHighlight();@@ -697,7 +701,7 @@ positionTooltip(x, y); } - function hidePadTooltip(rect) {+ function hidePadTooltip(rect) { try{parent.postMessage({type:'lbr-hover',pin:null},'*')}catch(_){} if (stickyPad !== null) return; // don't hide while sticky tooltip.classList.remove('visible'); clearHighlight();
IN-S63BTG-symview.html+4−1@@ -760,7 +760,10 @@ L6.2042 7.3994 } } + /* lbr-hover-bus v1 */ window.addEventListener('message',function(e){var d=e.data||{};if(d.type!=='lbr-hover')return;window.__lbrBus=true;try{if(d.pin==null)clearHighlight();else{var p=(typeof pins!=='undefined'?pins:[]).find(function(x){return String(x.number)===String(d.pin)});if(p)highlightPin(p);else clearHighlight();}}finally{window.__lbrBus=false;}}); function highlightPin(pin) {+ if(!window.__lbrBus)try{parent.postMessage({type:'lbr-hover',pin:String(pin.number)},'*')}catch(_){}+ clearHighlight(); // IC symbols: stroked-text groups [pin.name, pin.number].forEach(label => {@@ -840,7 +843,7 @@ L6.2042 7.3994 positionTooltip(x, y); } - function hideTooltip() {+ function hideTooltip() { if(!window.__lbrBus)try{parent.postMessage({type:'lbr-hover',pin:null},'*')}catch(_){} if (stickyPin) return; tooltip.classList.remove('visible'); clearHighlight();
IN-S63BTG.adom-lbr.json+129−70@@ -1,7 +1,7 @@ { "schema_version": 2, "mpn": "IN-S63BTG",- "manufacturer": "",+ "manufacturer": "Inolux", "package": "", "value": "", "category": "",@@ -11,18 +11,20 @@ { "number": "1", "name": "K",- "x": -150,- "y": 0,+ "x": 0,+ "y": -150, "length": 100,- "rotation": 0+ "rotation": 90,+ "electrical_type": "passive" }, { "number": "2", "name": "A",- "x": 150,- "y": 0,+ "x": 0,+ "y": 150, "length": 100,- "rotation": 180+ "rotation": 270,+ "electrical_type": "passive" } ], "body": null,@@ -31,24 +33,24 @@ "kind": "polyline", "points": [ [- -120.0,- -30.0+ 30.0,+ -120.0 ], [- -180.0,- -90.0+ 90.0,+ -180.0 ], [- -150.0,- -90.0+ 90.0,+ -150.0 ], [- -180.0,- -90.0+ 90.0,+ -180.0 ], [- -180.0,- -60.0+ 60.0,+ -180.0 ] ], "width": 0.0@@ -57,24 +59,24 @@ "kind": "polyline", "points": [ [- -70.0,- -30.0+ 30.0,+ -70.0 ], [- -130.0,- -90.0+ 90.0,+ -130.0 ], [- -100.0,- -90.0+ 90.0,+ -100.0 ], [- -130.0,- -90.0+ 90.0,+ -130.0 ], [- -130.0,- -60.0+ 60.0,+ -130.0 ] ], "width": 0.0@@ -83,12 +85,12 @@ "kind": "polyline", "points": [ [- -50.0,- 0.0+ 0.0,+ -50.0 ], [- 50.0,- 0.0+ 0.0,+ 50.0 ] ], "width": 0.0@@ -97,12 +99,12 @@ "kind": "polyline", "points": [ [- -50.0,+ 50.0, -50.0 ], [ -50.0,- 50.0+ -50.0 ] ], "width": 10.0@@ -112,19 +114,19 @@ "points": [ [ 50.0,- -50.0+ 50.0 ], [- 50.0,+ -50.0, 50.0 ], [- -50.0,- 0.0+ 0.0,+ -50.0 ], [ 50.0,- -50.0+ 50.0 ] ], "width": 10.0@@ -132,7 +134,53 @@ ], "designator_prefix": "D", "footprint": "IN-S63BTG",- "parameters": [],+ "parameters": [+ {+ "name": "Value",+ "value": "IN-S63BTG",+ "visible": true+ },+ {+ "name": "Datasheet",+ "value": "https://www.inolux-corp.com/datasheet/SMDLED/Mono%20Color%20Top%20View/IN-S63BT%20Series_V1.2.pdf",+ "visible": false+ },+ {+ "name": "Description",+ "value": "Inolux IN-S63BTG green 0603 top-view SMD LED, 527 nm dominant, 3.2 V typ at 20 mA, 560 mcd typ, 25 mA max",+ "visible": false+ },+ {+ "name": "Manufacturer",+ "value": "Inolux",+ "visible": false+ },+ {+ "name": "MPN",+ "value": "IN-S63BTG",+ "visible": false+ },+ {+ "name": "Adom Wiki",+ "value": "https://wiki.adom.inc/adom/in-s63btg",+ "visible": false+ },+ {+ "name": "ki_keywords",+ "value": "LED diode",+ "visible": false+ },+ {+ "name": "ki_fp_filters",+ "value": "LED* LED_SMD:* LED_THT:*",+ "visible": false+ },+ {+ "name": "Manufacturer Part Number",+ "value": "IN-S63BTG",+ "visible": false+ }+ ], "pin_numbers_hidden": true, "pin_names_hidden": true },@@ -141,20 +189,20 @@ "pads": [ { "number": "1",- "x_mm": -0.8,+ "x_mm": -0.7, "y_mm": 0.0,- "w_mm": 0.9,- "h_mm": 1.0,+ "w_mm": 0.6,+ "h_mm": 0.9, "drill_mm": 0.0, "rotation": 0.0, "shape": "roundrect" }, { "number": "2",- "x_mm": 0.8,+ "x_mm": 0.7, "y_mm": 0.0,- "w_mm": 0.9,- "h_mm": 1.0,+ "w_mm": 0.6,+ "h_mm": 0.9, "drill_mm": 0.0, "rotation": 0.0, "shape": "roundrect"@@ -162,24 +210,13 @@ ], "graphics": [ {- "kind": "rect",- "layer": {- "role": "courtyard"- },- "x1": -1.5,- "y1": -0.75,- "x2": 1.5,- "y2": 0.75,- "width": 0.05- },- {- "kind": "rect",+ "kind": "line", "layer": { "role": "fab" },- "x1": -0.8,+ "x1": -0.55, "y1": -0.4,- "x2": 0.8,+ "x2": -0.55, "y2": 0.4, "width": 0.1 },@@ -188,10 +225,10 @@ "layer": { "role": "silk" },- "x1": -1.46,- "y1": -0.71,+ "x1": -1.16,+ "y1": -0.56, "x2": 0.8,- "y2": -0.71,+ "y2": -0.56, "width": 0.12 }, {@@ -199,10 +236,10 @@ "layer": { "role": "silk" },- "x1": -1.46,- "y1": 0.71,+ "x1": -1.16,+ "y1": 0.56, "x2": 0.8,- "y2": 0.71,+ "y2": 0.56, "width": 0.12 }, {@@ -210,11 +247,33 @@ "layer": { "role": "silk" },- "x1": -1.46,- "y1": -0.71,- "x2": -1.46,- "y2": 0.71,+ "x1": -1.16,+ "y1": -0.56,+ "x2": -1.16,+ "y2": 0.56, "width": 0.12+ },+ {+ "kind": "rect",+ "layer": {+ "role": "courtyard"+ },+ "x1": -1.25,+ "y1": -0.7,+ "x2": 1.25,+ "y2": 0.7,+ "width": 0.05+ },+ {+ "kind": "rect",+ "layer": {+ "role": "fab"+ },+ "x1": -0.8,+ "y1": -0.4,+ "x2": 0.8,+ "y2": 0.4,+ "width": 0.1 } ] },@@ -231,4 +290,4 @@ "provenance": { "source": "kicad_import" }-}+}
IN-S63BTG.insertion.glb⋯ 1 unchanged line ⋯
IN-S63BTG.kicad_mod+13−20@@ -1,25 +1,18 @@ (footprint "IN-S63BTG" (version 20240108)- (generator "adom-footprint")+ (generator "adom-basic-parts-overhaul") (layer "F.Cu")- (descr "Inolux Corporation · Top View SMD LED · 0603 (1.6 × 0.8mm) · InGaN")+ (descr "Inolux Corporation IN-S63BTG, 0603. Land pattern from Inolux IN-S63BT series datasheet V1.2, p.1 (Recommended Solder Pattern); corners: datasheet silent; roundrect radius 0.1 mm = min(0.25 x smaller pad side, 0.1 mm), IPC-7351C rounded corners for paste release")+ (tags "0603") (attr smd)- (fp_rect (start -1.5 -0.75) (end 1.5 0.75)- (stroke (width 0.05) (type default)) (fill none) (layer "F.CrtYd"))- (fp_rect (start -0.8 -0.4) (end 0.8 0.4)- (stroke (width 0.1) (type default)) (fill none) (layer "F.Fab"))- (fp_line (start -1.46 -0.71) (end 0.8 -0.71)- (stroke (width 0.12) (type default)) (layer "F.SilkS"))- (fp_line (start -1.46 0.71) (end 0.8 0.71)- (stroke (width 0.12) (type default)) (layer "F.SilkS"))- (fp_line (start -1.46 -0.71) (end -1.46 0.71)- (stroke (width 0.12) (type default)) (layer "F.SilkS"))- (fp_text reference "REF**" (at 0 -2.8)- (layer "F.SilkS") (effects (font (size 1 1) (thickness 0.15))))- (fp_text value "IN-S63BTG" (at 0 2.8)- (layer "F.Fab") (effects (font (size 1 1) (thickness 0.15))))- (pad "1" smd roundrect (at -0.8 0) (size 0.9 1)- (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.25))- (pad "2" smd roundrect (at 0.8 0) (size 0.9 1)- (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.25))+ (fp_text reference "REF**" (at 0 -1.4) (layer "F.SilkS") (effects (font (size 1 1) (thickness 0.15))))+ (fp_text value "IN-S63BTG" (at 0 1.4) (layer "F.Fab") (effects (font (size 1 1) (thickness 0.15))))+ (fp_rect (start -1.25 -0.7) (end 1.25 0.7) (stroke (width 0.05) (type default)) (fill none) (layer "F.CrtYd"))+ (fp_rect (start -0.8 -0.4) (end 0.8 0.4) (stroke (width 0.1) (type default)) (fill none) (layer "F.Fab"))+ (fp_line (start -0.55 -0.4) (end -0.55 0.4) (stroke (width 0.1) (type default)) (layer "F.Fab"))+ (fp_line (start -1.16 -0.56) (end 0.8 -0.56) (stroke (width 0.12) (type default)) (layer "F.SilkS"))+ (fp_line (start -1.16 0.56) (end 0.8 0.56) (stroke (width 0.12) (type default)) (layer "F.SilkS"))+ (fp_line (start -1.16 -0.56) (end -1.16 0.56) (stroke (width 0.12) (type default)) (layer "F.SilkS"))+ (pad "1" smd roundrect (at -0.7 0) (size 0.6 0.9) (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.1667))+ (pad "2" smd roundrect (at 0.7 0) (size 0.6 0.9) (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.1667)) )
IN-S63BTG.lbr+30−28@@ -50,48 +50,49 @@ <layer number="98" name="Guide" color="6" fill="1" visible="yes" active="yes"/> </layers> <library>-<description>0603 SMD Green LED · 3.2 V drop · 25 mA max</description>+<description>Inolux IN-S63BTG green 0603 top-view SMD LED, 527 nm dominant, 3.2 V typ at 20 mA, 560 mcd typ, 25 mA max</description> <packages> <package name="IN-S63BTG">- <description>2 pads, 2.5 x 1.0 mm. Inolux Corporation · Top View SMD LED · 0603 (1.6 &times; 0.8mm) · InGaN</description>- <smd name="1" x="-0.8000" y="-0.0000" dx="0.9000" dy="1.0000" layer="1" roundness="50"/>- <smd name="2" x="0.8000" y="-0.0000" dx="0.9000" dy="1.0000" layer="1" roundness="50"/>- <wire x1="-1.4600" y1="0.7100" x2="0.8000" y2="0.7100" width="0.127" layer="21"/>- <wire x1="-1.4600" y1="-0.7100" x2="0.8000" y2="-0.7100" width="0.127" layer="21"/>- <wire x1="-1.4600" y1="0.7100" x2="-1.4600" y2="-0.7100" width="0.127" layer="21"/>+ <description>2 pads, 2.0 x 0.9 mm. Inolux Corporation IN-S63BTG, 0603. Land pattern from Inolux IN-S63BT series datasheet V1.2, p.1 (Recommended Solder Pattern); corners: datasheet silent; roundrect radius 0.1 mm = min(0.25 x smaller pad side, 0.1 mm), IPC-7351C rounded corners for paste release</description>+ <smd name="1" x="-0.7000" y="-0.0000" dx="0.6000" dy="0.9000" layer="1" roundness="33"/>+ <smd name="2" x="0.7000" y="-0.0000" dx="0.6000" dy="0.9000" layer="1" roundness="33"/> <wire x1="-0.8000" y1="0.4000" x2="0.8000" y2="0.4000" width="0.1000" layer="51"/> <wire x1="0.8000" y1="0.4000" x2="0.8000" y2="-0.4000" width="0.1000" layer="51"/> <wire x1="0.8000" y1="-0.4000" x2="-0.8000" y2="-0.4000" width="0.1000" layer="51"/> <wire x1="-0.8000" y1="-0.4000" x2="-0.8000" y2="0.4000" width="0.1000" layer="51"/>- <text x="0" y="1.300" size="1.27" layer="25" align="bottom-center">>NAME</text>- <text x="0" y="-1.100" size="1.27" layer="27" align="top-center">>VALUE</text>+ <wire x1="-0.5500" y1="0.4000" x2="-0.5500" y2="-0.4000" width="0.1000" layer="51"/>+ <wire x1="-1.1600" y1="0.5600" x2="0.8000" y2="0.5600" width="0.1200" layer="21"/>+ <wire x1="-1.1600" y1="-0.5600" x2="0.8000" y2="-0.5600" width="0.1200" layer="21"/>+ <wire x1="-1.1600" y1="0.5600" x2="-1.1600" y2="-0.5600" width="0.1200" layer="21"/>+ <text x="0" y="1.160" size="1.27" layer="25" align="bottom-center">>NAME</text>+ <text x="0" y="-1.160" size="1.27" layer="27" align="top-center">>VALUE</text> </package> </packages> <symbols> <symbol name="IN-S63BTG">- <description>0603 SMD Green LED · 3.2 V drop · 25 mA max</description>- <wire x1="-3.0480" y1="-0.7620" x2="-4.5720" y2="-2.2860" width="0.1524" layer="94"/>- <wire x1="-4.5720" y1="-2.2860" x2="-3.8100" y2="-2.2860" width="0.1524" layer="94"/>- <wire x1="-3.8100" y1="-2.2860" x2="-4.5720" y2="-2.2860" width="0.1524" layer="94"/>- <wire x1="-4.5720" y1="-2.2860" x2="-4.5720" y2="-1.5240" width="0.1524" layer="94"/>- <wire x1="-1.7780" y1="-0.7620" x2="-3.3020" y2="-2.2860" width="0.1524" layer="94"/>- <wire x1="-3.3020" y1="-2.2860" x2="-2.5400" y2="-2.2860" width="0.1524" layer="94"/>- <wire x1="-2.5400" y1="-2.2860" x2="-3.3020" y2="-2.2860" width="0.1524" layer="94"/>- <wire x1="-3.3020" y1="-2.2860" x2="-3.3020" y2="-1.5240" width="0.1524" layer="94"/>- <wire x1="-1.2700" y1="0.0000" x2="1.2700" y2="0.0000" width="0.1524" layer="94"/>- <wire x1="-1.2700" y1="-1.2700" x2="-1.2700" y2="1.2700" width="0.1524" layer="94"/>- <wire x1="1.2700" y1="-1.2700" x2="1.2700" y2="1.2700" width="0.1524" layer="94"/>- <wire x1="1.2700" y1="1.2700" x2="-1.2700" y2="0.0000" width="0.1524" layer="94"/>- <wire x1="-1.2700" y1="0.0000" x2="1.2700" y2="-1.2700" width="0.1524" layer="94"/>- <text x="0.0000" y="2.5400" size="1.27" layer="95" align="center">>NAME</text>- <text x="0.0000" y="-2.5400" size="1.27" layer="96" align="center">>VALUE</text>- <pin name="K" x="-3.81" y="0" length="short" direction="pas" visible="pad"/>- <pin name="A" x="3.81" y="0" length="short" direction="pas" rot="R180" visible="pad"/>+ <description>Inolux IN-S63BTG green 0603 top-view SMD LED, 527 nm dominant, 3.2 V typ at 20 mA, 560 mcd typ, 25 mA max</description>+ <wire x1="0.7620" y1="-3.0480" x2="2.2860" y2="-4.5720" width="0.1524" layer="94"/>+ <wire x1="2.2860" y1="-4.5720" x2="2.2860" y2="-3.8100" width="0.1524" layer="94"/>+ <wire x1="2.2860" y1="-3.8100" x2="2.2860" y2="-4.5720" width="0.1524" layer="94"/>+ <wire x1="2.2860" y1="-4.5720" x2="1.5240" y2="-4.5720" width="0.1524" layer="94"/>+ <wire x1="0.7620" y1="-1.7780" x2="2.2860" y2="-3.3020" width="0.1524" layer="94"/>+ <wire x1="2.2860" y1="-3.3020" x2="2.2860" y2="-2.5400" width="0.1524" layer="94"/>+ <wire x1="2.2860" y1="-2.5400" x2="2.2860" y2="-3.3020" width="0.1524" layer="94"/>+ <wire x1="2.2860" y1="-3.3020" x2="1.5240" y2="-3.3020" width="0.1524" layer="94"/>+ <wire x1="0.0000" y1="-1.2700" x2="0.0000" y2="1.2700" width="0.1524" layer="94"/>+ <wire x1="1.2700" y1="-1.2700" x2="-1.2700" y2="-1.2700" width="0.2540" layer="94"/>+ <wire x1="1.2700" y1="1.2700" x2="-1.2700" y2="1.2700" width="0.2540" layer="94"/>+ <wire x1="-1.2700" y1="1.2700" x2="0.0000" y2="-1.2700" width="0.2540" layer="94"/>+ <wire x1="0.0000" y1="-1.2700" x2="1.2700" y2="1.2700" width="0.2540" layer="94"/>+ <text x="0" y="10" size="1.27" layer="95" align="bottom-center">>NAME</text>+ <text x="0" y="-10" size="1.27" layer="96" align="top-center">>VALUE</text>+ <pin name="K" x="0" y="-3.81" length="short" direction="pas" rot="R90" visible="pad"/>+ <pin name="A" x="0" y="3.81" length="short" direction="pas" rot="R270" visible="pad"/> </symbol> </symbols> <devicesets> <deviceset name="IN-S63BTG" prefix="D">- <description>0603 SMD Green LED · 3.2 V drop · 25 mA max</description>+ <description>Inolux IN-S63BTG green 0603 top-view SMD LED, 527 nm dominant, 3.2 V typ at 20 mA, 560 mcd typ, 25 mA max</description> <gates> <gate name="G$1" symbol="IN-S63BTG" x="0" y="0"/> </gates>@@ -105,6 +106,7 @@ <technology name=""> <attribute name="MPN" value="IN-S63BTG" constant="no"/> <attribute name="MANUFACTURER" value="Inolux Corporation" constant="no"/>+ <attribute name="ADOM_WIKI" value="https://wiki.adom.inc/adom/in-s63btg" constant="no"/> </technology> </technologies> </device>
README.md+68−50@@ -1,67 +1,56 @@ # Green SMD LED 0603 - Inolux IN-S63BTG -0603 SMD Green LED · 3.2 V drop · 25 mA max+**Inolux Corporation IN-S63BTG**: 0603 SMD Green LED, 3.2 V drop, 25 mA max. An Adom Basic Part: Adom keeps it on reels for its pick-and-place line, so boards built with it draw on Adom stock. -> The page you see on the wiki is rendered from **`README.html`**, which takes precedence-> over this file. This copy is the plain-text source of record. `README.html` is generated-> by `gen/gen_page.py` in the rollout working tree (`~/project/basic-parts-rollout`).+## Key specs -## Summary+| Spec | Datasheet |+|---|---|+| 0603 top-view SMD LED in a clear-lens, PCB-type moulded package, 1.6 × 0.8 × 0.6 mm | p.1, p.9 |+| InGaN green emitter, dominant wavelength 527 nm, peak 530 nm, spectral width Δλ 35 nm | p.3, p.8 |+| Forward voltage 3.2 V typ at the 20 mA test current | p.3 |+| Luminous intensity 560 mcd typ at 20 mA, the brightest member of the series | p.3, p.8 |+| 120° viewing angle (2θ1/2) | p.3 |+| 25 mA max continuous forward current; 100 mA peak at 1/10 duty, 0.1 ms pulse | p.2 |+| 5 V max reverse voltage; 75 mW max power dissipation | p.2 |+| Operating −30 to +85 °C, storage −40 to +90 °C | p.2 |+| Moisture sensitive and ESD sensitive (InGaN), ships dry-packed in a sealed moisture-barrier anti-static bag | p.2, p.12 |+| Supplied on tape and reel, 4000 pcs per reel (EIA-481-1A conductive black carrier tape) | p.10, p.11 | -**Features** — every figure cited to the datasheet page it came from.+## Notes for designers -- 0603 top-view SMD LED in a clear-lens, PCB-type moulded package — 1.6 × 0.8 × 0.6 mm (p.1, p.9)-- InGaN green emitter — dominant wavelength 527 nm, peak 530 nm, spectral width Δλ 35 nm (p.3, p.8)-- Forward voltage 3.2 V typ at the 20 mA test current (p.3)-- Luminous intensity 560 mcd typ at 20 mA — the brightest member of the series (p.3, p.8)-- 120° viewing angle (2θ1/2) (p.3)-- 25 mA max continuous forward current; 100 mA peak at 1/10 duty, 0.1 ms pulse (p.2)-- 5 V max reverse voltage; 75 mW max power dissipation (p.2)-- Operating −30 to +85 °C, storage −40 to +90 °C (p.2)-- Moisture sensitive and ESD sensitive (InGaN) — ships dry-packed in a sealed moisture-barrier anti-static bag (p.2, p.12)-- Supplied on tape and reel, 4000 pcs per reel (EIA-481-1A conductive black carrier tape) (p.10, p.11)+IN-S63BTG is the green member of Inolux's IN-S63BT series: a low-profile 0603 top-view indicator LED in a clear, PCB-type moulded package. (p.1) The die is InGaN (p.8) at a dominant wavelength of 527 nm, and at 560 mcd typ it is the brightest part in the series at the 20 mA test point. (p.3) -**Brief.**+Forward voltage is 3.2 V typ at 20 mA (p.3), a 3.3 V rail leaves about 0.1 V of headroom, which is no way to set a current, so treat it as a 5 V-rail part: (5 − 3.2) / 0.02 = 90 Ω for the full 20 mA. Use a current-limiting resistor, the datasheet asks for one explicitly (p.13), and keep continuous current at or below 25 mA. (p.2) At 560 mcd, most status lights will run at a small fraction of the test current. -IN-S63BTG is the green member of Inolux's IN-S63BT series: a low-profile 0603 top-view indicator LED in a clear, PCB-type moulded package. (p.1) The die is InGaN (p.8) at a dominant wavelength of 527 nm, and at 560 mcd typ it is the brightest part in the series at the 20 mA test point. (p.3)+The 120° viewing angle (p.3) makes it a wide-angle panel indicator, reverse voltage is rated to only 5 V, (p.2) and InGaN chips are static-sensitive devices, ESD precautions apply in design and assembly. (p.2) -Forward voltage is 3.2 V typ at 20 mA (p.3) — a 3.3 V rail leaves about 0.1 V of headroom, which is no way to set a current, so treat it as a 5 V-rail part: (5 − 3.2) / 0.02 = 90 Ω for the full 20 mA. Use a current-limiting resistor — the datasheet asks for one explicitly (p.13) — and keep continuous current at or below 25 mA. (p.2) At 560 mcd, most status lights will run at a small fraction of the test current.+## Footprint -The 120° viewing angle (p.3) makes it a wide-angle panel indicator, reverse voltage is rated to only 5 V, (p.2) and InGaN chips are static-sensitive devices — ESD precautions apply in design and assembly. (p.2)+Redrawn from the datasheet land pattern (the previous pads were off by up to 0.5 mm). -## Schematic & Layout+Source: Land pattern from Inolux IN-S63BT series datasheet V1.2, p.1 (Recommended Solder Pattern). -Interactive symbol and footprint viewers, side by side, generated with-[`adom-symbol`](https://wiki.adom.inc/adom/adom-symbol) and-[`adom-footprint`](https://wiki.adom.inc/adom/adom-footprint) `embed`, inlined into-`README.html` as `srcdoc` (the wiki serves the README sandboxed without-`allow-same-origin`, so nested `src=` iframes cannot work).+| mm | Datasheet | KiCad standard (LED_0603_1608Metric) | Previous | This page |+|---|---|---|---|---|+| Pad length (along the part) | 0.6 | 0.875 | 0.9 | 0.6 |+| Pad width | 0.9 | 0.95 | 1 | 0.9 |+| Gap between pads | 0.8 | 0.7 | 0.7 | 0.8 |+| Centre to centre | 1.4 | 1.575 | 1.6 | 1.4 |+| Overall | 2 | 2.45 | 2.5 | 2 |+| Corner radius | not specified | 0.2188 (ratio 0.25) | 0.225 (ratio 0.25) | 0.1 (ratio 0.1667) | -## Datasheet+Corners: the datasheet drawing shows plain rectangles and says nothing about corners, so the pads are KiCad roundrects with the radius held to 0.25 x the smaller pad side and no more than 0.1 mm. IPC-7351C favours rounded SMD pad corners for cleaner paste release and to avoid stress points; capping the radius keeps the copper area within 1.59 % of a square-cornered pad. -**IN-S63BT series — Top View SMD LED 0603 PCB Type**, V1.2 revised 10 March 2022, Inolux Corporation.-Retrieved 13 August 2026 from [www.inolux-corp.com](https://www.inolux-corp.com/datasheet/SMDLED/Mono%20Color%20Top%20View/IN-S63BT%20Series_V1.2.pdf) — `md5 0a3f815d48308fe542a24a4a4ac7f0ce`.+Polarity: pad 1 = K (cathode, -X), pad 2 = A, matching the symbol (K = pin 1, A = pin 2) and the datasheet's cathode mark; the silkscreen bracket marks the cathode end. -The datasheet is the README's own final section — WebP page images in `ds/` under a-provenance header. The PDF itself is a **release asset**-(`/download/aravk/in-s63btg/1.0.0/IN-S63BTG-datasheet.pdf`), deliberately not a repo file: the-wiki auto-generates a duplicate native Datasheet section from any PDF anywhere in the-repo (recursive scan, no opt-out — measured 2026-08-10 on in-s42atr).+::adom-footprint-variants{src="/adom/in-s63btg/render/footprint-variants/IN-S63BTG.variants.json" heading="Pad corners: this footprint, square corners, KiCad default rounding"} -## Downloads+## Chip outline -| File | Description |-|------|-------------|-| [IN-S63BTG-datasheet.pdf](https://wiki.adom.inc/download/aravk/in-s63btg/1.0.0/IN-S63BTG-datasheet.pdf) | Datasheet — release asset |-| [IN-S63BTG.glb](/blob/component/in-s63btg/IN-S63BTG.glb) | 3D model (wiki viewer) |-| [IN-S63BTG.kicad_mod](/blob/component/in-s63btg/IN-S63BTG.kicad_mod) | KiCad Footprint |-| [IN-S63BTG.kicad_sym](/blob/component/in-s63btg/IN-S63BTG.kicad_sym) | KiCad Symbol: the standard LED symbol (the page default) |-| [IN-S63BTG-outline.kicad_sym](/blob/component/in-s63btg/IN-S63BTG-outline.kicad_sym) | KiCad Symbol with the 3D chip outline: the part's outline drawn small beside the LED symbol |-| viewers/symbol.html | Interactive viewer of the default symbol (`adom-symbol embed`); hovering a pin highlights it in the page's other viewers |-| [IN-S63BTG.lbr](/blob/component/in-s63btg/IN-S63BTG.lbr) | Fusion 360 / EAGLE library |-| [IN-S63BTG.step](/blob/component/in-s63btg/IN-S63BTG.step) | 3D STEP model with the lens in the LED colour (#54C487, dominant wavelength 527 nm) — default (0.55 mm tall, datasheet height; MPN etched on the side) |-| [IN-S63BTG-uncoloured.step](/blob/component/in-s63btg/IN-S63BTG-uncoloured.step) | Optional: the plain model (library colours, no mark), height-corrected to the datasheet 0.55 mm |-| [in-s63btg-hero.glb](/blob/component/in-s63btg/in-s63btg-hero.glb) | Wiki hero 3D: the coloured LED plus footprint reference art (pad outlines, silkscreen, K/A labels). Page viewer only, not for boards |+The outline symbol keeps the standard LED symbol (triangle, bar and emission arrows) and adds the part's 3D outline as a small grey drawing beside it, so a reader sees a small SMD LED, not a through-hole one. The outline is drawn from `IN-S63BTG.step` by Adom's OpenCascade service (hidden-line removal, iso view). The part is shown in the standard iso pose, pad 1 toward the viewer, so the side wall carrying the etched part number faces you: it shows in the outline exactly as on the 3D model, reading upright and left to right, and the top and the lens stay clear. The same outlines are cached here for reuse in other symbols and libraries:++::adom-chip-thumbnail{src="/adom/in-s63btg/render/artwork/IN-S63BTG-thumbs.json"} ## Symbol options @@ -69,8 +58,37 @@ The default symbol, `IN-S63BTG.kicad_sym` (the one in the Symbol & Footprint pan ::adom-symbol-variants{src="/adom/in-s63btg/render/page.json" mpn="IN-S63BTG"} -## Chip outline+## Ordering -The outline symbol keeps the standard LED symbol (triangle, bar and emission arrows) and adds the part's 3D outline as a small grey drawing beside it, so a reader sees a small SMD LED, not a through-hole one. The outline is drawn from `IN-S63BTG.step` by Adom's OpenCascade service (hidden-line removal, iso view). The part is shown in the standard iso pose, pad 1 toward the viewer, so the side wall carrying the etched part number faces you: it shows in the outline exactly as on the 3D model, reading upright and left to right, and the top and the lens stay clear. The same outlines are cached here for reuse in other symbols and libraries:+| | |+|---|---|+| MPN | `IN-S63BTG` |+| Manufacturer | Inolux Corporation |+| Adom stock | Adom Basic Part, stocked on reels for Adom's pick-and-place line; reel counts on [pnp-inventory](https://wiki.adom.inc/adom/pnp-inventory) |+| Other sources | [adom-parts-search](https://wiki.adom.inc/adom/adom-parts-search) compares Mouser, DigiKey and JLCPCB | -::adom-chip-thumbnail{src="/adom/in-s63btg/render/artwork/IN-S63BTG-thumbs.json"}+## Downloads++| File | What it is |+|---|---|+| [IN-S63BTG.kicad_sym](/blob/component/in-s63btg/IN-S63BTG.kicad_sym) | KiCad symbol (standard symbol, the page default) |+| [IN-S63BTG-outline.kicad_sym](/blob/component/in-s63btg/IN-S63BTG-outline.kicad_sym) | KiCad symbol with the 3D chip outline |+| [IN-S63BTG.kicad_mod](/blob/component/in-s63btg/IN-S63BTG.kicad_mod) | KiCad footprint (datasheet land pattern) |+| [IN-S63BTG.step](/blob/component/in-s63btg/IN-S63BTG.step) | 3D STEP with the part number laser-etched (default) |+| [IN-S63BTG-uncoloured.step](/blob/component/in-s63btg/IN-S63BTG-uncoloured.step) | 3D STEP before the colour and etch passes (the bare KiCad model) |+| [IN-S63BTG.glb](/blob/component/in-s63btg/IN-S63BTG.glb) | 3D GLB of the etched model (board use) |+| [IN-S63BTG.lbr](/blob/component/in-s63btg/IN-S63BTG.lbr) | Fusion 360 / EAGLE library |+| [IN-S63BTG.adom-lbr.json](/blob/component/in-s63btg/IN-S63BTG.adom-lbr.json) | adom-lbr part (converts to Altium, KiCad, EAGLE) |+| [IN-S63BTG-datasheet.pdf](https://wiki.adom.inc/download/aravk/in-s63btg/1.0.0/IN-S63BTG-datasheet.pdf) | Datasheet (release asset) |++## Provenance++- Datasheet: **IN-S63BT series, Top View SMD LED 0603 PCB Type**, V1.2 revised 10 March 2022, Inolux Corporation. [Manufacturer copy](https://www.inolux-corp.com/datasheet/SMDLED/Mono%20Color%20Top%20View/IN-S63BT%20Series_V1.2.pdf). `md5 0a3f815d48308fe542a24a4a4ac7f0ce`+- Footprint: Land pattern from Inolux IN-S63BT series datasheet V1.2, p.1 (Recommended Solder Pattern). Pads redrawn on 2026-10-03.+- 3D model and symbol: unchanged by the footprint pass; the etched STEP adds a flat virtual part-number mark (an identification aid, not the maker's marking).+- Earlier passes: [provenance/](provenance/) and [CHANGES.md](CHANGES.md).++## More++- [Datasheet pages](docs/datasheet.md): the 15 datasheet pages as images.+- [Assembly animation](docs/assembly.md): the part dropping onto its pads, and Adom's pick-and-place picking it from tape.
docs/assembly.htmladded+445@@ -0,0 +1,445 @@+<!doctype html>+<html lang="en">+<head>+<meta charset="utf-8">+<title>IN-S63BTG — Static & Pick-and-Place (Colby's viewer + additions)</title>+<meta name="viewport" content="width=device-width,initial-scale=1">+<style>+ :root{ --accent:#00b8b0; --panel:#161b22; --border:#30363d; }+ html,body{ margin:0; height:100%; overflow:hidden; background:#14171d; color:#e6edf3;+ font:13px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif; }+ /* Colby's viewer mounts into #app and fills the viewport; our chrome overlays it. */+ #app{ position:fixed; inset:0; }+ #app canvas{ width:100%; height:100%; display:block; outline:none; }++ header{ position:fixed; top:0; left:0; right:0; display:flex; align-items:center; gap:16px;+ padding:10px 16px; z-index:10; pointer-events:none; }+ header h1{ font-size:14px; font-weight:700; margin:0; pointer-events:auto;+ text-shadow:0 1px 3px #0009; }+ header .sub{ color:#a9b6c2; font-size:11px; }+ .seg{ margin-left:auto; display:flex; background:var(--panel); border:1px solid var(--border);+ border-radius:20px; padding:3px; pointer-events:auto; box-shadow:0 2px 8px #0006; }+ .seg button{ background:transparent; border:0; color:#c9d1d9; padding:6px 16px; border-radius:16px;+ font-size:12px; font-weight:600; cursor:pointer; font-family:inherit; }+ .seg button.on{ background:var(--accent); color:#04231f; }++ #legend{ position:fixed; top:112px; right:16px; z-index:10; background:var(--panel); border:1px solid var(--border);+ border-radius:8px; padding:8px 11px; font:11px 'JetBrains Mono',ui-monospace,monospace; color:#c9d1d9;+ display:none; min-width:150px; box-shadow:0 2px 8px #0006; }+ #legend.show{ display:block; }+ #legend .row{ display:flex; align-items:center; gap:7px; padding:2px 0; }+ #legend .sw{ width:11px; height:11px; border-radius:2px; display:inline-block; }++ .btn-row{ position:fixed; bottom:16px; left:50%; transform:translateX(-50%);+ display:flex; gap:8px; z-index:10; }+ .btn{ background:var(--panel); border:1px solid var(--border); color:#e6edf3; padding:6px 14px;+ border-radius:16px; font-size:12px; cursor:pointer; font-family:inherit; box-shadow:0 2px 8px #0006; }+ .btn:hover{ border-color:var(--accent); }+ .btn.on{ background:rgba(0,184,176,0.16); border-color:var(--accent); color:var(--accent); }+ #layer-menu{ position:fixed; bottom:56px; left:50%; transform:translateX(-50%); z-index:10; background:var(--panel);+ border:1px solid var(--border); border-radius:10px; padding:10px 14px; min-width:190px; display:none; box-shadow:0 2px 10px #0007; }+ #layer-menu.open{ display:block; }+ #layer-menu h2{ font-size:10px; letter-spacing:.08em; text-transform:uppercase; color:#8b949e; margin:0 0 8px; font-weight:600; }+ #layer-menu label{ display:flex; align-items:center; gap:8px; padding:4px 0;+ font:12px 'JetBrains Mono',ui-monospace,monospace; cursor:pointer; }+ #layer-menu label.disabled{ opacity:.4; cursor:not-allowed; }+ #layer-menu input{ accent-color:var(--accent); }+ #layer-menu .grp{ margin-top:6px; border-top:1px solid var(--border); padding-top:6px; }+ #status{ position:fixed; top:52px; left:16px; z-index:10; color:#a9b6c2;+ font:11px 'JetBrains Mono',ui-monospace,monospace; text-shadow:0 1px 3px #0009; }+</style>++<div id="app"></div>+<header>+ <h1>IN-S63BTG <span class="sub">· Static and pick-and-place · local</span></h1>+ <div class="seg">+ <button id="mode-static" class="on">Static</button>+ <button id="mode-pnp">Pick & Place</button>+ </div>+</header>+<div id="status">loading the 3D viewer</div>+<div id="legend">+ <div class="row"><span class="sw" style="background:#9fb4c8"></span> P&P nozzle (ghost)</div>+ <div class="row"><span class="sw" style="background:#bd964e"></span> Carrier tape (to datasheet)</div>+ <div class="row"><span class="sw" style="background:#d8d0c4"></span> LED in tape (real model)</div>+</div>+<div id="layer-menu"><h2>Layers</h2><div id="layer-list"></div></div>+<div class="btn-row">+ <button class="btn on" id="btn-ground">Ground</button>+ <button class="btn" id="btn-bottom">Bottom light</button>+ <button class="btn" id="btn-layers">Layers</button>+</div>++<!-- Colby/Kyle's ACTUAL shipped viewer bundle (window.Adom3DViewer). Unmodified. -->+<script>+(async () => {+ const statusEl = document.getElementById('status');++ // Wiki blobs render SANDBOXED (no allow-same-origin): localStorage/sessionStorage throw a+ // SecurityError that aborts the viewer's SceneBuilder (leaving no lights / IBL / shadows /+ // skybox). Shim both with no-ops BEFORE his bundle loads so his own init completes normally.+ for (const k of ['localStorage','sessionStorage']) {+ try { window[k] && window[k].getItem('x'); }+ catch (e) { try { Object.defineProperty(window, k, { configurable:true, value:{ getItem:()=>null, setItem:()=>{}, removeItem:()=>{}, clear:()=>{}, key:()=>null, length:0 } }); } catch(_) {} }+ }++ // Wiki blob storage serves .js as application/octet-stream + nosniff, so a <script src>+ // of the bundle is refused by the browser. Fetch it as text and inject it as an inline+ // script (which executes). Behaves the same when served locally.+ if (!window.Adom3DViewer) {+ try {+ const code = await (await fetch('https://wiki.adom.inc/blob/component/in-s63btg/adom-3d-viewer.min.js')).text();+ const s = document.createElement('script'); s.textContent = code; document.head.appendChild(s);+ } catch (e) { statusEl.textContent = 'viewer bundle fetch failed: ' + e.message; return; }+ }+ const V = window.Adom3DViewer;+ if (!V) { statusEl.textContent = 'Adom3DViewer bundle failed to load'; return; }+ const B = V.BABYLON; // his Babylon core instance+ try {++ // 1) His viewer — his camera, SpotLight+ShadowGenerator, studio IBL, skybox, view cube, axes.+ const viewer = V.init(document.getElementById('app'), { zUp: true, showViewCube: true, showGround: true });++ // 2) Load our composite through his pipeline (auto-framed + shadowed).+ await viewer.loadModel('https://wiki.adom.inc/blob/component/in-s63btg/IN-S63BTG.insertion.glb');+ const scene = viewer.getScene();+ scene.animationGroups.slice().forEach(g => g.dispose()); // we drive our own motion++ // Match Colby's CURRENT viewer EXACTLY (native /viewer/3d/, build ?v=20260717e). The shipped bundle+ // is older and differs two ways, both verified live against his native scene:+ // SKY — ships a flat grey (clearColor + skybox primaryColor 0.75, environmentIntensity 1.5) plus a+ // BackgroundSkybox mesh. His current build has NO skybox mesh: just clearColor = SKILL_BG_BOTTOM+ // (#2a3340) + environmentIntensity 1.0 + the studio env for PBR reflections.+ // GROUND — ships an opaque square shadowGround (the "grey rectangle"). His is the same square GroundMesh+ // + PBR groundMat (baseColor 0.15) but with a 256px radial-fade baseTexture + alpha 0.2+ // (ALPHABLEND), so it reads as a soft CIRCLE. We rebuild that fade texture here.+ const bgBot = new B.Color3(0.165, 0.200, 0.251); // SKILL_BG_BOTTOM = #2a3340+ const Color4 = scene.clearColor && scene.clearColor.constructor; // Color4 isn't on the bundle's B — harvest it+ let _groundFade = null;+ const groundFadeTex = () => { // his radial fade: opaque centre -> transparent rim+ if (_groundFade) return _groundFade;+ const t = new B.DynamicTexture('groundFadeTex', 256, scene, true);+ const c = t.getContext();+ const g = c.createRadialGradient(128,128,6, 128,128,128);+ g.addColorStop(0.0, 'rgba(255,255,255,1)');+ g.addColorStop(0.55,'rgba(255,255,255,0.6)');+ g.addColorStop(1.0, 'rgba(255,255,255,0)');+ c.fillStyle = g; c.fillRect(0,0,256,256); t.update(); t.hasAlpha = true;+ _groundFade = t; return t;+ };+ const matchColby = () => { // idempotent; also called after each re-frame+ if (Color4) scene.clearColor = new Color4(bgBot.r, bgBot.g, bgBot.b, 1);+ scene.environmentIntensity = 1.0;+ scene.meshes.filter(m => /^Background/.test(m.name)).forEach(m => m.setEnabled(false)); // no skybox, like his native+ const gnd = scene.getMeshByName('shadowGround');+ if (gnd && gnd.material) {+ const m = gnd.material;+ if (!(m.baseTexture && m.baseTexture.name === 'groundFadeTex')) {+ if ('baseTexture' in m) m.baseTexture = groundFadeTex();+ m.alpha = 0.2; m.transparencyMode = 2; m.backFaceCulling = false; // his soft ALPHABLEND circle+ }+ gnd.receiveShadows = true;+ }+ };+ matchColby();++ const led = scene.getNodeByName('IN-S63BTG');+ if (led) led.rotationQuaternion = null; // glTF sets a quaternion that would ignore rotation.z — use Euler+ const ledLit = scene.getNodeByName('LED_lit');+ const fovCone = scene.getNodeByName('fov_cone');+ const ptLight = scene.lights.find(l => l.getClassName && l.getClassName() === 'PointLight');+ const modelParent = (led && led.parent) || null; // share the model's coordinate space++ // Bottom-fill light: the shipped bundle exposes no setBottomLight() and builds no bottomLight,+ // so create our own (matching his design — a downward hemispheric that lights the part's+ // underside), using his Babylon instance via the existing hemi's constructor. Toggled by the button.+ let bottomFill = scene.getLightByName('bottomLight');+ if (!bottomFill) {+ const hemi = scene.getLightByName('light') || scene.lights.find(l => l.getClassName && l.getClassName() === 'HemisphericLight');+ if (hemi) {+ const HL = hemi.constructor;+ bottomFill = new HL('our_bottom_fill', new B.Vector3(0,0,-1), scene);+ bottomFill.diffuse = new B.Color3(1,1,1); bottomFill.groundColor = new B.Color3(0.5,0.5,0.5);+ bottomFill.intensity = 0;+ }+ }++ // Replicate his loadModel shadow step (ThreeDViewer.svelte ~159-166): register the loaded+ // model as shadow casters/receivers. (His current source does this; the shipped bundle is+ // older, so we do it here — same effect, no change to his code.) refreshRate=1 keeps the+ // cast shadow updating as the LED animates.+ const sg = viewer.getShadowGenerator && viewer.getShadowGenerator();+ // Shadows for EVERYTHING: every content mesh casts AND receives; the ground only receives;+ // skybox / view-cube / axes are environment helpers (neither). Called once after ALL geometry+ // (model + tape/reel + ghosts) is built so nothing is missed. transparencyShadow lets the+ // translucent ghosts (nozzle, cover tape) cast alpha-weighted shadows instead of hard ones.+ const shadowed = new Set();+ const registerShadows = () => {+ if (!sg) return;+ if (sg.setTransparencyShadow) sg.setTransparencyShadow(true); else sg.transparencyShadow = true;+ scene.meshes.forEach(m => {+ if (!m.getTotalVertices || m.getTotalVertices() === 0) return;+ if (/skyBox|viewCube|axis|gizmo|fov/i.test(m.name)) return; // FOV cone is a light-field indicator, not a solid — no shadows+ m.receiveShadows = true; // everything receives (incl. ground)+ if (!/shadowGround|^ground$/i.test(m.name) && !shadowed.has(m)) { // ground receives but doesn't cast+ sg.addShadowCaster(m, true); shadowed.add(m); // (Set guard avoids duplicate casters)+ }+ });+ const smap = sg.getShadowMap(); if (smap) smap.refreshRate = 1;+ };++ // 3) Translucent ghosts (nozzle + carrier tape + component-in-tape), built with HIS Babylon.+ const PX = 0.0065, LED_TOP = 0.00060; // squashed lens top (1.10mm model x ZS 0.545)+ // The shipped bundle exposes only a few BABYLON constructors; harvest TransformNode+ // from his scene (ViewerRoot) and use StandardMaterial (exposed) for the translucent ghosts.+ const TN = (scene.transformNodes[0] && scene.transformNodes[0].constructor) || null;+ const makeGroup = (name) => TN ? new TN(name, scene) : B.MeshBuilder.CreateBox(name, { size:1e-6 }, scene);+ function ghostMat(name, rgb, alpha){+ const m = new B.StandardMaterial(name, scene);+ m.diffuseColor = new B.Color3(rgb[0],rgb[1],rgb[2]);+ m.emissiveColor = new B.Color3(rgb[0]*0.5, rgb[1]*0.5, rgb[2]*0.5); // self-lit so it reads as a translucent ghost+ m.specularColor = new B.Color3(0.1,0.1,0.1);+ m.alpha = alpha; m.backFaceCulling = false; m.disableLighting = false;+ return m;+ }+ const ghostRoot = makeGroup('pnp_ghosts');+ ghostRoot.parent = modelParent;++ // ---- Datasheet carrier-tape constants (Inolux IN-S63BT V1.0, p.10 "Tape Dimension") ----+ // W=8.00 T=0.23 P1=4.00 E=1.75 F=3.50 Do=1.50 Po=4.00 P2=2.00 Ko(emboss depth)=0.70 — all from the p.10 drawing.+ // Ao/Bo (pocket cavity W/L) are NOT dimensioned in this datasheet -> derived from the 1.6x0.8mm body + EIA-481 clearance+ // (Ao 0.80 body-width +0.15, Bo 1.60 body-length +0.25). 8mm tape / 4000pcs per reel; reel O178 hub O60 arbor O13.0 (p.10 "Reel Dimension").+ const mm = 0.001;+ const TW=8.00*mm, TT=0.23*mm, TP1=4.00*mm, TE=1.75*mm, TF=3.50*mm, TDo=1.50*mm, TP2=2.00*mm, TAo=0.95*mm, TBo=1.85*mm, TKo=0.70*mm;+ const NPOCK = 3, PKX = 7.0*mm; // pockets shown; active pocket X (nozzle picks here). Set clear of the FR4 board (board ends at +1.6mm; tape starts ~+4mm)+ const ySpr = TW/2 - TE, PKY = ySpr - TF; // sprocket-hole row Y; component-pocket row Y (= pick Y)++ const nozzle = makeGroup('pnp_nozzle'); nozzle.parent = ghostRoot;+ const nozMat = ghostMat('nozMat', [0.62,0.70,0.78], 0.34, 0.6, 0.3);+ const tip = B.MeshBuilder.CreateCylinder('nozzle_tip', { height:0.0006, diameterBottom:0.0004, diameterTop:0.0008, tessellation:40 }, scene);+ tip.rotation.x = Math.PI/2; tip.position = new B.Vector3(0,0,0.0003);+ const shaft = B.MeshBuilder.CreateCylinder('nozzle_shaft', { height:0.0032, diameter:0.0008, tessellation:40 }, scene);+ shaft.rotation.x = Math.PI/2; shaft.position = new B.Vector3(0,0,0.0022);+ [tip, shaft].forEach(m => { m.material = nozMat; m.parent = nozzle; });+ nozzle.position = new B.Vector3(PKX, PKY, 0.0032);++ // ---- CAD-accurate embossed carrier tape (Inolux IN-S63BT V1.0, p.10), lying FLAT ----+ const pocketXs = Array.from({length:NPOCK}, (_,k)=> PKX + k*TP1);+ // sprocket holes: pitch Po, offset P2 from the pockets; base extends 1mm past the outermost holes+ const holeXs = pocketXs.map(x => x - TP2).concat([pocketXs[pocketXs.length-1] + (TP1 - TP2)]);+ const tMinX = Math.min(...holeXs) - 0.001, tMaxX = Math.max(...holeXs) + 0.001, tLen = tMaxX - tMinX, tCx = (tMinX+tMaxX)/2;+ const solidMat = (name,rgb) => { const m=new B.StandardMaterial(name,scene); m.diffuseColor=new B.Color3(rgb[0],rgb[1],rgb[2]); m.emissiveColor=new B.Color3(rgb[0]*0.55,rgb[1]*0.55,rgb[2]*0.55); m.specularColor=new B.Color3(0.1,0.1,0.1); m.backFaceCulling=false; return m; };+ const tapeMat = solidMat('tapeMat', [0.90,0.85,0.73]); // opaque BEIGE carrier tape (realistic)+ const wallMat = solidMat('wallMat', [0.62,0.56,0.45]); // embossed pocket cavity (darker beige)+ const holeMat = solidMat('holeMat', [0.05,0.05,0.06]); // sprocket holes (dark)+ const coverMat = ghostMat('coverMat', [0.62,0.76,0.92], 0.09); // clear cover-tape film (stays translucent)+ const POCKET_LED_Z = -TKo + 0.00003; // LED seated on the pocket floor (fully recessed: Ko 0.70 deep, LED 0.60 tall -> top ~0.1mm below the tape surface, as in the reel)+ const IN_TAPE_ROT = -Math.PI/2; // cathode faces +Y (toward sprockets), per datasheet+ const WT = 0.00004; // pocket wall thickness+ const tape = makeGroup('tape_reel'); tape.parent = ghostRoot;+ // base film with the pocket band OPEN at each pocket (embossed pockets + LEDs show through, not covered)+ const yPocT = PKY + TBo/2, yPocB = PKY - TBo/2;+ const strip = (w,h,cx,cy,nm) => { const m=B.MeshBuilder.CreateBox(nm,{width:w,height:h,depth:TT},scene); m.position=new B.Vector3(cx,cy,-TT/2); m.material=tapeMat; m.parent=tape; };+ // strip above the pockets — SMOOTH circular sprocket holes in a SOLID slab (thickness TT, matching the+ // rest of the tape) so the beige part reads as a physical part, not zero-thickness film. Hand-built:+ // radial-tessellated TOP + BOTTOM faces (clean vector circles), cylindrical WALLS through each hole,+ // and outer EDGE walls around the strip. Buffers written directly (no earcut/CSG needed).+ const HSEG = 72, holeR = TDo/2, holeCy = ySpr, zTop = 0, zBot = -TT;+ const sortedHx = holeXs.slice().sort((a,b)=>a-b);+ const bandB = [tMinX]; // vertical band boundaries = midpoints between holes+ for (let i=0;i<sortedHx.length-1;i++) bandB.push((sortedHx[i]+sortedHx[i+1])/2);+ bandB.push(tMaxX);+ const P = [], NR = [], IDX = [];+ const addV = (x,y,z,nx,ny,nz) => { P.push(x,y,z); NR.push(nx,ny,nz); return P.length/3 - 1; };+ sortedHx.forEach((cx,hi) => {+ const bx0 = bandB[hi], bx1 = bandB[hi+1];+ const tIn=[], tOut=[], bIn=[], bOut=[], wT=[], wB=[]; // top/bottom face rings + hole-wall rings+ for (let k=0;k<=HSEG;k++){+ const th = 2*Math.PI*k/HSEG, dx = Math.cos(th), dy = Math.sin(th);+ const ix = cx + holeR*dx, iy = holeCy + holeR*dy; // point ON the hole circle+ let t = Infinity; // ray from hole centre to the band-rectangle edge+ if (dx > 1e-12) t = Math.min(t,(bx1-cx)/dx); else if (dx < -1e-12) t = Math.min(t,(bx0-cx)/dx);+ if (dy > 1e-12) t = Math.min(t,(TW/2-holeCy)/dy); else if (dy < -1e-12) t = Math.min(t,(yPocT-holeCy)/dy);+ const ox = cx + t*dx, oy = holeCy + t*dy; // point on the rectangle edge+ tIn.push(addV(ix,iy,zTop, 0,0,1)); tOut.push(addV(ox,oy,zTop, 0,0,1)); // TOP face ring+ bIn.push(addV(ix,iy,zBot, 0,0,-1)); bOut.push(addV(ox,oy,zBot, 0,0,-1)); // BOTTOM face ring+ wT.push(addV(ix,iy,zTop, -dx,-dy,0)); wB.push(addV(ix,iy,zBot, -dx,-dy,0)); // hole WALL ring (inward normal)+ }+ for (let k=0;k<HSEG;k++){+ IDX.push(tIn[k], tIn[k+1], tOut[k], tOut[k], tIn[k+1], tOut[k+1]); // top face annulus+ IDX.push(bIn[k], bOut[k], bIn[k+1], bOut[k], bOut[k+1], bIn[k+1]); // bottom face annulus (reversed)+ IDX.push(wT[k], wB[k], wT[k+1], wT[k+1], wB[k], wB[k+1]); // cylindrical hole wall+ }+ });+ // outer edge walls around the strip rectangle [tMinX,tMaxX] x [yPocT,TW/2] — gives the tape edges thickness+ const edgeWall = (x0,y0,x1,y1,nx,ny) => { const a=addV(x0,y0,zTop,nx,ny,0), b=addV(x1,y1,zTop,nx,ny,0), c=addV(x0,y0,zBot,nx,ny,0), d=addV(x1,y1,zBot,nx,ny,0); IDX.push(a,c,b, b,c,d); };+ edgeWall(tMinX,TW/2, tMaxX,TW/2, 0,1); // top edge (free edge of the tape)+ edgeWall(tMaxX,yPocT, tMinX,yPocT, 0,-1); // bottom edge (meets the pocket band)+ edgeWall(tMinX,yPocT, tMinX,TW/2, -1,0); // left end+ edgeWall(tMaxX,TW/2, tMaxX,yPocT, 1,0); // right end+ const topStrip = B.MeshBuilder.CreateGround('tape_top', { width:1, height:1, subdivisions:1 }, scene);+ topStrip.setVerticesData('position', P);+ topStrip.setVerticesData('normal', NR);+ topStrip.setVerticesData('uv', new Array((P.length/3)*2).fill(0));+ topStrip.setIndices(IDX);+ topStrip.position = new B.Vector3(0,0,0); topStrip.material = tapeMat; topStrip.parent = tape; // coords baked into vertices+ if (topStrip.refreshBoundingInfo) topStrip.refreshBoundingInfo();+ strip(tLen, yPocB + TW/2, tCx, (-TW/2 + yPocB)/2, 'tape_bot'); // strip below the pockets+ const openHalf = TAo/2 + WT; // pocket-band fillers between the open pockets+ const edges = [tMinX, ...pocketXs.flatMap(x => [x-openHalf, x+openHalf]), tMaxX];+ for (let i=0;i<edges.length;i+=2){ const a=edges[i], b=edges[i+1]; if (b-a>1e-6) strip(b-a, TBo, (a+b)/2, PKY, 'tape_band'+i); }+ // (sprocket holes are real cut-outs in the top strip above — no dark discs)+ pocketXs.forEach((x,k) => { // embossed pocket = 4 walls + floor (exact Ao x Bo x Ko, open top)+ const w = (ww,hh,dd,dx,dy,dz,nm) => { const m=B.MeshBuilder.CreateBox(nm,{width:ww,height:hh,depth:dd},scene); m.position=new B.Vector3(x+dx,PKY+dy,dz); m.material=wallMat; m.parent=tape; };+ w(WT, TBo, TKo, TAo/2, 0, -TKo/2, 'pw'+k+'A'); w(WT, TBo, TKo, -TAo/2, 0, -TKo/2, 'pw'+k+'B');+ w(TAo, WT, TKo, 0, TBo/2, -TKo/2, 'pw'+k+'C'); w(TAo, WT, TKo, 0, -TBo/2, -TKo/2, 'pw'+k+'D');+ w(TAo, TBo, WT, 0, 0, -TKo, 'pf'+k);+ });+ pocketXs.forEach((x,k) => { // actual LED models in NON-active pockets (cathode-correct rotation)+ if (Math.abs(x - PKX) < 1e-9 || !led) return;+ const c = led.clone('tape_led_'+k, tape);+ if (!c) return;+ c.getDescendants(false).forEach(d => { if (d.getClassName && /Light/.test(d.getClassName())) d.dispose(); });+ c.rotationQuaternion = null; // same: use Euler so the 90° in-pocket rotation applies+ c.position = new B.Vector3(x, PKY, POCKET_LED_Z); c.rotation = new B.Vector3(0, 0, IN_TAPE_ROT);+ });+ const cover = B.MeshBuilder.CreateBox('cover_tape', { width:tLen, height:TW*0.6, depth:0.00003 }, scene); // clear cover tape+ cover.position = new B.Vector3(tCx, PKY + TBo*0.2, 0.00004); cover.material = coverMat; cover.parent = tape;+ registerShadows(); // now that ALL geometry exists (model + tape/reel + nozzle + pocket LEDs + cover), enable shadows on everything+ if (fovCone) [fovCone].concat(fovCone.getChildMeshes ? fovCone.getChildMeshes() : []).forEach(m => { if ('receiveShadows' in m) m.receiveShadows = false; if (sg && sg.removeShadowCaster) sg.removeShadowCaster(m); }); // FOV cone: no shadows (belt-and-suspenders vs the /fov/ exclusion)++ // 4) Motion — manual per-frame interpolation (no baked groups); positions in the model's space.+ const LIFT=0.00135, NHI=0.0032, NLO=0.00047, CARRY=0.0027;+ function lerpKeys(keys, t){+ for (let i=0;i<keys.length-1;i++){ const a=keys[i], b=keys[i+1];+ if (t>=a[0] && t<=b[0]){ const u=(t-a[0])/(b[0]-a[0]); return [a[1]+(b[1]-a[1])*u, a[2]+(b[2]-a[2])*u, a[3]+(b[3]-a[3])*u]; } }+ const l = keys[keys.length-1]; return [l[1],l[2],l[3]];+ }+ function lerp1(keys, t){ // scalar interpolation (LED pick rotation)+ for (let i=0;i<keys.length-1;i++){ const a=keys[i], b=keys[i+1];+ if (t>=a[0] && t<=b[0]){ const u=(t-a[0])/(b[0]-a[0]); return a[1]+(b[1]-a[1])*u; } }+ return keys[keys.length-1][1];+ }+ const bobKeys = [[0,0,0,0],[1.2,0,0,0],[3.0,0,0,LIFT],[4.2,0,0,LIFT],[6.0,0,0,0]];+ const nozKeys = [[0,PKX,PKY,NHI],[1.0,PKX,PKY,NLO],[1.9,PKX,PKY,NHI],[2.7,PKX,PKY,NHI],[3.6,0,0,NHI],[4.4,0,0,NLO],[5.2,0,0,NHI],[6.8,PKX,PKY,NHI],[8.0,PKX,PKY,NHI]];+ const ledKeys = [[0,PKX,PKY,POCKET_LED_Z],[1.0,PKX,PKY,POCKET_LED_Z],[1.9,PKX,PKY,CARRY],[2.7,PKX,PKY,CARRY],[3.6,0,0,CARRY],[4.4,0,0,0],[6.8,0,0,0],[8.0,PKX,PKY,POCKET_LED_Z]];+ // LED lifts STRAIGHT UP out of the pocket (still at the in-tape angle, so it never clips the pocket walls),+ // THEN the nozzle rotates it to the board orientation (0°) in the air, then carries it over and places it.+ // In-tape angle = IN_TAPE_ROT (cathode toward the sprocket holes, per datasheet); board = 0° (cathode −X).+ const rotKeys = [[0,IN_TAPE_ROT],[1.9,IN_TAPE_ROT],[2.7,0],[8.0,0]];+ let t0 = performance.now();+ scene.onBeforeRenderObservable.add(() => {+ // keep the shadow map re-rendering so the cast shadow follows the animated LED+ if (sg) { const sm = sg.getShadowMap(); if (sm && sm.refreshRate !== 1) sm.refreshRate = 1; }+ const t = (performance.now() - t0) / 1000;+ if (mode === 'static') {+ const p = lerpKeys(bobKeys, t % 6);+ [led, ledLit, fovCone].forEach(n => { if (n) n.position.set(p[0], p[1], p[2]); });+ if (led) led.rotation.z = 0;+ } else {+ const tt = t % 8;+ const np = lerpKeys(nozKeys, tt); nozzle.position.set(np[0], np[1], np[2]);+ const lp = lerpKeys(ledKeys, tt); if (led) { led.position.set(lp[0], lp[1], lp[2]); led.rotation.z = lerp1(rotKeys, tt); }+ const show = tt <= 6.8; if (led && led.isEnabled() !== show) led.setEnabled(show); // in the pocket from t=0, hidden only during the loop reset+ }+ });++ // 5) Layers — includes the two the wiki viewer lacks: Light (LED_lit) and FOV (fov_cone).+ const layers = [+ { key:'light', label:'Light (LED lit)', get:()=>ledLit, extra:on=>{ if(ptLight) ptLight.setEnabled(on); } },+ { key:'fov', label:'FOV (120° cone)', get:()=>fovCone },+ { key:'body', label:'LED body', get:()=>led, grp:true },+ { key:'board', label:'fr4_board', get:()=>scene.getNodeByName('fr4_board') },+ { key:'pad', label:'pad_top', get:()=>scene.getNodeByName('pad_top') },+ { key:'silk', label:'silk', get:()=>scene.getNodeByName('silk') },+ { key:'solder', label:'solder_top', get:()=>scene.getNodeByName('solder_top') },+ ];+ const state = { light:true, fov:true, body:true, board:true, pad:true, silk:true, solder:true };+ const listEl = document.getElementById('layer-list'); const rows = {};+ const setNodeEnabled = (node,on)=>{ if(!node) return; node.setEnabled(on); if(node.getChildMeshes) node.getChildMeshes().forEach(c=>c.setEnabled(on)); };+ layers.forEach(L => {+ const row = document.createElement('label'); if (L.grp) row.className='grp';+ const cb = document.createElement('input'); cb.type='checkbox'; cb.checked=state[L.key];+ cb.onchange = () => { state[L.key]=cb.checked; setNodeEnabled(L.get(),cb.checked); if(L.extra)L.extra(cb.checked); };+ row.appendChild(cb); row.append(' '+L.label); listEl.appendChild(row); rows[L.key]={row,cb};+ });+ const lockLayer = (key,locked)=>{ rows[key].row.classList.toggle('disabled',locked); rows[key].cb.disabled=locked; };++ // His frameModel() mis-frames in this embed (it framed the 5000-unit skybox → camera at+ // radius ~2500 m, so the ~3mm part is a sub-pixel dot). Run it for its spotlight/ground+ // positioning, then set a sane mm-scale camera explicitly.+ function applyFrame(mode){+ try { viewer.frameModel(); } catch (e) {}+ const c = scene.activeCamera;+ c.lowerRadiusLimit = 0.0015; c.upperRadiusLimit = 0.08; c.minZ = 0.00005; c.maxZ = 10;+ c.alpha = 1.05; c.beta = 1.0;+ if (mode === 'pnp') { c.target.copyFromFloats(0.003, 0, 0.0006); c.radius = 0.026; }+ else { c.target.copyFromFloats(0, 0, -0.0002); c.radius = 0.0065; }+ matchColby(); // frameModel may rebuild the ground/skybox — re-apply his ground fade + no-skybox+ }++ // 6) Mode switching — ghosts are a content root only in P&P (so Static frames just the part).+ let mode = 'static';+ function setMode(m){+ mode = m; t0 = performance.now();+ document.getElementById('mode-static').classList.toggle('on', m==='static');+ document.getElementById('mode-pnp').classList.toggle('on', m==='pnp');+ document.getElementById('legend').classList.toggle('show', m==='pnp');+ if (m==='static'){+ setNodeEnabled(ghostRoot, false); viewer.removeContentRoot(ghostRoot);+ lockLayer('light',false); lockLayer('fov',false);+ if (led) setNodeEnabled(led, true);+ if (ledLit) setNodeEnabled(ledLit, state.light); if (ptLight) ptLight.setEnabled(state.light);+ if (fovCone) setNodeEnabled(fovCone, state.fov);+ applyFrame(m);+ statusEl.textContent = 'STATIC · LED insertion (up/down) · toggle Light & FOV in Layers';+ } else {+ setNodeEnabled(ghostRoot, true); viewer.addContentRoot(ghostRoot, { castShadows:true, receiveShadows:true });+ if (ledLit) setNodeEnabled(ledLit, false); if (fovCone) setNodeEnabled(fovCone, false); if (ptLight) ptLight.setEnabled(false);+ lockLayer('light',true); lockLayer('fov',true);+ if (led) setNodeEnabled(led, true);+ applyFrame(m);+ statusEl.textContent = 'PICK & PLACE · nozzle picks LED from tape → places on pads';+ }+ }++ // 7) Buttons — Ground / Bottom light call HIS API; Layers is our menu.+ document.getElementById('mode-static').onclick = () => setMode('static');+ document.getElementById('mode-pnp').onclick = () => setMode('pnp');+ document.getElementById('btn-ground').onclick = function(){ this.classList.toggle('on'); viewer.setGroundVisible(this.classList.contains('on')); matchColby(); }; // setGroundVisible rebuilds the ground opaque — re-apply his fade circle+ document.getElementById('btn-bottom').onclick = function(){ this.classList.toggle('on'); if (bottomFill) bottomFill.intensity = this.classList.contains('on') ? 0.6 : 0; };+ document.getElementById('btn-layers').onclick = function(){ document.getElementById('layer-menu').classList.toggle('open'); this.classList.toggle('on'); };++ // Close the Layers menu on any click outside it (and outside the Layers button).+ document.addEventListener('click', (e) => {+ const menu = document.getElementById('layer-menu'), btn = document.getElementById('btn-layers');+ if (menu.classList.contains('open') && !menu.contains(e.target) && !btn.contains(e.target)) {+ menu.classList.remove('open'); btn.classList.remove('on');+ }+ }, true);++ setMode('static');+ window._v = { viewer, scene, B, setMode }; // debug hook+ } catch (e) { statusEl.textContent = 'init error: ' + e.message; window._err = (e.stack || e.message); console.error(e); }+})();+</script>++<style>html,body{overscroll-behavior:none}</style>+<script>+(function () {+ addEventListener('wheel', function (e) {+ for (var n = e.target; n && n !== document.documentElement; n = n.parentElement) {+ var oy = getComputedStyle(n).overflowY;+ if ((oy === 'auto' || oy === 'scroll') && n.scrollHeight > n.clientHeight) {+ var atTop = n.scrollTop <= 0;+ var atEnd = n.scrollTop + n.clientHeight >= n.scrollHeight - 1;+ if (!(e.deltaY < 0 && atTop) && !(e.deltaY > 0 && atEnd)) return;+ break;+ }+ }+ e.preventDefault();+ }, { passive: false, capture: true });+})();+</script>++</html>
docs/assembly.mdadded+7@@ -0,0 +1,7 @@+# Assembly animation++A small 3D scene of IN-S63BTG on a test board. **Static** lowers the part onto its pads; **Pick & Place** shows Adom's pick-and-place nozzle lifting it out of the carrier tape (pocket sizes from the datasheet) and placing it. The board is a thick illustrative slab, not a real stack-up, and the pads in the scene follow this page's footprint.++[Open the animation](https://wiki.adom.inc/adom/in-s63btg/render/docs/assembly.html) (drag to orbit, scroll to zoom; the buttons switch between Static and Pick & Place).++The scene is `docs/assembly.html`, which loads `IN-S63BTG.insertion.glb` from this page.
docs/datasheet.mdadded+33@@ -0,0 +1,33 @@+# IN-S63BTG datasheet++**IN-S63BT series, Top View SMD LED 0603 PCB Type**, V1.2 revised 10 March 2022, Inolux Corporation.++++++++++++++++++++++++++++++
footprint-variants/IN-S63BTG-RR25.kicad_modadded+18@@ -0,0 +1,18 @@+(footprint "IN-S63BTG-RR25"+ (version 20240108)+ (generator "adom-basic-parts-overhaul")+ (layer "F.Cu")+ (descr "Inolux Corporation IN-S63BTG, 0603. Land pattern from Inolux IN-S63BT series datasheet V1.2, p.1 (Recommended Solder Pattern); corners: datasheet silent; roundrect radius 0.1 mm = min(0.25 x smaller pad side, 0.1 mm), IPC-7351C rounded corners for paste release")+ (tags "0603")+ (attr smd)+ (fp_text reference "REF**" (at 0 -1.4) (layer "F.SilkS") (effects (font (size 1 1) (thickness 0.15))))+ (fp_text value "IN-S63BTG" (at 0 1.4) (layer "F.Fab") (effects (font (size 1 1) (thickness 0.15))))+ (fp_rect (start -1.25 -0.7) (end 1.25 0.7) (stroke (width 0.05) (type default)) (fill none) (layer "F.CrtYd"))+ (fp_rect (start -0.8 -0.4) (end 0.8 0.4) (stroke (width 0.1) (type default)) (fill none) (layer "F.Fab"))+ (fp_line (start -0.55 -0.4) (end -0.55 0.4) (stroke (width 0.1) (type default)) (layer "F.Fab"))+ (fp_line (start -1.16 -0.56) (end 0.8 -0.56) (stroke (width 0.12) (type default)) (layer "F.SilkS"))+ (fp_line (start -1.16 0.56) (end 0.8 0.56) (stroke (width 0.12) (type default)) (layer "F.SilkS"))+ (fp_line (start -1.16 -0.56) (end -1.16 0.56) (stroke (width 0.12) (type default)) (layer "F.SilkS"))+ (pad "1" smd roundrect (at -0.7 0) (size 0.6 0.9) (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.25))+ (pad "2" smd roundrect (at 0.7 0) (size 0.6 0.9) (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.25))+)
footprint-variants/IN-S63BTG-SQ.kicad_modadded+18@@ -0,0 +1,18 @@+(footprint "IN-S63BTG-SQ"+ (version 20240108)+ (generator "adom-basic-parts-overhaul")+ (layer "F.Cu")+ (descr "Inolux Corporation IN-S63BTG, 0603. Land pattern from Inolux IN-S63BT series datasheet V1.2, p.1 (Recommended Solder Pattern); corners: datasheet silent; roundrect radius 0.1 mm = min(0.25 x smaller pad side, 0.1 mm), IPC-7351C rounded corners for paste release")+ (tags "0603")+ (attr smd)+ (fp_text reference "REF**" (at 0 -1.4) (layer "F.SilkS") (effects (font (size 1 1) (thickness 0.15))))+ (fp_text value "IN-S63BTG" (at 0 1.4) (layer "F.Fab") (effects (font (size 1 1) (thickness 0.15))))+ (fp_rect (start -1.25 -0.7) (end 1.25 0.7) (stroke (width 0.05) (type default)) (fill none) (layer "F.CrtYd"))+ (fp_rect (start -0.8 -0.4) (end 0.8 0.4) (stroke (width 0.1) (type default)) (fill none) (layer "F.Fab"))+ (fp_line (start -0.55 -0.4) (end -0.55 0.4) (stroke (width 0.1) (type default)) (layer "F.Fab"))+ (fp_line (start -1.16 -0.56) (end 0.8 -0.56) (stroke (width 0.12) (type default)) (layer "F.SilkS"))+ (fp_line (start -1.16 0.56) (end 0.8 0.56) (stroke (width 0.12) (type default)) (layer "F.SilkS"))+ (fp_line (start -1.16 -0.56) (end -1.16 0.56) (stroke (width 0.12) (type default)) (layer "F.SilkS"))+ (pad "1" smd rect (at -0.7 0) (size 0.6 0.9) (layers "F.Cu" "F.Paste" "F.Mask"))+ (pad "2" smd rect (at 0.7 0) (size 0.6 0.9) (layers "F.Cu" "F.Paste" "F.Mask"))+)
footprint-variants/IN-S63BTG.kicad_modadded+18@@ -0,0 +1,18 @@+(footprint "IN-S63BTG"+ (version 20240108)+ (generator "adom-basic-parts-overhaul")+ (layer "F.Cu")+ (descr "Inolux Corporation IN-S63BTG, 0603. Land pattern from Inolux IN-S63BT series datasheet V1.2, p.1 (Recommended Solder Pattern); corners: datasheet silent; roundrect radius 0.1 mm = min(0.25 x smaller pad side, 0.1 mm), IPC-7351C rounded corners for paste release")+ (tags "0603")+ (attr smd)+ (fp_text reference "REF**" (at 0 -1.4) (layer "F.SilkS") (effects (font (size 1 1) (thickness 0.15))))+ (fp_text value "IN-S63BTG" (at 0 1.4) (layer "F.Fab") (effects (font (size 1 1) (thickness 0.15))))+ (fp_rect (start -1.25 -0.7) (end 1.25 0.7) (stroke (width 0.05) (type default)) (fill none) (layer "F.CrtYd"))+ (fp_rect (start -0.8 -0.4) (end 0.8 0.4) (stroke (width 0.1) (type default)) (fill none) (layer "F.Fab"))+ (fp_line (start -0.55 -0.4) (end -0.55 0.4) (stroke (width 0.1) (type default)) (layer "F.Fab"))+ (fp_line (start -1.16 -0.56) (end 0.8 -0.56) (stroke (width 0.12) (type default)) (layer "F.SilkS"))+ (fp_line (start -1.16 0.56) (end 0.8 0.56) (stroke (width 0.12) (type default)) (layer "F.SilkS"))+ (fp_line (start -1.16 -0.56) (end -1.16 0.56) (stroke (width 0.12) (type default)) (layer "F.SilkS"))+ (pad "1" smd roundrect (at -0.7 0) (size 0.6 0.9) (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.1667))+ (pad "2" smd roundrect (at 0.7 0) (size 0.6 0.9) (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.1667))+)
footprint-variants/IN-S63BTG.variants.jsonadded+28@@ -0,0 +1,28 @@+{+ "part": "IN-S63BTG",+ "package": "",+ "generator": "adom basic-parts overhaul 2026-10-03 (corner comparison)",+ "variants": [+ {+ "suffix": "",+ "device": "this page",+ "kicad_mod": "IN-S63BTG.kicad_mod",+ "footprintName": "IN-S63BTG",+ "changed": "the page footprint: roundrect, corner radius 0.1 mm (ratio 0.1667)"+ },+ {+ "suffix": "-SQ",+ "device": "square corners",+ "kicad_mod": "IN-S63BTG-SQ.kicad_mod",+ "footprintName": "IN-S63BTG-SQ",+ "changed": "same pads as plain rectangles, as the datasheet draws them"+ },+ {+ "suffix": "-RR25",+ "device": "KiCad default rounding",+ "kicad_mod": "IN-S63BTG-RR25.kicad_mod",+ "footprintName": "IN-S63BTG-RR25",+ "changed": "same pads with roundrect_rratio 0.25 (KiCad's default), radius 0.15 mm"+ }+ ]+}
in-s63btg-hero.glb⋯ 1 unchanged line ⋯
in-s63btg-hero.overlay.jsonadded+125@@ -0,0 +1,125 @@+{+ "spec": "adom-hero 1.4",+ "mpn": "IN-S63BTG",+ "kind": "component + footprint reference art",+ "board_use": false,+ "plane_z_mm": -0.02,+ "units": "metre",+ "upAxis": "Z",+ "layers": {+ "pad_outlines": {+ "material": "Footprint pads - teal dashed outlines - 50 percent opacity",+ "rgba": [+ 0.0,+ 0.902,+ 0.863,+ 0.5+ ],+ "pads": 2,+ "span_mm": 2.0,+ "dash_mm": 0.12,+ "gap_mm": 0.072,+ "pad_stroke_mm": 0.03+ },+ "silkscreen": {+ "material": "Silkscreen reference lines - 30 percent opacity",+ "rgba": [+ 0.92,+ 0.96,+ 1.0,+ 0.3+ ],+ "footprint_items": 3,+ "pin1": null+ },+ "signal_names": {+ "material": "Signal names - 50 percent opacity",+ "rgba": [+ 0.92,+ 0.96,+ 1.0,+ 0.5+ ],+ "font": "DejaVu Sans Mono",+ "labels": 2,+ "sides": "top + mirrored underside (single-sided)",+ "fallback_to_pad_number": 2+ }+ },+ "align": {+ "ok": true,+ "centre_offset_mm": 0.0,+ "tolerance_mm": 0.25,+ "orientation_flipped": false,+ "contacts_bbox_mm": [+ -1.7,+ 1.7,+ -0.9,+ 0.9+ ],+ "pads_bbox_mm": [+ -1.0,+ 1.0,+ -0.45,+ 0.45+ ],+ "seating_z_mm": -1.6+ },+ "sources": {+ "glb": "IN-S63BTG.glb",+ "glb_sha256": "ecd5d38c1a7d483255beb1075761d4cfd1cc01b2ab4150fa8b6e86eb526e162d",+ "footprint": "IN-S63BTG.kicad_mod",+ "footprint_sha256": "380bf8081f837572e367bbd4b4f19c842eaaec3f2623818e27ddb2ef6c5bd8b1",+ "pins": "page.json component.pins",+ "pins_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"+ },+ "generator": "adom-wiki 1.7.67 (component_hero)",+ "labels": [+ {+ "pad": "1",+ "text": "1",+ "x": -1.105,+ "y": 0.0,+ "align": "right",+ "vertical": false,+ "h": 0.42+ },+ {+ "pad": "2",+ "text": "2",+ "x": 1.105,+ "y": 0.0,+ "align": "left",+ "vertical": false,+ "h": 0.42+ }+ ],+ "pads": [+ {+ "number": "1",+ "shape": "roundrect",+ "center_mm": [+ -0.7,+ 0.0+ ],+ "size_mm": [+ 0.6,+ 0.9+ ],+ "rot": 0.0+ },+ {+ "number": "2",+ "shape": "roundrect",+ "center_mm": [+ 0.7,+ 0.0+ ],+ "size_mm": [+ 0.6,+ 0.9+ ],+ "rot": 0.0+ }+ ]+}