/* r-solar Brand System v2 compliance layer: type.
   Loaded after styles_v2.min.css on every page that loads it (brand gauntlet run 2, 2026-09-28).
   Owned by one gauntlet lane; see audits/brand-gauntlet-2026-09-27 in the SEO repo. */

/* ==========================================================================
   Measure (§type "Measure" + §layout "Measure" rule): running text never
   exceeds --measure (68ch), even inside a 1320px container. Round P12-r0
   found this stylesheet at 0 rules and every sampled page's running-text
   <p> — FAQ answers, blog/article body copy, hero/lead paragraphs —
   stretching to the full content column (76-185 characters per line). This
   is the single shared-rule fix for that: cap the column, don't shrink the
   type. Scoped to <p> (the element type every listed violation named), and
   carved out from short UI paragraphs whose layout role is to fill a row
   (buttons rendered as <p>, address lines, breadcrumbs) — those were never
   over 68ch to begin with, so the :not() list only removes accidental risk,
   not real content.

   P12 round 15 fix (found by the exhaustive scanner's new measure check,
   see scan_P12.py): the original selector's :not() clauses gave it
   specificity (0,3,1), which beats any page-local single-class max-width
   rule (0,1,0) - e.g. aboutus.html's `.abt-hero__sub { max-width: 620px; }`
   and ~35 more `*__hero-sub`/`*__sub`/`.lead` style page-local hero-subtitle
   classes sitewide, each deliberately authored NARROWER than 68ch for its
   own layout. This rule was WINNING that fight and WIDENING those boxes to
   68ch (780px at their ~19px font) instead of the page's own tighter
   value, which is backwards: --measure is meant to be an outer ceiling
   pages opt out of by setting their OWN narrower max-width, never a floor
   that overrides one. Wrapping the whole selector in :where() zeroes its
   specificity to (0,0,0) so it only ever applies where nothing more
   specific already set max-width - exactly the "opt-out to something
   narrower" behaviour the rule always intended, without changing anything
   for the plain, unclassed <p> elements (FAQ answers, blog copy) this rule
   exists to cap, since nothing else sets max-width on those. */
:root {
  --measure: 68ch;
}

:where(p:not(.btn):not(.breadcrumb-item):not(.office-addr)) {
  max-width: var(--measure);
}

/* A capped paragraph that was centred (hero/lead copy, CTA subtext) must
   stay centred in its column instead of collapsing to the left edge of its
   new, narrower box. */
p.text-center,
.text-center > p,
.lead.text-center {
  margin-left: auto;
  margin-right: auto;
}

/* Round 20 — the :not() clauses above were moved INSIDE :where() (they used
   to sit outside it), which finally gives this rule the true (0,0,0)
   specificity round 15's own comment always claimed it had. That correctly
   lets page-local narrower max-widths win (aboutus.html's .abt-hero__sub,
   etc.) - but it also means a page-local rule that is WIDER than --measure
   now wins too, which round 15's bug had been accidentally masking. Found
   one real instance by re-running the exhaustive scanner after this fix:
   the "rs-nextstep" reusable next-step block's `.rs-ns-sub` line
   (`.rs-nextstep .rs-ns-sub{...max-width:640px}`, page-local, identical
   copy-pasted rule on 16 pages) renders ~74 chars/line at 1280px on
   net-metering-mp - over the 68ch cap - because 640px was never checked
   against --measure when the component was authored. Restated here with
   higher specificity (two classes, matching the page-local selector's own
   0,2,0) plus !important so it wins over the page-local 640px regardless
   of which of the 16 pages it renders on, without editing 16 separate
   page-local <style> blocks for one shared component. */
.rs-nextstep .rs-ns-sub {
  max-width: var(--measure) !important;
}

/* ==========================================================================
   Body line-height (§type "Every line-height lands on the 4px grid" +
   --type-body 16/24). Several page-local rules set a unitless line-height
   on 16px running text that lands off the 4px grid (1.55 = 24.8px, 1.6 =
   25.6px, 1.65 = 26.4px, 1.72 = 27.52px instead of the required 24px).
   `.blog-content p:not(.lead)` etc. come from styles_v2.css, which
   rs-type.css already loads after — those win on source order alone. The
   rest (aboutus.html, contact-us.html, index.html) are page-local <style>
   blocks that sit AFTER rs-type.css's own <link> in <head>, so those need
   !important to win back regardless of source order. Fixed to an explicit
   24px (not an em ratio) so the grid value holds regardless of any future
   font-size edit on these same selectors.
   ========================================================================== */
.blog-content p:not(.lead),
.article-content p:not(.lead),
.article-body p:not(.lead),
.post-content p:not(.lead),
.content-body p:not(.lead),
article p:not(.lead) {
  line-height: 24px;
}

.timeline-card p,
.abt-why__tile p,
.rs-feat p,
.rsa-head p:not(.rsa-eyebrow),
.rsa-feature p,
.rsa-svc-card p,
.abt-why__quote p {
  line-height: 24px !important;
}

/* ==========================================================================
   Letter-spacing / line-height on scale (§type scale table: --type-h1
   -0.03em, --type-h2 -0.025em). Two pages carry page-local heading <style>
   blocks (aboutus.html, contact-us.html) whose <style> tag sits AFTER this
   stylesheet in <head>, so it wins ties on source order; matching its
   selectors here needs !important to win back. Only the off-token
   properties are touched — font-size/weight on these selectors already
   measured correct and are left alone.
   ========================================================================== */

/* aboutus.html hero h1: 44/48/700 already correct, tracking was -0.02em
   (-0.88px) instead of --type-h1's -0.03em (-1.32px). */
.abt-hero__h1 {
  letter-spacing: -0.03em !important;
}

/* aboutus.html section h2s (3 instances): font-size already 32px, but
   line-height 1.15 (~36.8px) and tracking -0.015em (-0.48px) miss
   --type-h2's 40px / -0.025em (-0.8px). */
.abt-h2 {
  line-height: 40px !important;
  letter-spacing: -0.025em !important;
}

/* contact-us.html section h2s: same --type-h2 gap (36.48px/36.px line-height
   and -0.48px tracking instead of 40px / -0.8px). */
.why-rs__title,
.rs-cta__title {
  line-height: 40px !important;
  letter-spacing: -0.025em !important;
}

@media (max-width: 767.98px) {
  /* --type-h2 mobile step is 26/32, not the desktop 32/40. .abt-h2,
     .why-rs__title and .rs-cta__title all correctly step their font-size
     down to 26px at this width (via the sitewide h2 mobile rule /
     page-local media query), but the desktop line-height set above would
     otherwise keep applying unconditionally, leaving 26px text at 40px
     line-height (P12-r2 critic finding: excess vertical gap between
     wrapped heading lines on mobile). Same fix already applied to the
     industrial-solar-indore/khargone h2 above. */
  .abt-h2,
  .why-rs__title,
  .rs-cta__title {
    line-height: 32px !important;
  }
}

/* industrial-solar-indore.html / industrial-solar-khargone.html (sister template)
   h2 "Is your Indore/Khargone factory eligible?": page-local inline
   style="font-size: clamp(1.5rem, 3vw, 2rem);" already renders the correct 32px
   desktop size (left untouched), but sets no line-height/letter-spacing, so
   both fall back to something off --type-h2 (37.12px / -0.48px instead of the
   required 40px / -0.025em / -0.8px). Attribute selector matches the exact
   inline style string on both sister pages without touching the inline size. */
h2[style*="font-size: clamp(1.5rem, 3vw, 2rem)"] {
  line-height: 40px !important;
  letter-spacing: -0.025em !important;
}

@media (max-width: 767.98px) {
  /* --type-h2 mobile step is 26/32, not the desktop 32/40; clamp() already
     resolves this element to the correct 26px at mobile widths, but the
     desktop line-height above would otherwise apply unconditionally. */
  h2[style*="font-size: clamp(1.5rem, 3vw, 2rem)"] {
    line-height: 32px !important;
  }
}

/* ==========================================================================
   index.html / pm-surya-ghar-yojana.html / subsidy-center.html hero <h1
   class="display-3 ...">: Bootstrap's .display-4 sibling class is already
   patched sitewide in css/styles_v2.css to match --type-h1 (44/48/700/
   -0.03em), but .display-3 was never covered by that patch, so its h1s
   render at Bootstrap's (or index.html's own page-local, pre-rs-type.css)
   unpatched default — measured 56px/48px/-1.4px on the homepage, off every
   type-scale step. Same shared-rule fix as .display-4's own patch, applied
   here once for all three .display-3 hero h1s sitewide (index.html has four
   separate page-local <style> blocks defining/overriding .display-3 and
   .hero-title ahead of this stylesheet's <link> in <head> — several with
   their own !important — so this rule needs !important + being the last
   .display-3 declaration in the document to win). Mobile value matches
   --type-h1's own mobile step (32/40), same breakpoint styles_v2.css uses
   for h1/.display-4. */
