/* r-solar Brand System v2 compliance layer: motion.
   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. */

/* P11 round 1 -- §motion Principle 04 "cheap by rule": nothing loops for
   longer than 3s, no continuous background motion, nothing plays that a
   person did not initiate (§motion "what never animates"). These four
   selectors carry an infinite CSS animation today:
     .animate-pulse      -- hero/results-cta/bottom-cta primary CTA button
                             (index.html), 2s infinite scale pulse
     .ceq-panel-cell      -- CO2-equivalence solar-panel glow, 2s infinite
     .ceq-panel-glow      -- CO2-equivalence "sun" pulse, 3s infinite
     .ceq-mini-car        -- CO2-equivalence mini-car fade, 3s infinite
   None is on the approved-pattern list and none is a skeleton or a
   progress indicator, so they are neutralized rather than re-timed. */
.animate-pulse,
.ceq-panel-cell,
.ceq-panel-glow,
.ceq-mini-car {
    animation: none !important;
}

/* §motion duration/easing tokens -- one shared rule per class beats
   patching every page. Each of these carried a hardcoded, off-token
   "transform 0.3s ease" (or, for .card/.btn-rs, a second parallel
   --dur-base and --ease-out pair instead of the published --motion
   and --ease tokens). Property stays transform-only (R4); duration
   moves onto the nearest token; easing moves onto an approved curve.
   None of these is a named §motion pattern, so each uses
   --motion-base with --ease-standard except the two literal
   button/control cases, which take the spec's own "Button
   hover/focus" value (--motion-fast, 120ms, standard). */
.card,
.savings-card,
.property-card-label,
.hover-lift,
.case-img-wrapper img,
.article-card,
.article-img-wrapper img,
.case-study-card,
.office-card,
.abt-tm,
.calculator-card,
.benefit-card,
.solution-card {
    transition: transform var(--motion-base, 180ms) var(--ease-standard, cubic-bezier(0.2, 0, 0.2, 1)) !important;
}
/* P11 round 13 -- .calculator-card (calculator.html only) carried the
   same off-token "transform 0.3s ease" pattern as the classes above;
   :hover only sets transform: translateY(-5px), so it belongs in this
   shared rule rather than a new one-off block. */
/* .abt-tm (aboutus.html team-member cards) carried "transform 0.3s,
   box-shadow 0.3s, border-color 0.3s" -- box-shadow is explicitly banned
   by R4 and border-color isn't on the approved-property list either, so
   both are dropped rather than re-timed; the hover's border-color change
   now happens instantly instead of animating, which R4 allows. */

.btn,
.filter-btn,
.btn-rs,
.read-more-btn i,
.btn-whatsapp,
footer ul.list-inline > li.list-inline-item > a {
    transition: transform var(--motion-fast, 120ms) var(--ease-standard, cubic-bezier(0.2, 0, 0.2, 1)) !important;
}
/* .btn-whatsapp carries its 0.3s-ease transition as an inline style on ~50
   pages (the floating WhatsApp CTA partial); !important here is what lets
   one shared rule reach every page instead of a 50-file find/replace. */

/* P11 round 3 -- contact-us's decorative hero orbs (css/styles_v2.css
   @keyframes float, .hero-circle-1/.hero-circle-2, animation-duration
   8s/10s, infinite) are the same banned-category infinite loop round 1
   already neutralized for .animate-pulse/.ceq-*; these two were missed
   because the drift fix that hides them (styles_v2.css line ~5044) lives
   only in the unminified dev source -- every page loads styles_v2.min.css,
   which predates that fix, so the loop still ships live. Stopped here
   rather than re-minifying styles_v2.min.css, which is out of this
   lane's CSS ownership (rs-motion.css only). */
.hero-circle-1,
.hero-circle-2 {
    animation: none !important;
}

/* P11 round 3 -- §motion duration/easing tokens, continued. Same root
   cause as the block above: a hardcoded duration/easing pair instead of
   the published tokens, on shared component classes with sitewide reach.
   .material-symbols-rounded's own base rule (styles_v2.min.css) carries
   "transition: transform 0.3s ease" for every icon on every page;
   .trust-icon-wrapper duplicates the same value for the "why choose us"
   trust badges. Bootstrap's .badge and .carousel-item defaults ship
   their own off-token durations/easings (.badge also transitions
   box-shadow, which R4 bans outright -- dropped here, not re-timed). */
