(version 1)

# The routine 0.10 mm copper-clearance and track-width floors are deliberately
# NOT rules here. They live in Board Setup > Constraints > "Minimum clearance"
# and "Minimum track width", because an unconditional custom clearance rule
# REPLACES the netclass clearance instead of flooring it. While the old rule
# was present every netclass from 0.15 mm to 0.5 mm resolved to 0.10 mm and no
# clearance violation could be reported at all. Do not re-add them as rules.
# Removed 2026-09-17.

(rule "JLCPCB rigid FR4 SMD pad-to-pad clearance"
	(condition "A.Type == 'Pad' && B.Type == 'Pad' && A.Pad_Type == 'SMD' && B.Pad_Type == 'SMD'")
	(constraint clearance (min 0.15mm)))

# TMC5130A TQFP-48 pad field is pitch-limited, added 2026-09-20. The package is
# 0.5 mm pitch with 0.3 mm pads, so ADJACENT PADS ARE 0.20 mm APART before any
# track is drawn -- and the TMC5130A puts VS (36 V, pad 40) next to VCC (5 V,
# pad 39), VCP (pad 38) next to VCC, and CPO (pad 35) next to VCC (pad 34).
# PWR_HV_BUS asks 0.40 mm, which no routing inside the pad field can ever meet.
# IPC-2221 B4 (external, uncoated) wants 0.13 mm at 31-50 V, so 0.20 mm still
# has margin; this floors the check at what the package allows rather than
# switching it off, so a real short or a sloppy escape is still caught.
#
# The condition has two halves, and the second was added 2026-09-20 after the
# first proved insufficient:
#
#   memberOfFootprint(...)      catches a PAD of the package against nearby copper.
#   both intersectsCourtyard(...) catches TWO TRACKS ESCAPING ADJACENT PINS, which
#                               are not footprint members and so slipped through.
#
# That second case is the harder one and it is worth the arithmetic. Pads 39
# (VCC, 5 V) and 40 (VS, 36 V) sit 0.500 mm centre to centre. Two 0.20 mm tracks
# leaving on those centrelines are 0.5 - 0.2 = 0.300 mm apart, which is exactly
# what DRC measured. Reaching PWR_HV_BUS's 0.400 mm would need 0.10 mm tracks --
# the board's absolute min_track_width, on a 36 V rail. There is no layout that
# satisfies it, so the rule has to, or DRC can never come back clean.
#
# `intersectsCourtyard` accepts the footprint identifier, not just a refdes --
# verified 2026-09-20, the whole condition parses and the finding clears. Keep the
# identifier form: refdes are reassigned every time a design block is re-placed,
# which is exactly what the RDN0011A comment below warns about.
#
# This is a FLOOR, not an exemption -- deliberately unlike the RDN0011A and
# DNC-pad rules below, which use (severity ignore). Inside the courtyard the
# check survives at 0.20 mm, so a real short or a sub-pitch approach still errors.
#
# Must stay BEFORE the low-voltage demote rule: later matching rules win, so a
# non-voltage-bearing pair inside this footprint still falls through to that
# rule and stays a warning. Moving this after it would promote every
# low-voltage advisory at U1201 to an error.
#
# Mirrored in ../kicad-libs -- the VCP/CPO copper is block-internal, so a fix or
# an exemption has to exist in the authoring project too.

(rule "TMC5130A TQFP-48 pad field is pitch-limited"
	(condition "A.memberOfFootprint('orb_weaver_smd:TQFP-48-1EP_7x7mm_P0.5mm_EP5x5mm_ThermalVias_JLCPCB') || (A.intersectsCourtyard('orb_weaver_smd:TQFP-48-1EP_7x7mm_P0.5mm_EP5x5mm_ThermalVias_JLCPCB') && B.intersectsCourtyard('orb_weaver_smd:TQFP-48-1EP_7x7mm_P0.5mm_EP5x5mm_ThermalVias_JLCPCB'))")
	(constraint clearance (min 0.2mm))
	(severity error))