.display-3 {
  font-size: 44px !important;
  line-height: 48px !important;
  font-weight: 700 !important;
  letter-spacing: -0.03em !important;
}

@media (max-width: 767.98px) {
  .display-3 {
    font-size: 32px !important;
    line-height: 40px !important;
  }
}

/* ==========================================================================
   lane-css-todo.md (P4 headings-lane handoff): h3 elements promoted from a
   lower heading level (<h6>/<h5>/<h4> -> <h3>) for document-structure fixes,
   while keeping their original Bootstrap size-utility class (.h4/.h5/.h6) so
   their VISUAL size stays the pre-promotion size, collide with two sitewide
   bare type-selector rules in css/styles_v2.css:
     h3 { font-size: 1.5rem !important; line-height: 1.4; }              (desktop)
     h3 { font-size: 1.25rem !important; line-height: 1.75rem !important; } (mobile, <=767.98px)
   A bare h3 with !important beats a .h4/.h5/.h6 utility class without
   !important regardless of which is kept, so every promoted heading was
   rendering at the sitewide h3 size instead of its intended, smaller
   pre-promotion size. This stylesheet loads after styles_v2.min.css on every
   page, so restoring the exact pre-promotion Bootstrap values here (with
   !important to beat the equally-!important bare h3 rule) fixes all 343+
   instances sitewide from one shared rule. footer h3.h5/h4.h5 are already
   correctly patched in styles_v2.css at higher specificity (footer h3...)
   and are unaffected either way. */
h3.h4 {
  font-size: 1.5rem !important;
}

h3.h5 {
  font-size: 1.25rem !important;
}

h3.h6 {
  font-size: 1rem !important;
}

h3.h4.h5 {
  /* Bootstrap's own .h4/.h5 cascade order makes .h5 win when both classes
     are present; the extra class here reproduces that at equal/lower cost. */
  font-size: 1.25rem !important;
}

/* P12 round 14 (found while verifying the h3.h5 fix above): the combo
   selector's final desktop size is 20px (h3.h4.h5, just above), but
   `h3.h4`'s own line-height rule (`h3.h4, body h3.h4 { line-height:32px }`,
   further down) also matches every h3.h4.h5 element (it carries the .h4
   class too) at HIGHER specificity (0,2,0 vs h3.h5's 0,1,1), so it kept
   winning line-height even after h3.h5 got fixed above — leaving these
   blog/card titles (news.html's 22 post-card h3s, and any other h3.h4.h5
   instance) at the exact same 20px/32px mismatch the h3.h5 fix just closed
   for the non-combo case. Needs its own restatement at specificity ≥ h3.h4's
   (0,3,0 here) to win outright. */
h3.h4.h5 {
  line-height: 28px !important; /* --type-h4 desktop: 20/28, same step h3.h5 uses */
  letter-spacing: -0.01em !important;
}

/* P12 round 14 — worst violation (critic-confirmed): h3.h5 (72 instances
   sitewide: FAQ questions on 3kw-solar-system-india/best-solar-panels-india/
   calculator/pm-surya-ghar-subsidy, card/office titles on aboutus/
   contact-us/industrial-solar-indore) and h3.h6 (7 instances: case-studies.html
   stat labels "Capacity"/"Annual Savings"/"Bill Reduction" etc.) got their
   font-size correctly pinned back to their pre-promotion Bootstrap value
   above (h3.h5=1.25rem/20px, h3.h6=1rem/16px), same as h3.h4, but — unlike
   h3.h4 below, which got this in round 13 — never had their line-height
   pulled off the sitewide bare `h3{line-height:1.4}` (desktop; computes ~34px
   but is beaten by an even-earlier-cascading, equally-!important source that
   nets out to line-height:32px on the promoted h3 elements in practice) /
   `h3{line-height:1.75rem!important}` (mobile) rule. Result: neither restored
   size lands on a declared type-scale step's line-height — 20px got the
   sitewide h3's 32px (no step pairs 20/32; the real step for a 20px heading
   is --type-h4 at 20/28) and 16px got 32px desktop / 28px mobile (no step
   pairs 16 with either; the real step for 16px is --type-body at 16/24,
   which also happens to be the running-text floor, so both breakpoints share
   one value). Fixed the same way as h3.h4: restate line-height (and
   letter-spacing, so the pairing is a complete, declared step rather than
   just a coincidentally-right number) at equal-or-higher specificity with
   !important. h3.h5 keeps its own weight (600, inherited from the bare h3
   rule, which already equals --type-h4's 600 — no separate weight rule
   needed). h3.h6's weight is left as-is (h3's semantic 600) for the same
   reason h3.h4 didn't touch weight either: these are still headings, and no
   sitewide h3(non-promoted)/h4 weight mismatch was found in 13 prior rounds
   of computed-style verification, so consistent heading weight across the
   promoted set is the established, spec-compliant baseline, not a new gap. */
h3.h5 {
  line-height: 28px !important; /* --type-h4 desktop: 20/28 */
  letter-spacing: -0.01em !important; /* --type-h4 tracking: -0.01em = -0.2px at 20px */
}

h3.h6 {
  line-height: 24px !important; /* --type-body: 16/24, same value both breakpoints */
  letter-spacing: 0 !important; /* --type-body tracking: 0 */
}

@media (max-width: 767.98px) {
  h3.h6 {
    /* --type-body's 16/24 pairing is identical at mobile, so the same value
       repeats here to beat the sitewide mobile `h3{line-height:1.75rem!important}`
       (28px) rule, which the desktop-scoped h3.h6 rule above cannot reach
       (browsers do not apply a later, unscoped declaration's specificity win
       across a media-query boundary the other rule sits inside). h3.h5 needs
       NO mobile override here: --type-h4 mobile is 18/24, but h3.h5 already
       renders 20/28 at mobile (the sitewide mobile h3 rule's own 1.25rem/28px
       coincidentally equals --type-h3's mobile pairing, not --type-h4's —
       this was already noted as correct-by-coincidence in the round 14
       critic report and is left untouched). */
    line-height: 24px !important;
  }
}

/* P12 round 13: index.html's page-local h3.h4 block (Task 6, 2026-08-23,
   same block described above) also sets line-height:1.3!important and
   letter-spacing:normal!important, which this stylesheet's font-size-only
   h3.h4 rule above doesn't touch, so those two properties still fall through
   to the page-local values (31.2px/23.4px, off the 4px grid, and 0 instead
   of -0.015em). font-size is intentionally NOT included here: lane-css-todo
   requires h3.h4 keep its pre-promotion size (24px desktop / 18px mobile,
   not the generic h3 token's own size), and that's already correct. Only
   line-height/letter-spacing follow the --type-h3 token. Scoped to `body
   h3.h4` (0,1,2) to beat the page-local block (0,1,1) regardless of source
   order, same pattern as the mobile font-size fix below. */
h3.h4,
body h3.h4 {
  line-height: 32px !important; /* on-grid; matches --type-h3 desktop */
  letter-spacing: -0.015em !important; /* -0.36px on this rule's 24px */
}

@media (max-width: 767.98px) {
  /* P12 round 14 fix: the block that used to live here shrank bare h3.h4 to
     1.125rem/18px on mobile, reasoning it "matched" index.html's own
     page-local h3.h4 override. It doesn't: index.html's page-local rule
     (`h3.h4{font-size:1.5rem!important;...}`, no media query) is unscoped,
     so it already renders 24px at every width, mobile included — it was
     never 18px there either. Bare .h4 is Bootstrap's non-responsive
     size-utility class (fixed 1.5rem regardless of viewport, unlike the
     --type-h4 *token*'s own 18px mobile step, which this selector was never
     meant to track), so 24px is the correct pre-promotion size at BOTH
     breakpoints for every bare h3.h4 sitewide. Grepped: only index.html (6
     instances, itself unaffected either way since 24px was already what its
     own page-local rule rendered) and subsidy-center.html (4 FAQ question
     headings, "How long does the subsidy take to arrive?" etc.) carry a
     bare h3.h4 anywhere on the site — subsidy-center's had no page-local
     history of its own and was being wrongly shrunk to an 18px/28px pairing
     that matches no declared --type step. Removing the shrink lets the
     unconditional (all-widths) `h3.h4, body h3.h4` rule above — 1.5rem font,
     32px line-height, -0.015em tracking, i.e. --type-h3 desktop's own
     pairing held at every width, matching Bootstrap .h4's real fixed-size
     behaviour — apply unchanged at mobile too, on both pages. */

  h3.h4.h5,
  body h3.h4.h5 {
    /* the unconditional desktop-tie-break rule above (h3.h4.h5: 1.25rem) is
       NOT scoped to a max-width and so is still active at mobile widths too,
       at higher specificity than h3.h4 alone (0,3,0 vs 0,2,0) — without this
       explicit mobile-scoped restatement it would keep winning here and the
       combo would stay at 20px instead of dropping to 18px like plain h3.h4.
    P12 round 14: at 18px final size, the combo's step is --type-h4 mobile
    (18/24), but line-height was still falling through to h3.h4's own mobile
    rule (28px, matching --type-h3 mobile) at higher specificity than this
    block alone — restated here at equal specificity to this rule's own
    font-size line, which already wins for the reason given above. */
    font-size: 1.125rem !important;
    line-height: 24px !important;
    letter-spacing: -0.01em !important;
  }

  h3.h6,
  body h3.h6 {
    font-size: 1rem !important;
  }

  /* h3.h5 (without .h4) needs no mobile override: the sitewide mobile
     h3{1.25rem!important} already equals .h5's own (non-important) 1.25rem,
     so h3.h5 already renders at the correct pre-promotion mobile size. */
}