.material-symbols-rounded,
.trust-icon-wrapper {
    transition: transform var(--motion-base, 180ms) var(--ease-standard, cubic-bezier(0.2, 0, 0.2, 1)) !important;
}

/* P11 round 15 -- .badge's border-color leg is itself an R4 violation (this
   file's own earlier fix retimed Bootstrap's default duration/easing but
   kept border-color in the property list; border-color isn't on the
   transform/opacity/named-pattern allow-list, and .badge's border colour
   never actually changes on hover/focus, so nothing is lost by dropping
   it -- Principle 01). */
.badge {
    transition: color var(--motion-fast, 120ms) var(--ease-standard, cubic-bezier(0.2, 0, 0.2, 1)),
                background-color var(--motion-fast, 120ms) var(--ease-standard, cubic-bezier(0.2, 0, 0.2, 1)) !important;
}

/* Bootstrap's carousel slide transition (0.6s ease-in-out) exceeds even
   --motion-slow, the longest token that exists (320ms, "the ceiling for
   navigation" -- this is a navigation slide, not a data reveal), and
   ease-in-out is not one of the four approved curves. */
.carousel-item {
    transition: transform var(--motion-slow, 320ms) var(--ease-standard, cubic-bezier(0.2, 0, 0.2, 1)) !important;
}

/* P11 round 11 -- worst finding first: §motion "What never animates" bans
   "anything triggered by scroll position alone... no reveal-on-scroll"
   outright (LEAD DECISION 21:45). aos.css/aos.js are being unloaded and
   AOS.init() removed page by page (see git log for this round), but that
   is a page-by-page fix; this is the belt-and-suspenders shared-root-cause
   version. AOS's own stylesheet sets [data-aos] to opacity:0 pre-scroll
   and only reveals it once JS adds .aos-animate on intersection -- if any
   page still ships that CSS (cache, a page this round missed, a future
   regression) this rule keeps content visible from first paint regardless,
   so nothing is ever hidden waiting for scroll. data-aos attributes are
   left in the markup per the lead's guidance; they simply do nothing. */
[data-aos] {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
    animation: none !important;
}

/* P11 round 11 -- §motion duration/easing tokens, continued (shared root
   cause: identical "color 0.2s, background 0.2s" .share-btn rule copied
   into 30+ pages' page-local <style> blocks). 200ms is not a token (the
   nearest are 180/240ms) and no easing token is set. The article
   share-icon hover is the spec's own "Button hover/focus" named pattern
   (background-color, 120ms, standard). One rule here reaches every page
   instead of a 30-file find/replace. */
.share-btn {
    transition: color var(--motion-fast, 120ms) var(--ease-standard, cubic-bezier(0.2, 0, 0.2, 1)),
                background-color var(--motion-fast, 120ms) var(--ease-standard, cubic-bezier(0.2, 0, 0.2, 1)) !important;
}

/* P11 round 11 -- index.html "r-solar Advantage" tab component. Both
   .rsa-nav button and .rsa-hw-cta a carried an undocumented fifth curve,
   cubic-bezier(.2,.8,.2,1) (or no curve at all), at an off-token 200ms.
   Neither is R3-banned (y-values don't overshoot) but §motion names only
   four approved curves and says to fall back to --motion-base/
   --ease-standard for anything not a listed pattern; the tab-nav button
   and its CTA are plain hover/focus state changes, so they take the
   spec's "Button hover/focus" values instead (--motion-fast, standard). */
.rsa-nav button,
.rsa-hw-cta a {
    transition: background-color var(--motion-fast, 120ms) var(--ease-standard, cubic-bezier(0.2, 0, 0.2, 1)),
                color var(--motion-fast, 120ms) var(--ease-standard, cubic-bezier(0.2, 0, 0.2, 1)) !important;
}

