Exercise 2: A Multi-Part Compound Selector vs. a Bare Id — Possible Solution ==================================================================== THE TEST ------------------------------ specificity(parse_selector("div.card p")) specificity(parse_selector("#x")) RESULT ------------------------------ 'div.card p' -> (0, 1, 2) '#x' -> (1, 0, 0) Comparing the two tuples: (1, 0, 0) > (0, 1, 2) is True. The bare id selector wins, decisively, despite 'div.card p' combining a tag, a class, AND a second tag across two separate parts of the selector. WHY 'div.card p' COMES OUT TO (0, 1, 2) ------------------------------ specificity() walks every SimpleSelector part of the whole selector, not just the target (the last part). "div.card p" splits into two parts on the space: SimpleSelector(tag='div', classes={'card'}) and SimpleSelector(tag='p'). Summing across both: - id_count: 0 (neither part has an id) - class_count: 1 (only 'div.card' contributes a class) - tag_count: 2 (both 'div' and 'p' contribute a tag) giving (0, 1, 2). WHY THE ID STILL WINS DESPITE THAT ------------------------------ Tuple comparison is lexicographic -- Python (and the real CSS spec) compares the FIRST component first, and only looks at the next component if the first one is tied. (1,0,0) has a 1 in the id slot; (0,1,2) has a 0 there. The comparison is decided on that very first digit alone -- Python never even needs to look at the class or tag counts to know (1,0,0) is bigger. No amount of accumulated class or tag count in the second and third positions can ever compensate for a zero in the first position when the other side has a one there. WHY THIS WORKS AS AN ANSWER ------------------------------ This is the same underlying principle Chapter 6's own Test 1 already demonstrated with ten stacked classes losing to one id -- here it's demonstrated again with a selector that "looks" more complicated (two tags and a class, spread across a real descendant combinator) rather than just a pile of classes on one element. The lesson generalizes: however elaborate a selector without an id gets, in however many parts, it can never outrank a selector that includes even a single id -- because specificity comparison never lets a lower tier's count "carry" into a higher one, the way summed decimal digits would.