/* ==========================================================================
   P12 round 4 — worst violation: .section-heading / .section-title
   (css/styles_v2.css:5383) sets its own clamp()-driven font-size,
   line-height:1.16 and letter-spacing:-0.015em completely independent of
   --type-h2 (32/40/-0.025em). Font-size already lands correctly on the
   token at both breakpoints (32px desktop, 26px mobile via the clamp), so
   only line-height and letter-spacing need correcting. letter-spacing is
   left as an em value on purpose: -0.025em resolves to -0.8px at the 32px
   desktop size and -0.65px at the 26px mobile size, matching both required
   px values from a single declaration. line-height needs the token's exact
   px step at each breakpoint (40/32, not a ratio), so it is pinned in px
   and stepped down at the same 767.98px boundary every other heading fix in
   this file uses. 72 instances / 12 files sitewide (industrial-solar-indore
   + 11 more), none previously covered by this stylesheet. */
.section-heading,
.section-title {
  line-height: 40px !important;
  letter-spacing: -0.025em !important;
}

@media (max-width: 767.98px) {
  .section-heading,
  .section-title {
    line-height: 32px !important;
  }
}

/* ==========================================================================
   P12 round 4 — index.html homepage h4s off the type scale entirely.
   Both page-local <style> blocks (lines ~1499, ~1889) sit AFTER this
   stylesheet's <link> in <head>, so matching selectors need !important to
   win back regardless of source order.

   .rsa-hw-body h4 (hardware cards: Bifacial modules / Silent smart
   inverters / Hurricane-proof structures / Uncompromised safety) was set
   at .95rem (15.2px) — under every step of the 9-step scale, well below
   --type-h4's 20px floor. line-height (28px, from the sitewide bare h4
   rule) was already correct and is left alone.

   .rsa-app-copy h4 (app-section titles, incl. the h4.h5-classed "Know
   before you invest" sibling, which the compound selector below also
   matches since it is itself an h4) was set at 1.4rem (22.4px) — an
   interpolated value that sits on no scale step at all, not 20 or 24.
   Both corrected to --type-h4's 20px (1.25rem) desktop.

   P12 round 5 critic fix: the desktop 1.25rem was applied unconditionally
   (no min-width), so at 390px the same 5 headings ("Bifacial modules",
   "Silent, smart inverters", "Hurricane-proof structures", "Uncompromised
   safety", "Know exactly where your system stands") still rendered at 20px
   instead of --type-h4's mobile step (18/24, 1.125rem). Scoped to
   min-width:768px to match every other desktop/mobile split in this file,
   with an explicit mobile !important restatement at 18px so it wins over
   the same page-local <style> blocks this rule already has to beat. */
@media (min-width: 768px) {
  .rsa-hw-body h4,
  .rsa-app-copy h4 {
    font-size: 1.25rem !important;
  }
}

@media (max-width: 767.98px) {
  .rsa-hw-body h4,
  .rsa-app-copy h4 {
    font-size: 1.125rem !important;
  }
}

/* ==========================================================================
   P12 round 4 — aboutus.html "our story" narrative copy, 6 instances in
   one page-local <style> block (and one matching inline style="" attribute)
   all setting 17px, an off-scale size between the --type-body (16) and
   --type-body-lg (18) tokens, with line-height 1.75 (29.75px) or 1.7
   (28.9px) — both off the 4 px grid. Moved down to the --type-body step
   (16/24px, both tokens share the same 24px line-height so this also holds
   the grid for a possible future --type-body-lg read). The attribute
   selector targets the one inline style="font-size:17px; line-height:1.7;"
   paragraph in the Manufacturing Excellence section by its exact string
   (grep-confirmed unique sitewide), since it carries no class of its own. */
.abt-story__copy p,
.abt-why__head p,
.abt-team__head p,
.abt-why__tile h5,
p[style*="font-size:17px; line-height:1.7;"] {
  font-size: 16px !important;
  line-height: 24px !important;
}

/* ==========================================================================
   P12 round 4 — sitewide inline style="font-size:1.05rem" on lead/intro
   <p> elements (calculator.html, industrial-solar-indore.html,
   pm-surya-ghar-subsidy.html, 3kw-solar-system-india.html + 22 more; 35
   instances / 26 pages, grep-confirmed). 1.05rem = 16.8px, an off-scale
   value sitting between the --type-body (16) and --type-body-lg (18)
   tokens. An attribute selector on the inline style is the one shared-CSS
   fix that reaches every instance without a page-by-page edit; !important
   is required and sufficient to win over an inline declaration that has no
   !important of its own. Moved to --type-body (16/24), the floor of the
   scale, since these are short lead-in labels/paragraphs rather than
   confirmed long-form lead copy. */
p[style*="font-size:1.05rem"] {
  font-size: 16px !important;
  line-height: 24px !important;
}

/* ==========================================================================
   P12 round 4 — contact-us.html .office-addr (4 office-address blocks):
   font-size 0.92rem (14.72px) and line-height 1.5 (22.08px) are both
   off-scale and off the 4 px grid. Treated as dense structured text (short
   address lines), mapped to --type-body-sm (14/20) rather than up to
   --type-body, since address lines are exactly the "dense UI... helper
   text" use case the token table names for that step. */
.office-addr {
  font-size: 14px !important;
  line-height: 20px !important;
}

/* ==========================================================================
   P12 round 4 — bare <h4> with no size-overriding class. The shared
   desktop h4 rule in css/styles_v2.css (~line 5345) sets line-height,
   weight and letter-spacing but never font-size, so it silently falls
   back to Bootstrap's own default (1.5rem / 24px) instead of --type-h4's
   20px. Scoped to min-width:768px only: the mobile h4 rule (~line 5917,
   inside styles_v2.css's own 767.98px query) already correctly pins h4 to
   18px, and an unscoped fix here at equal specificity + !important loaded
   after it would incorrectly override that already-correct mobile value
   back up to 20px. */
@media (min-width: 768px) {
  h4 {
    font-size: 1.25rem !important;
  }
}

/* ==========================================================================
   P12 round 5 — index.html .rsa-head h3 (3 headings: "Built to outlast a
   25-year loan.", "See it work, every single day.", "Live in 48 hours. Zero
   paperwork on you."). The page-local <style> block (line ~1514) sets
   `.rsa-head h3 { ...; letter-spacing:-.01em; ... }` with no !important;
   the sitewide bare `h3` rule in styles_v2.css already carries the correct
   --type-h3 tracking (-0.015em) but, also with no !important on that
   property, loses the tie to `.rsa-head h3` on specificity (0,1,1 beats
   0,0,1) regardless of source order. Font-size/line-height on this selector
   already resolve to the correct 24/32 (desktop) and 20/28 (mobile) via the
   sitewide bare h3 !important rules, so only letter-spacing needs fixing
   here. --type-h3's tracking (-0.015em) is a single value for both
   breakpoints, so one rule covers both. Site-wide grep: `rsa-head` appears
   only on index.html. */
.rsa-head h3 {
  letter-spacing: -0.015em !important;
}

/* ==========================================================================
   P12 round 5 — pm-surya-ghar-subsidy.html h2.h4.font-weight-bold.mb-4
   ("Why apply through r-solar?"). font-size (32px, from the sitewide bare
   `h2{font-size:2rem!important}` rule) and letter-spacing (-0.025em, from
   the sitewide bare h2 rule) already land on --type-h2, but line-height
   computes 38.4px (1.2 * 32px) instead of the required 40px: Bootstrap's
   own heading-utility rule (".h1,.h2,.h3,.h4,.h5,.h6,h1..h6{line-height:1.2}")
   carries the `.h4` class in its selector list, which beats the sitewide
   bare `h2{line-height:1.25}` rule (non-important) on specificity alone —
   the same collision pattern already fixed above for h3/h4 font-weight
   against `.font-weight-bold`. Pinned to the token's exact px step at each
   breakpoint, same pattern as every other heading fix in this file.
   Site-wide grep: this exact class combination is unique to this one
   page/heading. */
h2.h4 {
  line-height: 40px !important;
}

@media (max-width: 767.98px) {
  h2.h4 {
    line-height: 32px !important;
  }
}