/* P11 round 11 -- index.html .rsa-panel.is-active tab-switch reveal
   (@keyframes rsaIn, defined in the page's own <style>). It animated at
   350ms on the same undocumented curve as above. A tab-panel switch is
   the duration table's own "tab change" case (--motion-moderate, 240ms);
   as an element arriving, it takes --ease-entrance (rise-and-settle), not
   --ease-standard. Overriding animation-duration/-timing-function here
   keeps the page's own @keyframes rsaIn (opacity+translateY, R4-clean)
   and only retimes it. */
.rsa-panel.is-active {
    animation-duration: var(--motion-moderate, 240ms) !important;
    animation-timing-function: var(--ease-entrance, cubic-bezier(0, 0, 0.2, 1)) !important;
}

/* P11 round 13 -- .whatsapp-float is a distinct floating-WhatsApp variant
   from .btn-whatsapp above; its own page-local <style> block (not inline)
   sets "transition: transform 0.3s ease" on 3 pages (index.html,
   delete-account.html, solar-panel-cleaning-india.html). 300ms is not a
   token and plain "ease" is not an approved curve. It is a hover/focus
   state change (transform: scale on :hover), the spec's own "Button
   hover/focus" pattern, so it takes --motion-fast/--ease-standard like
   .btn-whatsapp. One shared rule reaches all 3 pages instead of 3 edits,
   and covers any future page that reuses this partial. */
.whatsapp-float {
    transition: transform var(--motion-fast, 120ms) var(--ease-standard, cubic-bezier(0.2, 0, 0.2, 1)) !important;
}

/* P11 round 13 -- contact-us.html's .rs-proof-link (the "See the proof"
   inline link) and its icon carry "transition: color .2s, border-color
   .2s" / "transition: transform .2s" in the page's own <style> block.
   200ms is not a token (nearest are 180/240ms) and no easing token is
   set. Both are a hover/focus state change -- the spec's "Button
   hover/focus" pattern -- so both take --motion-fast/--ease-standard. */
.rs-proof-link,
.rs-proof-link .material-symbols-rounded {
    transition-duration: var(--motion-fast, 120ms) !important;
    transition-timing-function: var(--ease-standard, cubic-bezier(0.2, 0, 0.2, 1)) !important;
}

/* P11 round 12 -- worst finding first: the 14 city/district gallery pages
   (commercial-solar-{bhopal,dhar,indore,barwani,khandwa}, industrial-solar-
   {dhar,khandwa,mandideep,pithampur}, solar-in-{dhar,indore,khargone,
   khandwa,barwani}) each carry a page-local ".<prefix>-gallery__tile img"
   rule with "transition: transform 0.4s ease" on the hover-zoom photo
   tiles. Every page uses its own prefix class (csb2/csd/csi/csb/csk/isd/
   isk/ism/isp/dhr/idr/kgn/kwa/brw) for the same identical component, so
   one shared rule here -- listing every prefix -- reaches all 14 instead
   of 14 file edits. 400ms is off every duration token (nearest 320/480ms)
   and bare "ease" is not one of the 4 approved curves; this is a plain
   hover state change with no named pattern, so it takes the spec's own
   fallback: --motion-base with --ease-standard. */
.csb2-gallery__tile img,
.csd-gallery__tile img,
.csi-gallery__tile img,
.csb-gallery__tile img,
.csk-gallery__tile img,
.isd-gallery__tile img,
.isk-gallery__tile img,
.ism-gallery__tile img,
.isp-gallery__tile img,
.dhr-gallery__tile img,
.idr-gallery__tile img,
.kgn-gallery__tile img,
.kwa-gallery__tile img,
.brw-gallery__tile img {
    transition: transform var(--motion-base, 180ms) var(--ease-standard, cubic-bezier(0.2, 0, 0.2, 1)) !important;
}

/* P11 round 12 -- calculator.html's .stepper-item carries the same
   undocumented parallel --dur-base/--ease-out pair the lead named as a
   violation (css/styles_v2.css ~line 2403), out of this lane's CSS
   ownership. Sibling classes (.btn-rs, .card, footer icons) were already
   moved onto the published tokens the same way; this closes the one that
   was missed because it isn't in rs-motion.css's override list. It is a
   hover/focus state change on a step indicator, so it takes the spec's
   "Button hover/focus" values. */