# Clearance severity is split, changed 2026-09-20. The clearance violation TYPE
# is "error" in Board Setup > Violation Severities, and the rule below demotes
# every pair where NEITHER side is voltage-bearing back to "warning". The result
# is that the ~474 legacy low-voltage advisories stay visible but unobtrusive,
# while the handful of findings on 36 V / 12 V / motor / gate-drive copper are
# real errors that fail a DRC pass.
#
# The advisories come from design blocks authored against the old broken 0.10 mm
# floor; reworking their internals is not a v1.0 task, and boards built from
# these blocks have been manufactured and work. Fixes happen upstream in
# kicad-libs, which is deliberately the stricter project.
#
# WHY THIS ORDER. Two facts about KiCad severity, one of which was previously
# recorded here too broadly and is corrected 2026-09-20:
#
#   1. TRUE: with the clearance TYPE set to "ignore", KiCad skips the clearance
#      test altogether and no rule can bring it back. Verified 2026-09-18 against
#      tmc5160_power_stage_buk7d36_60ex, which reported 131 clearance errors under
#      the kicad-libs mining project and ZERO here with a (severity error) rule in
#      place. **Never set the clearance type back to "ignore".**
#   2. FALSE, and this file used to assert it: "rule severity can only LOWER the
#      type severity, never raise it." A rule CAN raise. Measured 2026-09-20: the
#      mining project runs clearance at type "warning" with a
#      (severity error) rule on the voltage-bearing netclasses and reports 123
#      clearance ERRORS. The 2026-09-18 observation was only ever about "ignore".
#
# So both arrangements work: type "warning" plus a raise rule (what kicad-libs
# does), or type "error" plus this demote rule (what this board does). This board
# uses the demote form deliberately -- if a rule ever stops matching, the finding
# falls back to error and fails loud, rather than falling back to warning and
# going quiet. Do not set the type back to "ignore".
#
# The three (severity ignore) exemptions below must stay AFTER this rule: later
# matching rules win, so they still silence the package-geometry cases.

(rule "Legacy low-voltage block clearance is advisory"
	(condition "A.NetClass != 'PWR_HV_ENTRY' && A.NetClass != 'PWR_HV_BUS' && A.NetClass != 'PWR_HV_RETURN' && A.NetClass != 'PWR_HV_LOCAL' && A.NetClass != 'MOTOR_2A' && A.NetClass != 'BRIDGE_MID' && A.NetClass != 'BOOTSTRAP' && A.NetClass != 'GATE_DRIVE' && A.NetClass != 'PWR_12V' && A.NetClass != 'PWR_12V_LOCAL' && B.NetClass != 'PWR_HV_ENTRY' && B.NetClass != 'PWR_HV_BUS' && B.NetClass != 'PWR_HV_RETURN' && B.NetClass != 'PWR_HV_LOCAL' && B.NetClass != 'MOTOR_2A' && B.NetClass != 'BRIDGE_MID' && B.NetClass != 'BOOTSTRAP' && B.NetClass != 'GATE_DRIVE' && B.NetClass != 'PWR_12V' && B.NetClass != 'PWR_12V_LOCAL'")
	(constraint clearance)
	(severity warning))

# TPSM365R6 module (TI RDN0011A, QFN-FCMOD 3.5x4.5, 0.5mm pitch). The land
# pattern's own pad gaps are 0.125-0.150mm, below the JLCPCB SMD pad-to-pad
# minimum above. Package-defined geometry, not routed copper, so ignore it.
# Must stay after that rule: later matching rules win.
# A.Reference == B.Reference limits this to pads within one instance, so real
# violations between two adjacent modules are still reported.
(rule "RDN0011A-MFG intra-package pad clearance"
	(condition "A.memberOfFootprint('orb_weaver_smd:RDN0011A-MFG') && A.Reference == B.Reference")
	(constraint clearance)
	(severity ignore))