/* ==========================================================================
   P12 round 7 (critic round 11 findings) — shared root causes for the
   remaining 10 violations, fixed as shared rules rather than page edits.

   1) .pmlf h3 — lead-form CTA heading, identical page-local <style> block
   on 22 pages sitewide (grep-confirmed): `.pmlf h3{font-weight:700;
   font-size:clamp(1.3rem,3vw,1.7rem);...}`. clamp() lands on no scale step
   at all (20.8-27.2px) and weight 700 is not the h3 token's 600. Every
   page's local block sits after this stylesheet's <link> in <head> at the
   same 0,1,1 specificity, so it wins on source order; `body .pmlf h3`
   (0,2,1) beats it regardless of order. Full h3 token applied (not just
   the two flagged properties) so the fix is complete against the token,
   not just against this round's two symptoms. */
body .pmlf h3 {
  font-size: 24px !important;
  line-height: 32px !important;
  font-weight: 600 !important;
  letter-spacing: -0.015em !important;
}

@media (max-width: 767.98px) {
  body .pmlf h3 {
    font-size: 20px !important;
    line-height: 28px !important;
  }
}

/* 2) h1.hero-title — the three case-study pages (industrial/residential/
   institutional) share an identical page-local `.hero-title{font-size:
   clamp(2.5rem,5vw,4rem);font-weight:700;...}` rule, landing at 56-64px
   desktop / well above 32px mobile instead of --type-h1 (44/48 desktop,
   32/40 mobile). One shared rule for the shared class fixes all three
   pages; index.html's own unrelated `.hero-title{font-size:3.5rem}` (a
   different page, not in this round's findings) is fixed by the same
   selector for free since it has the identical off-scale problem.
   `body .hero-title` (0,1,1) beats the page-local `.hero-title` (0,1,0)
   on specificity regardless of source order. */
body .hero-title {
  font-size: 44px !important;
  line-height: 48px !important;
  font-weight: 700 !important;
  letter-spacing: -0.03em !important;
}

@media (max-width: 767.98px) {
  body .hero-title {
    font-size: 32px !important;
    line-height: 40px !important;
  }
}

/* 3) .why-rsolar-card h3 — bare h3 (no size-utility class) used for stat
   numbers ("1500+", "5.5 MW+", "15-20 MW", "95%"), identical page-local
   rule on all 3 case-study pages: `font-size:2.5rem!important;
   font-weight:700;`, i.e. 40px/700 at every width with no mobile step at
   all — off every scale step, not mapped to any token. Mapped to
   --type-h3 (24/32/600/-0.015em), the only heading token available for a
   bare, unpromoted <h3>; there is no stat/metric token in the spec to map
   these to instead. `body .why-rsolar-card h3` (0,2,1) beats the
   page-local rule's (0,1,1 + !important) on specificity regardless of
   source order. */
body .why-rsolar-card h3 {
  font-size: 24px !important;
  line-height: 32px !important;
  font-weight: 600 !important;
  letter-spacing: -0.015em !important;
}

@media (max-width: 767.98px) {
  body .why-rsolar-card h3 {
    font-size: 20px !important;
    line-height: 28px !important;
  }
}

/* 4) subsidy-center h2.display-4.font-weight-bold.mb-3 ("Knowledge is
   savings"). Bootstrap's own .display-4 is already patched sitewide in
   styles_v2.css to land on --type-h1's 32px-equivalent font-size (correct,
   not touched here) and its mobile size (32px, correct for the h1 pages
   that also carry .display-4 — but this is the only h2.display-4 sitewide,
   so it wrongly inherits the h1 pages' mobile 32px instead of --type-h2's
   26px). Two independent defects: (a) Bootstrap's own heading-utility rule
   (".h1,.h2,.h3,.h4,.h5,.h6{line-height:1.2}") carries .display-4 in that
   same selector list, so line-height computes 1.2*32=38.4px instead of the
   token's flat 40px; (b) mobile font-size never steps down from the h1
   pages' 32px to h2's 26px. h2.display-4 (0,2,1) is already more specific
   than the sitewide `.display-4` patch (0,1,0), so no extra specificity
   boost or `body` prefix is needed — only !important to beat that rule's
   own !important. Scoped to the h2 tag so none of the ~35 h1.display-4
   pages (already correctly patched to h1 spec) are touched. */
h2.display-4 {
  line-height: 40px !important;
}

@media (max-width: 767.98px) {
  h2.display-4 {
    font-size: 26px !important;
    line-height: 32px !important;
  }
}

/* 5) subsidy-center h3.h4.mb-0 (4 FAQ question headings) and h3.resource-
   title (3 resource-card titles): both compute the wrong weight (500 and
   700 respectively) against the h3 token's required 600. h3.h4's existing
   rule above only restores the pre-promotion FONT-SIZE per lane-css-todo;
   weight was never part of that collision fix. Per the P12 round-1 note
   that shipped the h3.h4/h3.h5/h3.h6 rules ("font-weight 700->600 on these
   is fine — that's the h3 weight the spec calls for, not a regression"),
   every h3-tagged element takes the h3 token's 600 weight regardless of
   which size-utility class it also carries, so the weight fix belongs on
   the shared h3.h4/h3.h5/h3.h6/h3.h4.h5 rules, not as a one-off. Grep
   confirms plain (non-font-weight-bold, non-inline-styled) h3.h6 is also
   used sitewide (case-studies.html, environmental-impact.html,
   ppa-for-industry.html, r-solar-industrial-case-study.html) as ordinary
   subsection headings that need the same 600; `:not([style])` on h3.h6
   excludes the two genuine all-caps eyebrow instances (ppa-for-industry's
   "TYPICAL 5 MW FACILITY..." and solar-panel-cleaning-india's two
   "Study Details"/"Related Reading" labels) that carry their own inline
   caption-style overrides (uppercase, +0.08em tracking, small size) —
   those are the P1-exempt eyebrow case, not a violation, so they are left
   alone rather than forced onto the h3 token's weight/tracking. .resource-
   title has no promotion history and no collision — its own page-local
   rule (`font-weight:700`, no !important) is fixed directly. */
h3.h4,
h3.h5,
h3.h6:not([style]),
h3.h4.h5 {
  font-weight: 600 !important;
}

.resource-title {
  font-weight: 600 !important;
}

/* 6) ppa-for-industry.html's genuine eyebrow (h3.h6 with inline
   color/font-size/font-weight/text-transform/letter-spacing) is
   intentionally left untouched above via :not([style]) — it is a P1-exempt
   eyebrow, not a violation, and forcing h3's -0.015em/600 onto it would
   break its correct caption-style +0.08em/700 all-caps treatment. */

/* ==========================================================================
   P12 round 12 — §type "Minimum size, running text: 16 px. Never smaller."
   5 violations, none on the closed P1-exemption list (eyebrow/breadcrumb/
   caption/byline/input-hint/trust-chip): full sentences of running copy
   sitting under the floor. Fixed at the shared-selector root cause instead
   of per-page, same pattern as every earlier P12 round.

   1) index.html .hero-lead — the homepage's primary hero paragraph, above
      the fold. Desktop (1.25rem/20px) already clears the floor and is left
      alone; only the mobile override (page-local <style>, line ~848) drops
      it to 0.95rem (15.2px), under both the 16px floor and --type-body-lg's
      own mobile step (17/24). That page-local block sits after this
      stylesheet's <link> (line 920 vs 829) with its own !important, so
      matching it here needs !important too to win back regardless of
      source order. Moved to --type-body-lg's mobile values (17/24): this
      is lead copy, not default body text. */
@media (max-width: 767.98px) {
  .hero-lead {
    font-size: 17px !important;
    line-height: 24px !important;
  }
}

/* 2) contact-us.html .office-addr (4 office-address blocks). P12 round 4
   deliberately mapped this to --type-body-sm (14/20) as "dense structured
   text", reasoning an address block was closer to a table cell than to
   prose. The round-12 critic correctly rejects that: it is not on the
   closed exemption list (not an eyebrow, breadcrumb, caption, byline,
   input-hint or trust-chip), so the 16px floor applies regardless of how
   dense the content looks. Raised to --type-body (16/24), the floor of the
   scale — this supersedes the round-4 rule below by appearing later in the
   same file at equal specificity. */
.office-addr {
  font-size: 16px !important;
  line-height: 24px !important;
}

/* 3) aboutus.html p.small.text-white-50 — the two "Subsidies, financing,
   installation..." / "We answer calls. We follow up. Every time." sub-lines
   under the trust-strip headings. Bootstrap's .small utility (0.875em, no
   !important) renders these at 14px. They are full sentences, not a caption
   or trust-chip (which the P1 exemption list already covers separately) —
   borderline feature-caption in tone but not literally caption-classed, so
   per "when in doubt, count it" they are running text and need the floor.
   Scoped to the exact class combination (small + text-white-50, no other
   selector on this site pairs them) so ordinary .small usage elsewhere
   (breadcrumbs, eyebrows, chips already exempt) is untouched. */
p.small.text-white-50 {
  font-size: 16px !important;
  line-height: 24px !important;
}