.stepper-item {
    transition: transform var(--motion-fast, 120ms) var(--ease-standard, cubic-bezier(0.2, 0, 0.2, 1)) !important;
}

/* P11 round 12 -- services.html's app-journey stepper. Two separate
   violations on the same component:
   1) Principle 03 caps cascading reveals at three items; four elements
      (animate-step + delay-1/2/3) fire the same slideInStep entrance in
      sequence. The fourth (delay-3) is pulled out of the cascade in the
      page HTML itself (class removed there, not here) so only three
      animate.
   2) animation-duration:0.5s / timing-function:ease-out is off every
      token and "ease-out" is not one of the 4 approved curves. The
      keyframe (opacity + translateX, R4-clean already) matches the
      spec's own named "Install-step advance" pattern closely enough
      (an app-installation step list arriving) to take its values:
      240ms, entrance. styles_v2.css is out of this lane's ownership, so
      the retiming happens here as an override. */
.app-step.animate-step {
    animation-duration: var(--motion-moderate, 240ms) !important;
    animation-timing-function: var(--ease-entrance, cubic-bezier(0, 0, 0.2, 1)) !important;
}

/* P11 round 15 -- exhaustive scan found the app-journey stepper's OWN
   descendants carry two further off-token animations that the round-12
   override above (targeting .app-step.animate-step itself) never reached:
   .step-line's growLine (300ms, "ease-out" -- not a token, not one of the
   4 curves; transform:scaleY is R4-clean) is retimed to the "Install-step
   advance" pattern's own duration/curve (240ms, entrance -- this line is
   part of that same step-advancing reveal). .step-indicator's
   pulse-indicator (2s infinite scale+opacity) is a genuine progress
   indicator -- which step is currently in progress, not decoration --
   permitted to keep looping under "What never animates" ("except a
   skeleton and a progress indicator", line 852). It takes --ease-linear,
   the curve §motion reserves for exactly this case ("continuous
   indeterminate states", line 818), instead of the browser default
   "ease" it had. Round 11: the duration table (line 806-811) names no
   loop token of its own -- the only loop duration §motion sanctions
   anywhere is the skeleton shimmer's 1200 ms (line 837) -- so this
   progress-indicator loop is retimed to that same value rather than
   left at the off-token 2000ms, keeping one motion token system instead
   of a second, disagreeing loop duration. */
.app-step.animate-step .step-line {
    animation-duration: var(--motion-moderate, 240ms) !important;
    animation-timing-function: var(--ease-entrance, cubic-bezier(0, 0, 0.2, 1)) !important;
}

.app-step.in-progress .step-indicator {
    animation-duration: 1200ms !important;
    animation-timing-function: linear !important;
}

/* P11 round 14 -- worst finding first: aboutus.html's "Why r-solar" bento
   grid (.bento-card and its large variant) carries the same off-token,
   off-curve "transform 0.3s ease" pattern the shared override list above
   already closes for .card/.savings-card/.hover-lift/etc, but .bento-card
   was never added to that list. It is a plain hover lift with no named
   pattern, so it takes the spec's own fallback: --motion-base with
   --ease-standard, same as its siblings. */
.bento-card,
.bento-card.bento-item-large {
    transition: transform var(--motion-base, 180ms) var(--ease-standard, cubic-bezier(0.2, 0, 0.2, 1)) !important;
}

/* P11 round 14 -- calculator.html's .custom-select-lg (District and other
   large selects, the calculator's primary input controls) carries the
   same "transform 0.3s ease" defect as .bento-card above: 300ms is off
   every duration token and plain "ease" is not one of the 4 approved
   curves. A select's own hover/focus state change is the spec's "Button
   hover/focus" pattern (transform: none is its stated value, but this
   control's existing motion is a hover lift, not a color change) --
   nothing on the named list covers a select lifting on hover, so it
   takes the documented fallback: --motion-base with --ease-standard. */
.custom-select-lg {
    transition: transform var(--motion-base, 180ms) var(--ease-standard, cubic-bezier(0.2, 0, 0.2, 1)) !important;
}

