* { box-sizing: border-box; padding: 0; margin: 0; } /* * AppLink is the only place link affordance (color, underline) is decided — * this reset keeps a bare (e.g. inside rich text) from inheriting the * browser's default blue/underline before AppLink's own styling applies. */ a { color: inherit; text-decoration: none; } ::selection { background-color: var(--bal-primary-soft); color: var(--bal-text-primary); } /* * Directional icons (back/chevron_start, …) are authored for LTR and mirror * under RTL. AppIcon sets `data-icon-directional` for every name registered * in AppIcon/config.ts's DIRECTIONAL_ICONS — this is the only flip rule in * the app; never hand-roll a per-component mirror. */ [dir='rtl'] [data-icon-directional] { transform: scaleX(-1); } /* * App-wide motion pass (phase 12) — one restrained language: a calm 150–200ms fade + small slide on * route-group content and skeleton→content swaps. `key`-triggered remounts (RouteFadeIn) or a plain * mount (a skeleton branch replaced by a populated one) both replay this the same way — there is * exactly one animation definition for both cases, never a per-screen bespoke one. */ @keyframes bal-fade-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: translateY(0); } } [data-bal-route-fade] { animation: bal-fade-in var(--bal-motion-base) var(--bal-easing-standard); } /* * The single reduced-motion gate for the whole app (client/CLAUDE.md "Golden rules" — CSS over JS for * theme mechanics). This is the ONE place `prefers-reduced-motion: reduce` is handled — every animation * and transition this phase adds (the route fade above, MUI's own Dialog/Drawer/Menu/Collapse/Fade * transitions, the admin config-history/ExplainerCard/EscrowExplainer chevron rotations) collapses to * an effectively-instant appearance. Do not add a second, component-local reduced-motion check anywhere * else — extend this rule instead if a new motion primitive needs the same treatment. */ @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; } }