/* 4) calculator.html's WhatsApp CTA line ("Got a question? WhatsApp us at
   +91 94070...") — a full sentence with a live phone number, set via an
   inline style="font-size:0.92rem" (14.72px, no line-height declared, so it
   inherits the sitewide default). Attribute selector on the inline style
   string, the same technique already used above for
   p[style*="font-size:1.05rem"] and p[style*="font-size:17px..."], since
   this paragraph carries no class of its own to hang a rule off. */
p[style*="font-size:0.92rem"] {
  font-size: 16px !important;
  line-height: 24px !important;
}

/* 5) p.text-muted.small.text-center.mt-2 — the calculator disclaimer/CTA
   line repeated on 16 pages (commercial-solar-*, industrial-solar-*,
   solar-in-* templates; industrial-solar-indore sampled directly, the
   other 15 confirmed by grep of the identical class string), e.g. "Based
   on 5.2-5.5 kWh/m²/day solar irradiation..." Bootstrap's .small utility
   renders it at 14px with no explicit line-height. One shared class
   selector reaches all 16 pages / every instance of the pattern from this
   file, the same shared-root-cause approach as every fix above. */
p.text-muted.small.text-center.mt-2 {
  font-size: 16px !important;
  line-height: 24px !important;
}

/* 6) p.small.text-muted.text-center.mt-4 — the "Prefer to run/check the
   numbers yourself first? Use our solar savings calculator." CTA subtext
   on 3kw-solar-system-india.html and best-solar-panels-india.html (P12-r13
   critic finding). This is a full sentence, not a caption/eyebrow/chip, so
   it does not qualify for the P1 short-text exemptions and must clear the
   16px running-text floor. Same mt-2 pattern above, different margin
   utility (mt-4 not mt-2), so it falls outside that selector. */
p.small.text-muted.text-center.mt-4 {
  font-size: 16px !important;
  line-height: 24px !important;
}

/* ==========================================================================
   P12 round 14 — h2.h5.font-weight-bold shared root cause (critic finding,
   worst + 1 more). Same collision as the h2.h4 fix above (round 5):
   Bootstrap's own heading-utility rule (".h1,.h2,.h3,.h4,.h5,.h6,h1..h6
   {line-height:1.2}") carries the `.h5` class in its selector list, which
   beats the sitewide bare `h2{line-height:1.25}` rule (non-important) on
   specificity alone, landing line-height at 38.4px (1.2*32px) instead of
   the required 40px / 32px steps. font-size and letter-spacing already
   land on --type-h2 via the sitewide bare h2 rules once no inline
   font-size override is present, so only line-height needs fixing here.
   `:not([style*="font-size"])` excludes the one other sitewide h2.h5
   instance that is a deliberately small, inline-sized eyebrow line
   (c-and-i-solar-calculator.html "Your Savings Estimate", 0.85rem
   uppercase eyebrow — a P1-exempt short label, not running heading text),
   so this rule cannot force a 40px line-height onto a 13.6px eyebrow.
   Covers downloads.html's 4 "Product Brochure / Residential Booklet /
   Commercial Booklet / ₹0 Solar Scheme Flyer" headings and
   net-metering-mp.html's "Quick reference" h2 (whose own inline
   `font-size:1.25rem !important` override was removed directly in the
   page's HTML this round, since it fully defeated the h2 token and was
   grep-confirmed unique sitewide to that one element). */
h2.h5.font-weight-bold:not([style*="font-size"]) {
  line-height: 40px !important;
}

/* P12 exhaustive-mode scan (round 14): the two h2.h5/h2.h6 instances this
   file's `:not([style*="font-size"])` guard above deliberately excludes —
   c-and-i-solar-calculator.html's "Your Savings Estimate" (h2.h5, inline
   font-size:0.85rem, +0.08em uppercase eyebrow) and "Calculator
   Assumptions" (h2.h6, inline font-size:0.88rem caption label) — were
   assumed correct by that guard's own comment ("cannot force a 40px
   line-height onto a 13.6px eyebrow") on the theory that an inline
   font-size beats any external rule. It does not: css/styles_v2.css:1996's
   sitewide `h2 { font-size: 2rem !important; }` carries !important, and
   !important beats a plain inline declaration regardless of specificity,
   so both elements were actually rendering at 32px (2rem) the whole time —
   an oversized eyebrow/caption, not the small label the page's own markup
   asks for. Restoring each element's own already-declared inline value at
   matching specificity (element+2 classes+attribute, !important) fixes the
   actual regression without touching the HTML. Line-heights are the
   nearest on-4px-grid value to each element's original ratio (~1.2); these
   are decorative micro-labels below --type-caption's own 12px floor by
   design (a deliberately smaller eyebrow/kicker), not a declared scale
   step, so no step-pairing claim is made for them the way the other rules
   in this file make for real heading/body sizes. */
h2.h5.font-weight-bold[style*="font-size:0.85rem"] {
  font-size: 0.85rem !important;
  line-height: 16px !important;
}

h2.h6.font-weight-bold[style*="font-size:0.88rem"] {
  font-size: 0.88rem !important;
  line-height: 20px !important;
}

@media (max-width: 767.98px) {
  h2.h5.font-weight-bold:not([style*="font-size"]) {
    line-height: 32px !important;
  }
}

/* ==========================================================================
   P12 round 17 (final round, expanded scope). This round's task added the
   coverage-audit's layout-spacing-agents group (non-icon) and
   icons-and-type-legibility's type items on top of the closed §type-sizing
   checks r0-r16 already cleared. Two categories below are sitewide layout
   issues (Bootstrap's own .container/.container-fluid 15px side padding,
   and the unmodified Bootstrap 576/768/992/1200 breakpoint set) that are
   deliberately NOT fixed here: fixing either means editing
   css/bootstrap.min.css or css/styles_v2.css's grid usage, which is outside
   this lane's CSS ownership (rs-type.css only). Correction (P12 round 12):
   these are NOT queued in review-queue.md — that file's schema is for
   wording changes (current text / proposed text), which doesn't fit a CSS
   ownership gap, and no such rows exist there. The accurate status is: flag
   to the lead as an open item for whichever lane/round owns
   bootstrap.min.css or styles_v2.css's grid usage, not "queued". Everything
   else below is fixed at the shared root cause.
   ========================================================================== */

/* 1) .breadcrumb-item / .breadcrumb-item a touch target (worst finding).
   Measured 22px tall (38-114px wide) at BOTH 1280px and 390px on every
   page with breadcrumbs (33 sitewide) — this is not a mobile-only gap, so
   R8's global 44x44pt/48x48dp floor applies at every width, not just
   "below md". Bootstrap's own .breadcrumb-item only sets padding-left
   (.5rem); styles_v2.css's override only sets font-size (14px). Neither
   sets a height/padding rule, so the li (and its one real interactive
   child, the <a>) sit at the raw text line-height. Both selectors get
   display:inline-flex + align-items:center + min-height so the anchor's
   own hit box — not just the surrounding row — clears 48px, matching the
   §layout Touch rule's dp value. The active (non-link) crumb gets the
   same min-height purely so the row's baseline stays visually aligned;
   it carries no separate touch-target obligation since it has no <a>. */
.breadcrumb-item {
  display: inline-flex;
  align-items: center;
  min-height: 48px;
}
.breadcrumb-item a {
  display: inline-flex;
  align-items: center;
  min-height: 48px;
}

/* 2) news.html .read-more-btn.stretched-link (27 instances/1 page).
   Measured 26px tall x 107-154px wide — already inline-flex/align-items
   center in the page's own <style> block, just missing a height floor.
   Page-local fix (page-unique class, not used elsewhere sitewide). */

/* 3) contact-us.html .why-rs__sub / .rs-cta__sub: page-local inline sizes
   of 1.06rem/1.65 (16.96px/27.98px) and 1.08rem/1.6 (17.28px/27.65px) sit
   off every scale step and off the 4px grid. Both sit between --type-body
   (16) and --type-body-lg (18) — same shape as the round-4 aboutus/1.05rem
   fixes above — so, per that established precedent, they move down to the
   --type-body floor (16/24) rather than up, since neither is confirmed
   long-form lead copy. */
.why-rs__sub,
.rs-cta__sub {
  font-size: 16px !important;
  line-height: 24px !important;
}

/* 4) index.html's two testimonial-quote paragraphs
   (`.lead.mb-4.text-brand-dark`, "I ..." quotes from Yash Patidar and Musa
   Khan) carry an inline style="font-size: 1.1rem; line-height: 1.6;"
   (17.6px / 28.16px) — off-scale and off-grid, grep-confirmed unique to
   these 2 instances on index.html. Same 16/24 floor treatment as #3 above.
   Round 20: this rule restated font-size/line-height (correctly landing
   on --type-body) but never reset letter-spacing, so the element kept
   inheriting Bootstrap's `.lead` tracking (-0.01em) instead of
   --type-body's own tracking (0) — the type-scale table specifies size,
   line-height, weight AND tracking together per step, not size/line-
   height alone. */