/* P11 round 14 -- Bootstrap's default .fade / .tab-pane crossfade
   (bootstrap.min.css) ships "transition: opacity .15s linear". 150ms is
   off every duration token and --ease-linear is reserved by name for
   continuous indeterminate states (spinners, skeletons, progress, live
   data) -- a tab-pane fade is a discrete, user-initiated state change,
   not one of those. A pane swap is the duration table's own "tab change"
   case (--motion-moderate, 240ms); as a plain crossfade with no
   direction, it takes --ease-standard rather than an entrance/exit pair.
   Reaches contact-us.html's Residential/Commercial/Industrial tabs and
   every other page using Bootstrap tabs/collapse/carousel fade. */
.fade,
.tab-pane {
    transition: opacity var(--motion-moderate, 240ms) var(--ease-standard, cubic-bezier(0.2, 0, 0.2, 1)) !important;
}

/* P11 round 14 -- sitewide (45 of 69 sitemap pages use .form-control;
   every Bootstrap .collapsing accordion too): styles_v2.min.css already
   forces transition-property:transform !important on .form-control /
   .progress-bar / .collapsing (R4's transform-and-opacity-only rule is
   satisfied), but it left Bootstrap's original transition-duration /
   -timing-function (0.15s ease-in-out, from the border-color+box-shadow
   rule it partially overrode) still attached. The computed style is
   therefore a genuine off-token, off-curve transition even though the
   transform value never actually changes so nothing visibly moves.
   .form-control/.progress-bar's live behaviour is a focus/state change,
   the spec's "Button hover/focus" pattern (--motion-fast, standard);
   .collapsing is an expand/collapse, the "Accordion / dropdown" pattern
   (--motion-moderate). Retimed here rather than in bootstrap.min.css or
   styles_v2.min.css, both out of this lane's CSS ownership. */
.form-control,
.progress-bar {
    transition-duration: var(--motion-fast, 120ms) !important;
    transition-timing-function: var(--ease-standard, cubic-bezier(0.2, 0, 0.2, 1)) !important;
}

.collapsing {
    transition-duration: var(--motion-moderate, 240ms) !important;
    transition-timing-function: var(--ease-standard, cubic-bezier(0.2, 0, 0.2, 1)) !important;
}

/* P11 round 14 -- aboutus.html's testimonial carousel indicator dots
   (Bootstrap default .carousel-indicators li) carry "transition:
   background-color 0.2s ease". 200ms is off-token (nearest 180/240ms)
   and "ease" is not an approved curve. A dot lighting up on selection is
   the spec's "Button hover/focus" pattern (background-color, 120ms,
   standard). Low visibility (small dots) but the same genuine defect as
   every other finding in this round. */
.carousel-indicators li {
    transition: background-color var(--motion-fast, 120ms) var(--ease-standard, cubic-bezier(0.2, 0, 0.2, 1)) !important;
}

/* P11 round 15 -- exhaustive scanner sweep of scan_P11.py, sitewide.
   styles_v2.min.css's input[type=range] rule (opacity fade on hover/
   disabled, e.g. c-and-i-solar-calculator.html's slider) carries an
   off-token "opacity 0.2s" with no easing token set. opacity is already
   an R4-allowed property; only the duration/easing need retiming. Out of
   this lane's CSS ownership (styles_v2.min.css), so overridden here. */
input[type="range"] {
    transition: opacity var(--motion-fast, 120ms) var(--ease-standard, cubic-bezier(0.2, 0, 0.2, 1)) !important;
}

/* P11 round 15 note -- pm-surya-ghar-yojana.html's .benefit-card and the
   three r-solar-*-case-study.html pages' .solution-card carried the same
   off-token, off-curve "transform 0.3s ease" (or, for .solution-card,
   "transform 0.3s" with no easing at all) hover-lift already closed for
   .card/.hover-lift/.bento-card/etc above; both were added to that shared
   selector list near the top of this file rather than getting their own
   one-off rules here. The rest of this round's fixes (a page-local
   "background" shorthand instead of "background-color" repeated across
   several pages' .rs-ns-ctas/.rs-btn/.nav-link/.cix-cities rules; the
   .badge rule two blocks up dropping its own border-color leg; dead
   box-shadow/border-color legs on pm-surya-ghar-bank-loan-list.html's
   .lpq-inp/.lpq-submit and resco-platform.html's .rtab; an undocumented
   bespoke curve on commercial-industrial-solar.html's .cix-btn; a missed
   sibling-page copy of the .industry-card / gallery-card fix already
   applied elsewhere) were page-local, one-off drift from an otherwise-
   correct pattern, so they were fixed in the page HTML directly -- see
   scan_P11.py's output and this round's commit for the full list. */