# Creepage pads on the two high-voltage parts are deliberately floating copper,
# and clearance to them is not a voltage-stress question. Without these rules
# they produce five findings against `+36V_SW` and `HV_IN` at 0.25 mm, which is
# backwards: the pads exist precisely to create spacing.
#
# TMC5130A datasheet rev 1.21, pin list: "DNC. Do not connect these pins.
# Provided to increase creeping [distance]." Nine such pads on the TQFP-48.
# TPS1HTC100-Q1 datasheet, pin 11: "No internal connection."
#
# Scoped by footprint rather than reference so the exemption survives
# re-annotation, and by pad number so only the designated pins are covered --
# every other pad on both parts is still checked normally. Both footprints are
# unique to these two parts on this board; if either package is ever reused for
# a different part, tighten the scope. Verified 2026-09-18: these remove exactly
# the five NC/DNC findings and nothing else.
#
# Must stay after the netclass rules and the SMD pad-to-pad rule: later matching
# rules win.

(rule "TPS1HTC100-Q1 no-connect pad is not a clearance target"
	(condition "A.memberOfFootprint('orb_weaver_smd:Texas_HTSSOP-14-1EP_4.4x5mm_P0.65mm_EP3.4x5mm_Mask3.155x3.255mm_ThermalVias_JLCPCB') && A.Pad_Number == '11'")
	(constraint clearance)
	(severity ignore))

(rule "TMC5130A DNC creepage pads are not a clearance target"
	(condition "A.memberOfFootprint('orb_weaver_smd:TQFP-48-1EP_7x7mm_P0.5mm_EP5x5mm_ThermalVias_JLCPCB') && (A.Pad_Number == '14' || A.Pad_Number == '16' || A.Pad_Number == '18' || A.Pad_Number == '20' || A.Pad_Number == '22' || A.Pad_Number == '41' || A.Pad_Number == '43' || A.Pad_Number == '45' || A.Pad_Number == '47')")
	(constraint clearance)
	(severity ignore))

(rule "JLCPCB rigid FR4 routine via diameter"
	(condition "A.Type == 'Via'")
	(constraint via_diameter (min 0.45mm)))

(rule "JLCPCB rigid FR4 routine via drill"
	(condition "A.Type == 'Via'")
	(constraint hole_size (min 0.20mm)))

(rule "JLCPCB rigid FR4 1oz PTH annular ring"
	(condition "A.Type == 'Pad' && A.Pad_Type == 'Through-hole'")
	(constraint annular_width (min 0.18mm)))

(rule "JLCPCB rigid FR4 via annular ring"
	(condition "A.Type == 'Via'")
	(constraint annular_width (min 0.125mm)))

(rule "JLCPCB rigid FR4 via hole-to-hole"
	(condition "A.Type == 'Via' && B.Type == 'Via'")
	(constraint hole_to_hole (min 0.20mm)))

(rule "JLCPCB rigid FR4 pad hole-to-hole"
	(condition "A.Type == 'Pad' && B.Type == 'Pad'")
	(constraint hole_to_hole (min 0.45mm)))

(rule "JLCPCB rigid FR4 hole to copper"
	(constraint hole_clearance (min 0.20mm)))

(rule "JLCPCB rigid FR4 PTH hole to copper"
	(condition "A.Type == 'Pad' && A.Pad_Type == 'Through-hole'")
	(constraint hole_clearance (min 0.28mm)))

(rule "JLCPCB rigid FR4 routed copper to board edge"
	(constraint edge_clearance (min 0.20mm)))

(rule "JLCPCB rigid FR4 silkscreen clearance"
	(constraint silk_clearance (min 0.15mm)))

(rule "Ignore non-production silkscreen clearance"
	(constraint silk_clearance)
	(severity ignore))

(rule "JLCPCB rigid FR4 silkscreen text height"
	(condition "A.Layer == 'F.SilkS' || A.Layer == 'B.SilkS'")
	(constraint text_height (min 1.00mm)))

(rule "JLCPCB rigid FR4 silkscreen text thickness"
	(condition "A.Layer == 'F.SilkS' || A.Layer == 'B.SilkS'")
	(constraint text_thickness (min 0.15mm)))