p[style*="font-size: 1.1rem; line-height: 1.6;"] {
  font-size: 16px !important;
  line-height: 24px !important;
  letter-spacing: 0 !important;
}

/* 5) index.html's "1,500+ rooftop installations..." stat line
   (`p.mb-0.text-muted.font-weight-bold.h6`, grep-confirmed unique sitewide
   to this exact class combination — the visually similar
   `.font-weight-bold.mb-0.text-brand-dark.h6` name-credit lines under the
   testimonials above are a different combination and are NOT in scope).
   font-size already lands on --type-h6/body (16px, correct); only
   line-height is off-grid, inherited from the sitewide bare
   `h5, h6 { line-height: 1.3 }` rule (16 * 1.3 = 20.8px) instead of the
   required 24px. */
p.mb-0.text-muted.font-weight-bold.h6 {
  line-height: 24px !important;
}

/* 6) calculator.html's "Prefer to read first? Get our free MP solar
   handbook." line (`p.small.text-muted.text-left.mb-2.font-weight-bold`,
   grep-confirmed unique to this page). A full-sentence CTA, not one of the
   closed P1 exemptions (eyebrow/breadcrumb/caption/byline/input-hint/
   trust-chip), so Bootstrap's .small (14px, no !important) must be raised
   to the 16px running-text floor. */
p.small.text-muted.text-left.mb-2.font-weight-bold {
  font-size: 16px !important;
  line-height: 24px !important;
}

/* ==========================================================================
   Round 13 — two violations from the round-12 critic, fixed at the shared
   root cause (one rule each in this stylesheet, not per-page edits).
   ========================================================================== */

/* 7) Worst finding: header Solutions/Subsidy-and-savings nav dropdown items
   ("For Homes", "For Industry", "How It Works", "Case Studies", "Contact
   Us", etc.) carry a page-local inline style="padding:0.6rem 1.2rem;
   font-size:0.9rem;" (14.4px) on the shared header markup included on 72
   sitewide pages. styles_v2.css only raises `.navbar-nav .dropdown-item` to
   0.95rem !important (still off-scale) inside its `@media (max-width:
   991.98px)` block, so above 992px nothing overrides the inline 0.9rem at
   all, and the running-text floor (16px, never smaller) is missed at both
   the sampled desktop and mobile widths. Fixed once here for every page
   that shares the header: !important beats the non-important inline
   font-size regardless of width, so no media query is needed. line-height
   is set to the --type-body value (24px) since none was specified inline
   and the item text is running nav copy, not a caption/chip/eyebrow. */
.navbar-nav .dropdown-item,
.dropdown-item {
  font-size: 16px !important;
  line-height: 24px !important;
}

/* 8) Off-scale/interpolated comparison-table text: `<table style="font-
   size:0.95rem...">` (15.2px, between --type-body-sm's 14px and --type-body's
   16px — the §type rule against interpolating new steps) on aboutus.html
   (2 tables), how-to-choose-solar-installer-mp.html, net-metering-mp.html
   and pm-surya-ghar-bank-loan-list.html. These are dense data tables
   (district/year breakdowns, bank-loan comparison rows), the exact use case
   --type-body-sm names ("dense UI, table cells"), so they move onto that
   token exactly rather than up to --type-body — a table is not running
   prose and 14px still clears both the 12px absolute floor and the
   §type table use-case. line-height moves to --type-body-sm's 20px to stay
   on the 4px grid together with the size change. */
table[style*="font-size:0.95rem"] {
  font-size: 14px !important;
  line-height: 20px !important;
}

/* ==========================================================================
   P12 round 11 — critic re-flagged the same interpolated-table-text family
   (spec §type: "--type-body-sm | 14/20 | Dense UI, table cells, helper
   text." + "Scale ratio ... Do not interpolate new steps."), found via the
   exhaustive full-sitemap sweep rather than a sample:

   1) `.cost-table` (page-local class, one identical `.cost-table{font-size:
      0.95rem}` <style> block repeated on 21 sitemap pages / 55 table
      instances — cost/spec comparison tables on every *kw-solar-system-india
      page, panel-tech pages, pm-surya-ghar-yojana-login.html, etc.).
      15.2px sits between --type-body-sm (14) and --type-body (16), the exact
      "do not interpolate" violation. A single class-selector rule here
      reaches every page that ships the class without editing 21 page-local
      <style> blocks; !important is required since rs-type.css's <link> loads
      before each page's own <style> block, so the page-local rule would
      otherwise win the source-order tie at equal (0,1,0) specificity. Two
      further sitewide `.cost-table` pages (almm-list-decoded.html,
      solar-panel-cost-mp.html) carry no page-local font-size override at all
      and were already rendering at the unstyled 16px default (--type-body,
      already on-scale) — this rule intentionally brings them to the same
      14/20 dense-table treatment as the other 19 for one consistent
      sitewide table style, not because they were previously in violation.

   2) `table[style="font-size: 0.95rem;"]` (pm-surya-ghar-subsidy.html, one
      cost-comparison table) — the exact family the rule above (8) already
      fixed, but with a space after the colon that the existing
      `[style*="font-size:0.95rem"]` substring selector does not match. This
      is the gap the sampled critic rounds missed and the exhaustive sweep
      caught: same 15.2px value, same fix.

   3) `table[style="font-size:0.92rem;"]` (calculator.html, 2 EMI-comparison
      tables) — 14.72px, the same interpolated-step violation one step lower
      (between 14 and 16, closer to 14). Same dense-table use case, same
      --type-body-sm target. */
.cost-table,
table[style*="font-size: 0.95rem"],
table[style*="font-size:0.92rem"] {
  font-size: 14px !important;
  line-height: 20px !important;
}

/* ==========================================================================
   P12 round 13 — p.small.text-white.mt-3.mb-0.opacity-80 (critic finding,
   worst + only remaining item). index.html homepage hero, above the fold:
   "Results in 30 seconds • No commitment required" under the primary CTA
   buttons. Full-sentence CTA reassurance copy, not an eyebrow, breadcrumb,
   caption, byline, input hint or short trust chip, so it does not qualify
   for the P1 exemptions and must clear the 16px running-text floor like the
   other two CTA-subtext class combos already fixed above (.mt-2 / .mt-4).
   Bootstrap's .small utility renders it at 14px (0.875rem) with no explicit
   line-height; this distinct combo (text-white + mt-3 + opacity-80) was
   never covered by either of those rules or any prior P12 round. One page /
   one instance, fixed at the shared class selector per the lead's
   "shared rule beats page edits" guidance. */
p.small.text-white.mt-3.mb-0.opacity-80 {
  font-size: 16px !important;
  line-height: 24px !important;
}

/* ==========================================================================
   P12 exhaustive scan (round 14): commercial-industrial-solar.html's
   page-local `.cix-sec h2{font-size:clamp(1.6rem,3vw,2.2rem);...
   line-height:1.2;...}` (10 section h2s: "Three things happen...", the
   three PPA-type card titles, etc.) already resolves font-size to --type-h2's
   32px at desktop / ~26px at mobile via its own clamp() (unrelated font-size
   fix from an earlier round, left as-is), but its own line-height:1.2 is
   non-important and never had an equally-specific overriding rule, so it
   computes 38.4px (1.2*32) at desktop instead of the required 40px, and the
   equivalent mobile mismatch at 1.2*~26=~31.2 instead of 32px. Same
   collision family as every other page-local-clamp fix in this file (see
   the h2[style*="clamp(1.5rem, 3vw, 2rem)"] rule above); `body .cix-sec h2`
   bumps specificity to win regardless of source order, matching that
   pattern. One page, 10 instances, one shared rule. */
.cix-sec h2,
body .cix-sec h2 {
  line-height: 40px !important;
}

@media (max-width: 767.98px) {
  .cix-sec h2,
  body .cix-sec h2 {
    line-height: 32px !important;
  }
}

/* Same page, one more instance outside .cix-sec: the lead-form section's
   `<h2 style="font-size: clamp(1.6rem, 3vw, 2.4rem); ... line-height: 1.2;
   ...">Is your facility eligible?...` ("ci-lead-form"). Its own clamp()
   preferred value (3vw = 38.4px at 1280px, sitting right at the 2.4rem/
   38.4px max) never actually renders, because css/styles_v2.css:1996's
   sitewide `h2{font-size:2rem!important}` beats the inline (non-important)
   font-size outright - so it renders at 32px (--type-h2's own desktop size,
   correct by the same coincidence as the h2.h5/h2.h6 eyebrow fix above) with
   the inline line-height:1.2 (38.4px) never challenged. Attribute-matched
   to this element's own already-unique inline value, same pattern as the
   other inline-style targeted fixes in this file. */
h2[style*="clamp(1.6rem, 3vw, 2.4rem)"] {
  line-height: 40px !important;
}

@media (max-width: 767.98px) {
  h2[style*="clamp(1.6rem, 3vw, 2.4rem)"] {
    line-height: 32px !important;
  }
}