/* P11 round 16 -- worst finding first: §motion "Reduced motion --
   mandatory" (line 856-857) + R5: "Under prefers-reduced-motion: reduce,
   every duration token resolves to --motion-instant (0 ms)... This is
   not a graceful extra -- a build that ignores it does not ship."
   styles_v2.css/styles_v2.min.css carry a universal reduced-motion reset
   ("*, *::before, *::after { transition-duration:.01ms!important;
   animation-duration:.01ms!important }"), but every class-specific rule
   above is loaded AFTER styles_v2.css and sets the same properties with
   the same !important -- equal specificity, later source wins, so this
   file's own rules beat the universal reset on every selector they
   touch (confirmed live: .btn/.material-symbols-rounded/.trust-icon-
   wrapper stayed at 0.12s/0.18s/0.18s under prefers-reduced-motion
   instead of resolving toward 0). This file therefore needs its OWN
   reduced-motion block re-zeroing every duration/delay it sets, so it
   wins the cascade back to --motion-instant the way the universal reset
   intends. One block, one selector list mirroring every rule above,
   instead of hand-adding a media query per rule.
   Exception: .app-step.in-progress .step-indicator is the spec's named
   exception -- "a skeleton and a progress indicator" may keep looping
   under reduced motion ("What never animates", line 855) -- but line
   857 also says "looping animations stop entirely" under reduced
   motion for everything else, and a progress indicator is explicitly
   carved back out as allowed to loop; kept out of the zero-duration list
   below so it keeps signalling in-progress state, which is real
   information, not decoration. */
@media (prefers-reduced-motion: reduce) {
    .animate-pulse,
    .ceq-panel-cell,
    .ceq-panel-glow,
    .ceq-mini-car,
    .hero-circle-1,
    .hero-circle-2,
    [data-aos],
    .card,
    .savings-card,
    .property-card-label,
    .hover-lift,
    .case-img-wrapper img,
    .article-card,
    .article-img-wrapper img,
    .case-study-card,
    .office-card,
    .abt-tm,
    .calculator-card,
    .benefit-card,
    .solution-card,
    .bento-card,
    .bento-card.bento-item-large,
    .custom-select-lg,
    .btn,
    .filter-btn,
    .btn-rs,
    .read-more-btn i,
    .btn-whatsapp,
    footer ul.list-inline > li.list-inline-item > a,
    .whatsapp-float,
    .stepper-item,
    .material-symbols-rounded,
    .trust-icon-wrapper,
    .badge,
    .carousel-item,
    .share-btn,
    .rsa-nav button,
    .rsa-hw-cta a,
    .rsa-panel.is-active,
    .rs-proof-link,
    .rs-proof-link .material-symbols-rounded,
    .csb2-gallery__tile img,
    .csd-gallery__tile img,
    .csi-gallery__tile img,
    .csb-gallery__tile img,
    .csk-gallery__tile img,
    .isd-gallery__tile img,
    .isk-gallery__tile img,
    .ism-gallery__tile img,
    .isp-gallery__tile img,
    .dhr-gallery__tile img,
    .idr-gallery__tile img,
    .kgn-gallery__tile img,
    .kwa-gallery__tile img,
    .brw-gallery__tile img,
    .app-step.animate-step,
    .app-step.animate-step .step-line,
    .fade,
    .tab-pane,
    .form-control,
    .progress-bar,
    .collapsing,
    .carousel-indicators li,
    input[type="range"] {
        transition-duration: 0ms !important;
        transition-delay: 0ms !important;
        animation-duration: 0ms !important;
        animation-delay: 0ms !important;
    }
}

