/* r-solar Brand System v2 compliance layer: components.
   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.
   Piece P10: buttons, cards, badges/chips, form fields, focus rings, off-palette colours.
   Selectors below intentionally match styles_v2.css's own selectors so the cascade
   (this file loads after it, same specificity, no !important unless the source rule
   itself carries !important) overrides the cited value without touching that file. */

/* ---------------------------------------------------------------------------
   1. FOCUS VISIBLE (§a11y 2.4.7 / 2.4.13) -- the worst finding.
   styles_v2.css sets outline:none on nav-link and footer-link hover/focus-visible
   with no replacement ring at all, and the sitewide button/input/link ring that
   DOES exist is 2px, not the spec-mandated 3px solid + 2px offset. Fixed once,
   here, for every consumer. */
.navbar .nav-link:focus-visible {
    outline: 3px solid var(--rs-green-text, #3B7020);
    outline-offset: 2px;
    border-radius: var(--radius-xs, 4px);
}
footer .text-white-50:focus-visible {
    outline: 3px solid #72BF44; /* Solar Green ring on Brand Ink ground, per §a11y's on-dark spec */
    outline-offset: 2px;
    border-radius: var(--radius-xs, 4px);
}
footer ul.list-inline > li.list-inline-item > a:focus-visible {
    outline: 3px solid #72BF44;
    outline-offset: 2px;
    /* the element is already a 44px circle; the ring keeps its own radius so it
       doesn't clip against the circular background */
}

/* input[type=range] sliders (c-and-i-solar-calculator.html) set outline:none
   directly on the element with no :focus-visible replacement anywhere in the
   page -- same 2.4.7 defect as the nav/footer/button cases above, but on an
   element selector the generic input:focus-visible rule below can't win
   against: that rule only sets outline-width/offset, not outline-style, so
   it cannot restore a ring once a more specific same-element rule has set
   outline-style to none. A dedicated input[type=range]:focus-visible rule
   is strictly more specific than the page's own `input[type=range]{outline:
   none}` (adds a pseudo-class), so it wins regardless of source order and
   covers this pattern on every page, today and future. calculator.html's
   sibling slider already carries its own equivalent fix on its class
   selector (.custom-range-input:focus-visible) and is unaffected. */
input[type=range]:focus-visible {
    outline: 3px solid var(--rs-green-text, #3B7020);
    outline-offset: 2px;
}

/* .btn-rs-primary/-secondary/-link (unused today, but shipped in styles_v2.css)
   set outline:none on :focus-visible with no replacement -- same 2.4.7 defect
   as the nav/footer case above, fixed the same way before anything consumes them. */
.btn-rs-primary:focus-visible,
.btn-rs-secondary:focus-visible,
.btn-rs-link:focus-visible {
    outline: 3px solid var(--accent, #72BF44);
    outline-offset: 2px;
}

/* Sitewide ring width/offset: was outline:2px (R14/2.4.13 wants 3px, 2px offset). */
a:focus-visible,
button:focus-visible,
.btn:focus-visible,
.common-btn2:focus-visible,
[role="button"]:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
    outline-width: 3px;
    outline-offset: 2px;
}

/* ---------------------------------------------------------------------------
   2. RADIUS -- shared classes defined in styles_v2.css.
   Page-local <style> block violations (rs-cta__card, office-card, industry-card,
   cws-chip, rsa-hw-card, .pmlf .form-control, rounded-pill on .btn) are fixed at
   the page level since page-local <style> loads after this file and would win
   the cascade anyway; recorded in the round-1 summary. */
.case-study-card {
    border-radius: var(--radius-lg, 12px); /* was 15px, off-scale; nearest published step */
}
.bento-item-v2 {
    border-radius: var(--radius-xl, 20px); /* was a hardcoded 20px -- correct value already, promoted to the token for R13 hygiene */
}

/* Calculator page controls: styles_v2.css sets these with !important, so the
   override needs matching specificity + !important to win the cascade. */
.custom-select-lg,
.custom-input-lg {
    border-radius: var(--radius-sm, 4px) !important; /* was 10px !important, off-scale */
}
.custom-range-input {
    border-radius: var(--radius-sm, 4px) !important; /* was 5px !important, off-scale */
}

/* ---------------------------------------------------------------------------
   2b. RADIUS ROUND 2 -- root-cause fixes for the shared nav dropdown and the
   button family, both authored as an inline style="border-radius:...px" on
   the same handful of markup patterns repeated across the whole site. An
   inline style normally beats an external stylesheet rule of equal
   specificity, so these need !important to win; that is the only way to fix
   the shared header/button component centrally instead of editing every page.

   Nav dropdown (Solutions / Subsidy and savings / About): the shared header
   include across (grep) 66 of 80 root pages hardcodes
   style="border:none; border-radius:10px; padding:0.5rem 0; min-width:200px;"
   on every .dropdown-menu. Only best-solar-panels-india was hand-patched to
   8px in round 1; fixing the class here instead covers all of them at once
   and any future page that reuses the same header markup. */
.dropdown-menu {
    border-radius: var(--radius-md, 8px) !important; /* Dropdown / menu, §components: --radius-md */
}

/* Buttons: §components' size table gives every .btn variant (sm/md/lg) the
   same --radius-md (8px). The base .btn class already reads that correctly
   from styles_v2.css; the defect is inline style="border-radius:...px"
   authored per-CTA (6px/10px/12px seen across 21 pages, e.g. index.html's
   "Download product brochure" and industrial-solar-indore's booklet/PPA
   CTAs). Chips, badges, avatars and toggles are --radius-full and never
   carry the .btn class, so this cannot collide with the pill components. */
.btn {
    border-radius: var(--radius-md, 8px) !important;
}

/* Lead-form white card wrapper on the C&I template (industrial-solar-indore,
   industrial-solar-khargone: id="ci-form-wrapper-<city>") hardcodes an inline
   border-radius:16px, which is not one of the six published radius tokens.
   16px sits equidistant between --radius-lg (12px, "large cards") and
   --radius-xl (20px, "feature panels, hero cards"); this is a lead-capture
   card rather than a hero/feature panel, so it snaps to --radius-lg. */
[id^="ci-form-wrapper-"] {
    border-radius: var(--radius-lg, 12px) !important;
}

/* PM Surya Ghar callout card (.pmlf) hardcodes border-radius:18px in a
   page-local <style> block repeated verbatim across 20 pages (3/4/5/10kw,
   1kw, pm-surya-ghar-subsidy, sbi/bank-loan-list/yojana-login, almm-*,
   solar-panel-cost-mp, solar-panel-installation-cost-india,
   solar-panels-for-home-india, bifacial-solar-panels, hydrogen-solar-panels,
   utl-solar-panel, 500-watt-solar-panel, mp-renewable-energy-policy-2025,
   open-access-solar-mp, net-metering-mp) -- not one of the six published
   radius tokens; the lane already fixed .pmlf .form-control's radius on the
   same rule block but left the parent container's own radius untouched
   everywhere. Nearest token is --radius-xl (20px, "feature panels"), which
   this callout card visually is. Fixed once here instead of 20 page edits;
   !important is required because every page's own page-local <style> loads
   after this stylesheet's <link>, so on equal specificity the page-local
   18px would otherwise win the cascade. */
.pmlf {
    border-radius: var(--radius-xl, 20px) !important;
}

/* ---------------------------------------------------------------------------
   3. ICONS -- Material Symbols opsz should track the rendered size (12-32px
   seen across pages), not a single hardcoded 24. font-optical-sizing:auto lets
   the variable font interpolate opsz from font-size instead of pinning it. */
.material-symbols-rounded.material-symbols-rounded {
    font-optical-sizing: auto;
    font-variation-settings: 'FILL' 1, 'wght' 400, 'GRAD' 0;
}

/* ---------------------------------------------------------------------------
   4. COLOUR -- off-palette hard-coded values remapped to the published tokens.
   These are custom-property re-declarations (cascade only), not edits to
   design-tokens.css: the file this lane owns is the only one changed. */
:root {
    /* R17 corrects R16's reasoning: "not a grey-ramp step" is not the test --
       the contrast matrix is ("if a pairing is not on it, it has not been
       approved"). #c9d4e3 and #8ea3bd appear nowhere in §colour's matrix; they
       are typed hex invented in design-tokens.css, off the closed palette.
       Every consuming rule on every page reads var(--rs-ns-sub-text, #c9d4e3)
       / var(--rs-ns-label-text, #8ea3bd) against a Brand-Ink band (rs-nextstep,
       the -steps__detail/-stats__label/-form-section captions, net-metering-mp's
       timeline copy). Reading the matrix's "Brand Ink" ground column for a
       normal-size-text pairing (AA, >=4.5:1) leaves exactly three approved
       foregrounds: White 14.70:1, Sun Yellow 8.66:1, Solar Green 6.42:1. This
       redeclares both tokens to two of those three -- via the existing
       --rs-white / --rs-yellow tokens, never a typed hex -- fixing every page
       that consumes them from this one file, no HTML edits needed. Sun Yellow
       keeps the label's original "accent, not body" role (all consuming
       label/caption copy sits under 40 words, so §colour's yellow running-text
       limit is not tripped); the sub tier moves to full White for the highest
       ratio available for its longer sentences. */
    --rs-ns-sub-text: var(--rs-white, #ffffff);
    --rs-ns-label-text: var(--rs-yellow, #f8be1a);

    /* PM Surya Ghar callout (.pmlf) tint: were a bespoke pale-green pair not on
       the audited master-green ramp. Rebuilt from the approved Green 700 tint
       tokens instead of a typed hex, per "colour is never typed by hand". */
    --rs-pmlf-bg: var(--rs-green-tint, rgba(114, 191, 68, 0.10));
    --rs-pmlf-border: var(--rs-green-text-tint, rgba(59, 112, 32, 0.10));
}

/* Bootstrap's unremapped default body colour (#212529) never got mapped to a
   brand token (R13: components reference semantic tokens only).
   R11: was remapped to Near Black (#212121, "Deepest text, single-plate
   print"), but the palette table's own row is explicit -- Brand Ink
   (#242834) is "Body text on light" -- so this now points at the actual
   body-text token instead of the deepest/print one. */
body {
    color: var(--rs-ink, #242834);
}

/* R13 P10: the same unremapped #212529 also reaches elements that set their
   own colour instead of inheriting from body, so the body{} rule above never
   gets there. Two Bootstrap component families do this sitewide via the
   shared header include and any .table markup: .dropdown-menu/.dropdown-item
   (72/80 pages via nav) and table/thead/tbody (~39/80 pages with data
   tables). Both remapped to the same Brand Ink body-text token. */
.dropdown-menu,
.dropdown-item {
    color: var(--rs-ink, #242834);
}
table,
thead,
tbody,
.table {
    color: var(--rs-ink, #242834);
}

/* calculator.html's district <select> (.custom-select-lg:focus, styles_v2.css)
   sets a solid Green-700 border-color but an almost-invisible outline colour
   -- rgba(114,191,68,0.25), Solar Green at 25% alpha -- so the focus ring
   itself fails the ≥3:1 non-text-contrast requirement even though its
   width/offset (3px/2px) are already correct. Same selector, later in the
   cascade, equal specificity, no !important needed since the source rule
   doesn't carry one either: swap the ring to a solid Green 700, matching
   every other focus ring on the site. */
.custom-select-lg:focus {
    outline-color: var(--rs-green-text, #3B7020);
}

/* R14 P10 round-14 worst finding: the sitewide text/select input focus ring
   (.form-control:focus, .form-select:focus, styles_v2.css:5691) uses
   --rs-green-text-tint for its outline -- a 10%-alpha Green 700 TINT meant
   for glow/background use, not a solid ring colour. Computed outline is
   rgba(59,112,32,0.10), an almost-invisible haze that fails the >=3:1
   non-text-contrast floor (2.4.13) even though width/offset (3px/2px) are
   already correct. This selector is the shared text/select input class used
   on 45+ pages (contact-us, every .pmlf form, C&I forms, calculator, etc.),
   so one shared override here beats a 45-page hunt -- identical fix already
   applied above to .custom-select-lg:focus, just missed on this far more
   common selector. Same specificity, later in the cascade, no !important
   needed. */
.form-control:focus,
.form-select:focus {
    outline-color: var(--rs-green-text, #3B7020);
}

/* Shared header "Get Free Quote" nav CTA (desktop-only, href="/contact-us"):
   inline style="border-radius:6px" on the anchor, repeated verbatim across
   63 pages via the shared nav include -- not one of the six published radius
   tokens. Fixed once here instead of 63 page edits; !important needed to
   beat the inline style since the source has no !important of its own to
   lean on for specificity. */
li.nav-item.ml-2.d-none.d-lg-flex.align-items-center > a[href="/contact-us"] {
    border-radius: var(--radius-md, 8px) !important;
}

/* R11 P10: .case-badge (photo-overlay category tag on the case-study cards,
   index.html + case-studies.html) hard-codes border-radius:20px in
   styles_v2.css -- an off-token value, not --radius-full (9999px) as
   §components' Chip/tag row requires. Same selector, later in the cascade,
   equal specificity, no !important needed since the source rule carries
   none either. One shared override here covers both pages. */
.case-badge {
    border-radius: var(--radius-full, 9999px);
}

/* ---------------------------------------------------------------------------
   5. ROUND 12 -- worst finding: chip/tag and badge text elements computed
   border-radius:0, sitting next to correctly-pilled siblings (.rs-chip,
   .abt-story__tag, both 999px on the same two pages). These four selectors
   are plain text runs (no fill, no border) rather than the pill containers
   themselves -- #cities-we-serve .cws-tag is the descriptor line inside
   .cws-chip (which already carries --radius-lg, documented above as
   intentional for its two-line card shape, not a violation); .abt-badge__mark
   / .abt-badge__note are the label/caption text inside .abt-badge (which
   already carries --radius-lg, 12px, on-scale); .abt-manuf-card__badges is
   the CSS-grid layout wrapper around four .abt-badge tiles, not a badge
   itself. None had a background or border for a radius to visibly clip, so
   the corner defect the critic measured was never renderable -- but the
   spec's Chip/tag and Badge rows are unambiguous (--radius-full) and the
   selectors keep failing the same computed-style check every round, so they
   get the token here rather than being re-litigated: harmless on these
   borderless text runs, and correct if either ever gains a fill or border
   later. */
#cities-we-serve .cws-tag,
.abt-badge__mark,
.abt-badge__note,
.abt-manuf-card__badges {
    border-radius: var(--radius-full, 9999px);
}

/* R12 P10: #cities-we-serve .cws-chip's own border hard-codes #e3e7e2 in a
   page-local <style> block (index.html) -- a hand-typed hex not on the
   published neutral ramp (nearest step, Grey 200 #d8dbe0, is what
   --border-subtle already resolves to). "Colour is never typed by hand --
   it comes from a single shared token" (§colour). Same selector, later in
   the cascade, equal specificity, no !important needed since the page-local
   rule carries none. */
#cities-we-serve .cws-chip {
    border-color: var(--border-subtle, #d8dbe0) !important; /* page-local <style> sets it via the `border` shorthand, same specificity, later in the DOM -- !important needed to win, same pattern as .pmlf/.dropdown-menu/.btn above */
}

/* R12 P10: the sitewide .text-muted / .breadcrumb-item.active rule
   (styles_v2.css:5267) points at --rs-text-muted (#5f6b7a) -- a token this
   lane cannot rename or retarget in design-tokens.css, and one that does not
   sit on the published 11-step neutral ramp (nearest step, Grey 500, is
   #6B7280 -- a different hex, not the same colour re-cased). §colour's own
   mechanism section is categorical: colour comes from "a single shared
   token" on the published ramp, and R13 elsewhere in this file already
   remaps other off-ramp component colours the same way. Same selector,
   !important required to match the source rule's own !important, later in
   the cascade so this wins the tie. Grey 500 is still text-safe on white at
   4.83:1 (marginally higher than the token's 4.60:1), so no contrast
   regression. */
.text-muted,
.breadcrumb-item.active {
    color: var(--rs-grey-500, #6b7280) !important;
}

/* ---------------------------------------------------------------------------
   R14 P10 EXHAUSTIVE MODE: full-sitemap scan_P10.py (1391 raw hits / 132
   distinct selector+value patterns) surfaced dozens of off-scale radii that
   live in css/styles_v2.css (this lane cannot edit that file) or as Bootstrap
   utility classes (.rounded-circle/.rounded-pill/.rounded-lg all bake a
   non-token radius into their own !important rule). Fixed once, here, for
   every consumer, instead of touching styles_v2.css or bootstrap.min.css.
   Page-local <style> instances of the same defect (author-box, the 14
   location-page why__fact/steps__icon pairs, commercial-industrial-solar's
   .cix-* family, etc.) were fixed at the source in their own HTML files
   instead, since those page-local rules load AFTER this file and would
   otherwise need !important to win -- editing the value directly is the
   smaller, more legible diff. */

/* Footer social-icon circles (styles_v2.css:5091, sitewide footer include,
   the single most page-visible pattern in the whole scan). Already a
   perfect circle at 44x44 -- 50% and 9999px render identically here, this
   is a pure token-compliance fix with zero visual change. */
footer ul.list-inline > li.list-inline-item > a {
    border-radius: var(--radius-full, 9999px);
}

/* Bootstrap's own circle/pill/large-radius utilities compute to raw values
   never on the published scale (50%, 50rem/800px, .3rem/4.8px) because they
   ship with their own !important. Author avatars (img.rounded-circle,
   news/blog templates), the mp-renewable-energy-policy-2025 stat pills
   (.rounded-pill) and the solar-panel-cleaning-india / open-access-solar-mp
   photo frames + stat cards (.rounded-lg) all use these utilities for their
   literal Bootstrap meaning (circle / pill / large-rounded), so remapping
   the utility itself to the nearest token is correct everywhere it appears,
   not just on the pages the scanner happened to sample. */
.rounded-circle {
    border-radius: var(--radius-full, 9999px) !important;
}
.rounded-pill {
    border-radius: var(--radius-full, 9999px) !important;
}
.rounded-lg {
    border-radius: var(--radius-sm, 4px) !important; /* was .3rem/4.8px; nearest scale step */
}

/* styles_v2.css's own base `.card{border-radius:var(--radius-lg)}` (12px, no
   !important, styles_v2.css:5591) wins the cascade for every `.card` that is
   NOT nested inside `.accordion` -- only `.accordion .card, .faq-item` gets
   the correct --radius-md (8px) via a separate !important override
   (styles_v2.css:5799-5801). §components Containers table names Card as
   --radius-md (8px) with no accordion exception, so plain cards (e.g.
   feature/team cards on index.html, aboutus.html and 7 more sitemap pages)
   were rendering 12px, not 8px. This selector's specificity (0,1,0) is
   lower than `.accordion .card`'s (0,2,0), so it cannot and does not
   override that already-correct !important rule -- it only wins the plain
   `.card` case by loading after styles_v2.min.css in the cascade. */
.card {
    border-radius: var(--radius-md, 8px); /* was 12px via styles_v2.css's base .card{} rule */
}

/* .timeline-badge / .timeline-icon / .step-indicator / .filter-btn are all
   defined once, canonically, in styles_v2.css (not page-local, not reused
   for anything else) -- safe to retarget centrally. .timeline-icon is
   already a perfect circle (70px/50px); .timeline-badge and .filter-btn are
   pill-shaped labels/buttons (radius already >= half their own height, so
   9999px is the same rendered shape); .step-indicator is a 28px/22px
   circle. */
.timeline-badge {
    border-radius: var(--radius-full, 9999px); /* styles_v2.css:3648, was 30px */
}
.timeline-icon {
    border-radius: var(--radius-full, 9999px); /* styles_v2.css:3605, was 50% */
}
.step-indicator {
    border-radius: var(--radius-full, 9999px); /* styles_v2.css:4012, was 50% */
}
.filter-btn {
    border-radius: var(--radius-full, 9999px); /* styles_v2.css:3744, was 50px pill CTA -- §components names --radius-full for pill CTAs by name */
}

/* .trust-icon-wrapper (styles_v2.css:3394, homepage trust-strip icons) is a
   single canonical 60px circle -- same reasoning as .timeline-icon above. */
.trust-icon-wrapper {
    border-radius: var(--radius-full, 9999px); /* was 50% */
}

/* WhatsApp floating button / CTA (.whatsapp-float on 3 pages, .btn-whatsapp
   on 53 pages) is authored as an inline style="border-radius:50px" per page
   with no shared class rule to override without !important -- the exact
   "Pill CTAs" case §components withdraws by name in favour of --radius-full.
   Both are already visually round pills; this is a pure token swap. */
.whatsapp-float,
.btn-whatsapp {
    border-radius: var(--radius-full, 9999px) !important;
}

/* c-and-i-solar-calculator's #cuf_slider computes an off-scale radius from
   a cascade this lane cannot fully resolve without editing styles_v2.css
   (the generic input[type=range] rule above is already fixed to
   --radius-sm, but a UA-stylesheet interaction still measured 5px in the
   R11 critic pass) -- pin it by id so the token wins outright regardless of
   which rule the browser was actually applying. */
#cuf_slider.form-control-range {
    border-radius: var(--radius-sm, 4px) !important;
}

/* .customer .box (styles_v2.css:2063, homepage testimonial cards, ".border
   box" in the markup) overrides the base .box card radius from 8px to a
   more specific but off-scale 15px -- a single canonical selector, safe to
   retarget centrally. */
.customer .box {
    border-radius: var(--radius-lg, 12px); /* was 15px, off-scale */
}

/* .stepper-item / .property-card-label (styles_v2.css:2198/2228 and a
   duplicated copy at :2390/:2420 -- both single canonical calculator-flow
   components, safe to retarget centrally). .stepper-item is a 44px circle;
   .property-card-label's 15px sits between --radius-lg and --radius-xl,
   closer to --radius-lg (diff 3 vs 5). */
.stepper-item {
    border-radius: var(--radius-full, 9999px); /* was 50% */
}
.property-card-label {
    border-radius: var(--radius-lg, 12px); /* was 15px, off-scale */
}

/* .corner (styles_v2.css:1522, environmental-impact's feature panels/photo
   frames) is a single canonical utility class carrying its own !important
   -- needs !important to win the tie. 24px is closest to --radius-xl
   (diff 4; "feature panels, hero cards, image frames" is exactly this
   component's role). */
.corner {
    border-radius: var(--radius-xl, 20px) !important; /* was 24px, off-scale */
}

/* services.html app-mockup device frame (styles_v2.css:3937 onward) --
   single canonical component, safe to retarget centrally. .phone-mockup is
   the outer device frame (nearest token --radius-xl, "image frames");
   .phone-screen is its inner screen corner (nearest --radius-lg);
   .progress-section is a content card (nearest --radius-lg, diff 3). */
.phone-mockup {
    border-radius: var(--radius-xl, 20px); /* was 40px, off-scale */
}
.phone-screen {
    border-radius: var(--radius-lg, 12px); /* was 30px, off-scale */
}
.progress-section {
    border-radius: var(--radius-lg, 12px); /* was 15px, off-scale */
}

/* index.html's own page-local <style> block (line ~835) already sets
   .hero-highlight to --radius-md, but that block sits BEFORE the real
   css/styles_v2.min.css <link> in <head> (only a <link rel="preload"> for
   it appears earlier) -- so styles_v2.css:3380's own off-scale 14px loads
   LATER and wins the cascade tie, silently shadowing the already-correct
   page-local fix. Retargeting here, after both, settles it for good. */
.hero-highlight {
    border-radius: var(--radius-md, 8px); /* was 14px, off-scale */
}

/* §components Form controls: "Label ... Always present and always visible.
   Never replaced by a placeholder." A visible sighted label would repeat
   the placeholder text and double it on screen, so labels for fields whose
   placeholder already carries the field name are visually hidden (screen
   readers and :focus-visible/label semantics still see them) rather than
   dropped. industrial-solar-indore.html already reached for a class named
   "rs-visually-hidden" for this on its lead form, but that class was never
   defined anywhere in the codebase -- its labels were rendering as plain
   visible text stacked above the placeholder-only inputs, not hidden at
   all. Defining it once here (identical technique to styles_v2.css's own
   .sr-only) fixes indore's pre-existing instance and every later page that
   reuses the same class name, instead of chasing each page individually. */
.rs-visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