/* ==========================================================================
   P12 round 15 — worst finding: §layout "Measure" / §type "Measure" rule
   (--measure: 68ch, max 68 characters, regardless of container width) was
   scoped to <p> only when this stylesheet's opening Measure rule shipped;
   <li> was never covered, so running-text list items (FAQ answers,
   eligibility bullets, T&C clauses) still stretch to the full content
   column. ~41 instances / 3 pages confirmed by computed measurement at
   1280px: net-metering-mp.html eligibility/FAQ bullets (~880px column,
   ~100 chars/line), privacy-policy.html T&C bullets (~1070px column,
   ~130 chars/line), pm-surya-ghar-bank-loan-list.html bank-loan bullets
   (~95-105 chars/line).

   Every classed <li> sitewide is a UI-role list — grep-confirmed exhaustive:
   nav-item / dropdown(-item/-header) / breadcrumb-item / breadcrumb-sep /
   list-inline-item / step-item / page-item, all short label/link text that
   was never near 68ch — while every running-text bullet on these (and any
   other) page is a bare <li> with no class, or carries only a spacing
   utility (mb-*, mt-*, font-weight-bold). One shared selector excluding the
   UI roles reaches every current and future running-text list without
   constraining any navigational or chip-style list, the same shared-rule
   pattern the <p> Measure rule above already uses. Wrapped in :where(),
   same as the <p> rule above and for the same reason: zero specificity so
   any page-local <li> rule that sets its own (narrower) max-width keeps
   winning, and this only ever fills in where nothing more specific set one. */
:where(li):not(.nav-item):not(.dropdown):not(.dropdown-item):not(.dropdown-header):not(.breadcrumb-item):not(.breadcrumb-sep):not(.list-inline-item):not(.step-item):not(.page-item) {
  max-width: var(--measure);
}

/* Same Measure rule for <td>, found by the exhaustive scanner's measure
   check: net-metering-mp.html's regulation-explainer table has a bare,
   unclassed <td> ("Lowest solar (or wind) tariff discovered in Madhya
   Pradesh bidding in the preceding financial year") that renders at ~74ch
   in its column. :where() again so any table that deliberately sets its
   own (narrower) cell width keeps winning; this only fills in where
   nothing more specific already constrains the cell. */
:where(td) {
  max-width: var(--measure);
}

/* P12 round 16 — root cause of the round-15 fix above not actually landing:
   max-width on a <td> is a no-op for column sizing while the table itself
   uses the browser default table-layout:auto, which sizes each column from
   its content's natural (unwrapped) width before any max-width on the cell
   is consulted. net-metering-mp.html's "How unused units are paid out"
   table (bare <td>, no page-local width/class) kept rendering its longest
   cell ("Lowest solar (or wind) tariff discovered in Madhya Pradesh bidding
   in the preceding financial year") at ~639px/~70ch regardless of the
   --measure max-width above — the only known instance sitewide (exhaustive
   scan of all 69 sitemap pages), so fixed at the table rather than widening
   the shared bare-td rule's scope. table-layout:fixed forces the browser to
   honour column widths instead of content width, so the label column's
   explicit width plus the value column's overflow-wrap actually keep the
   value column under the 585px/68ch cap. New class, this lane's HTML only;
   the rule itself lives here per lane ownership. */
.rs-measure-table {
  table-layout: fixed;
  /* Bootstrap's `.table{width:100%!important}` forces the table to fill its
     container; under table-layout:fixed that leftover width past the two
     explicit column widths below gets redistributed proportionally across
     columns per spec, so the value column kept exceeding --measure even
     with its own explicit width set. width:auto lets the table size itself
     to its columns' own widths instead (still never wider than the
     container, since a table can't overflow one it isn't told to). */
  width: auto !important;
}

.rs-measure-table td:first-child {
  width: 220px;
}

/* table-layout:fixed distributes any width NOT explicitly set on a column
   across the table's own width (100% of its container by Bootstrap's
   .table default), so an explicit width is needed on the value column too
   — max-width alone (the round-15 :where(td) rule above) is still not
   consulted for column sizing even under fixed layout unless the column's
   own width resolves within it. --measure caps it directly; the label
   column above is far under it already. */
.rs-measure-table td:last-child {
  width: var(--measure);
  max-width: var(--measure);
}

.rs-measure-table td {
  overflow-wrap: break-word;
  word-break: break-word;
}

@media (max-width: 767.98px) {
  .rs-measure-table td:first-child {
    width: 40%;
  }

  .rs-measure-table td:last-child {
    width: auto;
  }
}

/* Round 12 fix — §type scale table (--type-body 16/24) + "Every
   line-height lands on the 4 px grid": bare, unclassed <td> cells in the
   14 city subsidy/savings-comparison location-template pages
   (commercial-solar-*, industrial-solar-*, solar-in-* — each carries a
   page-local `.<prefix>-subsidy__table { font-size: 1rem; }` rule with no
   line-height of its own on its td) render at 16px font-size but inherit
   body's line-height:1.6 (25.6px) from styles_v2.css instead of the
   required 24px, off the 4px grid. 276 confirmed instances across 14
   pages via computed style (e.g. industrial-solar-pithampur.html td
   "50 kW" -> fs:16px, lh:25.6px). :where() again, so any table that
   deliberately sets its own line-height on td (none currently do) keeps
   winning; this only fills the gap for the common case of a bare running-
   text cell whose font-size resolves to the --type-body step. */
:where(td) {
  line-height: 24px;
}

/* ==========================================================================
   P12 round 15 — §type Rules table: "Minimum size, running text. 16 px.
   Never smaller." `p.small.text-muted.mb-0` full-sentence card/feature
   descriptions (r-solar-industrial-case-study.html, r-solar-institutional-
   case-study.html, r-solar-residential-case-study.html, solar-panel-cost-
   mp.html, sbi-pm-surya-ghar-solar-loan.html, pm-surya-ghar-yojana.html;
   ~17 instances) render at Bootstrap's sitewide `small,.small{font-size:
   14px!important}` instead of the 16px floor: these are full sentences
   ("Capital better deployed in core operations...", "Step-by-step
   application process for MP homeowners"), not one of the closed P1
   exemptions (eyebrow/breadcrumb/caption/byline/input-hint/trust-chip).

   The identical class string (`small text-muted mb-0`) also renders the
   sitewide footer copyright line ("© 2026 r-solar. All rights reserved.")
   on ~50 other pages — that IS the correct P1-exempt byline/copyright use
   (established precedent, same rule other P12 rounds already applied to
   other byline text) and must stay at 14px, so raising the general
   selector to 16px would regress it. Scoped with `:not(footer *)` so the
   footer instance falls through to Bootstrap's own 14px/20px untouched,
   while every card-description instance elsewhere gets the floor. */
p.small.text-muted.mb-0:not(footer *) {
  font-size: 16px !important;
  line-height: 24px !important;
}

/* ==========================================================================
   P12 round 11 (EXHAUSTIVE MODE) — extending scan_P12.py to check every
   running-text element's line-height (not just <p>) and every heading's
   weight/letter-spacing (not just its size/line-height pair) surfaced one
   large, previously-invisible category, plus the round's own critic list
   (worst: footer li 25.6 not 24; body-lg running text 31.68 not 24;
   breadcrumb 22.4 not 20; trust chips 24 not 20; bare h3 weight 700 not
   600). The shared root cause behind almost all of it: a class rule that
   sets font-size but not line-height falls through to whichever bare-
   element line-height happens to apply — body's own `line-height:1.6`
   ratio for <li> (nothing had ever set <li> line-height directly, only
   its max-width via the Measure rule above), or the sitewide bare
   `p{line-height:24px}` rule for every smaller-than-16px <p> (eyebrows,
   captions, trust chips) regardless of that <p>'s own class-set size —
   instead of the size's OWN token line-height. lane-css-todo.md's h3.h4/
   h3.h5/h3.h6 promoted-heading sizes were already applied in earlier
   rounds (see the h3.h4/h3.h5/h3.h6 rules above); the "bare h3 weight 700"
   finding is a DIFFERENT, previously-unfixed gap: the sitewide bare
   `h3{font-weight:600}` (no !important) loses to any page-local ancestor-
   scoped selector (`.rsa-head h3`, `.rs-feat h3`) or inline style that
   sets font-weight:700, on specificity/inline priority.
   ========================================================================== */

/* 1) WORST FINDING: running-text <li>/<dd> at body/body-lg sizes (16px,
   17.6-18px) sitewide render at body's own line-height ratio (1.6 -> 25.6px
   on 16px text) or a page-local container ratio (e.g. `.blog-content
   {line-height:1.8}` -> 31.68px on its 17.6px text) because nothing had
   ever set <li>/<dd> line-height directly. --type-body and --type-body-lg
   share the same 24px line-height at both breakpoints, so one shared value
   covers every 16-18px running-text <li>/<dd> sitewide at once: footer
   nav/office links, FAQ/eligibility/spec bullets, nav dropdown menu rows.
   :where() keeps this non-destructive (any page-local <li> rule that
   already sets its own line-height keeps winning), same pattern as the
   Measure rule above. Breadcrumb roles render at 14px (--type-body-sm,
   20px line-height, fixed separately in #2) so they're excluded here. */
:where(li, dd):not(.breadcrumb-item):not(.breadcrumb-sep) {
  line-height: 24px;
}

/* 2) Breadcrumb crumbs/separators (14px, --type-body-sm) inherit body's
   1.6 ratio (22.4px) for the identical reason as #1 — styles_v2.css's
   `.breadcrumb, .breadcrumb-item{font-size:14px}` sets size only, never
   line-height. 33 pages sitewide (round-11 critic finding #3). */
.breadcrumb-item,
.breadcrumb-sep {
  line-height: 20px !important;
}

/* 3) Trust-chip / reassurance / meta <p> at ~14px (--type-body-sm, 20px
   line-height) inherit the sitewide bare `p{line-height:24px}` rule
   (round-11 critic finding #4: .pmlf__trust/.rs-cta__trust at 24 not 20),
   since that bare rule only loses to a class rule that sets its OWN line-
   height, and every one of these only ever sets font-size. Grouped with
   every other ~13-14.4px trust/meta/label <p> class the exhaustive scan
   found in the identical shape (all page-local <style> blocks, all set
   font-size only, all grep-confirmed to the exact page/count named): */
.pmlf__trust,
.rs-cta__trust,
.cix-reassure,
.blog-meta,
.hero-meta,
.progress-title,
p.nm-toc-title.nm-toc-toggle,
p.font-weight-700.mb-1.text-dark,
p.font-weight-700.text-dark.mb-3,
p.font-weight-bold.mb-4:not(.lead),
p.mb-0.font-weight-bold.text-white,
p.font-weight-bold.text-muted.mb-3,
p[style*="color:rgba(255,255,255,0.7);font-size:0.9rem;"] {
  line-height: 20px !important;
}

/* 4) Caption-role <p> (eyebrows, section labels, legal/hint captions) at
   12-12.8px (--type-caption, 16px line-height) inherit the same sitewide
   bare `p{line-height:24px}` rule as #3, one step down the scale.
   `[class*="eyebrow"]` alone reaches every one of the ~20 page-local
   `*-hero__eyebrow` / `*-eyebrow` classes the exhaustive scan found (one
   per city/vertical landing page, identical 12-12.8px shape, grep-
   confirmed) without listing all of them by name. `.cap`/`.h` are exact
   single-class selectors (not substring matches) already named in
   scan_P12.py's own EXACT_EXEMPT_CLASSES as caption-role by established
   precedent (legal caveat text / section-intro kicker). The two
   `p[style*="..."]` attribute selectors reach two more bare, page-local
   *unclassed* eyebrow-style <p>s the scan found, matched to the exact
   shared inline-style fragment confirmed present on all 14 (chip pattern)
   and 2 (cluster-label pattern) template pages respectively, the same
   `p[style*="..."]` pattern already used elsewhere in this file. */
[class*="eyebrow"],
.section-label,
.input-hint,
.form-note,
.cap,
.h,
p[class="mb-0 text-white"],
p[style*="font-size:0.75rem;font-weight:700;letter-spacing:.12em"],
p[style*="color:#72BF44; font-size:12px; font-weight:700; letter-spacing:2px;"],
p[style*="color:var(--rs-green-text, #3B7020);font-size:.8rem;font-weight:600;letter-spacing:.08em"],
p[style*="font-size:.8rem;color:rgba(255,255,255,.7);margin:0 0 .6rem;"] {
  line-height: 16px !important;
}

/* 5) Bootstrap's `.small`/`small` utility (14px, correctly at --type-
   body-sm's 20px by default - e.g. news.html's plain `p.small.text-muted
   .mb-2` byline dates, left untouched) combined with an inline `style=
   "font-size:1rem !important;"` that pushes the SAME class combination
   back up to 16px on other pages keeps Bootstrap's own 20px line-height
   instead of following the size back up to --type-body's 24px. Scoped to
   the inline-style attribute, not the bare class combination, so the
   many correct 14px/20px instances of this exact class string elsewhere
   (news.html) are untouched - round 11's first attempt at this rule used
   the bare class and regressed those 14px instances to 24px sitewide. */
p.small.text-muted.mb-2[style*="font-size:1rem !important;"],
p.mb-2.text-muted.small[style*="font-size:1rem !important;"] {
  line-height: 24px !important;
}

/* 6) Two testimonial name-credit <p>s (`.h6` micro-heading style) on
   index.html inherit the sitewide bare `h5, h6 { line-height: 1.3 }` rule
   (16 * 1.3 = 20.8px) via the `.h6` utility class, instead of --type-
   body's 24px — same collision shape as the round-4/round-15 `.h6`-classed
   <p> fixes above, just two more instances the exhaustive scan found. */
p.font-weight-bold.mb-0.text-brand-dark.h6,
p.clr-green.h6 {
  line-height: 24px !important;
}

/* 7) A card stat line (`li.mt-3.font-weight-bold`, "ROI Time: ~5 Years"
   pattern, system-size-mistake.html) picks up `.font-weight-bold`'s own
   ancestor context line-height (28.8px) instead of #1's shared <li> fix
   above, because this exact class combination carries page-local
   specificity higher than :where(li). Restated explicitly. */
li.mt-3.font-weight-bold {
  line-height: 24px !important;
}

/* 8) Two DIFFERENT bare, inline-styled <p>s on the same 14 city/vertical
   template pages (industrial-solar-*, commercial-solar-*, solar-in-*)
   each carry their own inline line-height that survives even though the
   sitewide bare `p{line-height:24px}` rule would otherwise correct it —
   inline beats a non-!important stylesheet rule regardless of
   specificity. Both exact shared fragments grep-confirmed present
   verbatim on all 14 pages: `.text-muted.mt-3`'s own descriptive
   paragraph (`style="line-height:1.7;"`, 27.2px) and a second, page-
   local-style-only paragraph with no distinguishing class at all
   (`style="color:#8a9bb8; line-height:1.6; margin-bottom:1.5rem;"`,
   25.6px). */
p[class="text-muted mt-3"][style*="line-height:1.7;"],
p[style*="color:#8a9bb8; line-height:1.6; margin-bottom:1.5rem;"] {
  line-height: 24px !important;
}

/* 9) Bare, non-utility-classed <h3>/<h4> render at font-weight 700 instead
   of the token's 600 (round-11 critic finding #5, sampled on 3 pages; the
   exhaustive scan found the same gap on 7 more h3 pages + 1 h4 instance).
   The sitewide bare `h3{font-weight:600}` / `h4{font-weight:600}` rules in
   styles_v2.css carry NO !important, so any page-local ancestor-scoped
   selector (`.rsa-head h3`, `.rs-feat h3`) or inline `style="font-
   weight:700"` beats them on specificity or inline priority respectively.
   A single bare, blanket rule per tag, with !important, beats every one of
   those at once (a stylesheet !important rule always beats a plain inline
   style, regardless of specificity) while the MORE specific, already-
   correct promoted-heading rules above (h3.h4/h3.h5/h3.h6, `body .pmlf
   h3`, footer h3.h5, etc., all class-scoped so all higher-specificity)
   are completely unaffected — they keep winning on specificity exactly as
   before. This is the h3/h4 case's own equivalent of the h5/h6 weight fix
   already applied elsewhere in this file. */
h3 {
  font-weight: 600 !important;
}
h4 {
  font-weight: 600 !important;
}

/* 11) index.html's hero lead (`.hero-lead`, "PM Surya Ghar subsidy up to
   ₹78,000...") set font-size:1.25rem(20px)/line-height:1.8(36px) at
   desktop in a page-local <style> - this round's line-height:24px fix
   left the font-size untouched, so the pair (20px/24px) still matched no
   declared step (not h4's 20/28, not body-lg's 18/24). Round 20 fixed the
   font-size itself at the source (index.html's page-local `.hero-lead`
   base rule, now 1.125rem/18px) so the pair lands cleanly on
   --type-body-lg desktop (18/24); this line-height override still applies
   on top of that. Mobile already renders at 17px/24px (a different,
   already-correct media-query override with its own !important, which
   still wins on mobile since it's scoped and unaffected by this bare,
   unscoped rule only touching line-height). */
.hero-lead {
  line-height: 24px !important;
}

/* 10) One promoted `h3.h6` (ppa-for-industry.html, "Typical 5 MW facility
   · Annual economics") carries an inline `style="...font-weight:700;..."`
   that the existing `h3.h6:not([style])` weight rule above deliberately
   doesn't touch (that rule's `:not([style])` exists to respect other
   inline overrides that don't concern weight) — but #9's blanket `h3`
   rule above already fixes this one too, being a bare `h3` rule with
   !important, which beats even an inline style. No separate rule needed;
   documented here so the interaction is legible, not accidental. */
