Rams MCP · The full engine, now in your coding agent
picocss on GitHub

picocss/pico

Reviewed against Rams quality heuristics: accessibility, color, typography, spacing, components, motion, UX, and craft.

30 files reviewed·July 25, 2026

View on GitHub

Elevated

Design risk in this codebase.

3issues
Critical & Serious

Top fix

Hide closed dropdown links from keyboard focus, not just opacity

See the fix

Verdict

Solid tokens, shaky states: Pico nails static theming but fumbles the dynamic moments where focus and motion actually matter. A closed dropdown that still traps keyboard focus on invisible links is the kind of bug that undercuts an otherwise accessibility-literate codebase.

Files Rams reviewed

scss/components/_accordion.scss

scss/components/_card.scss

scss/components/_dropdown.scss

scss/components/_group.scss

scss/components/_loading.scss

scss/components/_modal.scss

scss/components/_nav.scss

scss/components/_progress.scss

scss/components/_tooltip.scss

scss/_index.scss

scss/_settings.scss

scss/colors/utilities/_background-colors.scss

scss/colors/utilities/_colors.scss

scss/colors/utilities/_css-vars.scss

scss/colors/utilities/_settings.scss

scss/colors/utilities/_utils.scss

scss/content/_button.scss

scss/content/_code.scss

scss/content/_embedded.scss

scss/content/_link.scss

scss/content/_misc.scss

scss/content/_table.scss

scss/content/_typography.scss

scss/forms/_basics.scss

scss/forms/_checkbox-radio-switch.scss

scss/forms/_input-date.scss

scss/forms/_input-file.scss

scss/forms/_input-range.scss

scss/forms/_input-search.scss

scss/helpers/_functions.scss

97/100

Accessibility

1 critical
AccessibilityCritical

scss/components/_dropdown.scss:159

Closed dropdown submenu links stay keyboard-focusable while invisible

The submenu selector `details.dropdown > summary + ul` is hidden in its closed state with `opacity: 0` alone, while `display: flex` and `position: absolute` stay active and there is no `visibility` or `pointer-events` change. A keyboard user tabbing through the closed dropdown lands on invisible `a` links inside the hidden `ul`, with no visual indicator of where focus is.

Why it matters

A keyboard-only user tabs into a menu that looks closed but is silently swallowing focus, so they lose track of their position on the page with no visible cue to recover.

Fix

Pair opacity with visibility and pointer-events so the closed submenu is removed from the focus order until it opens.

#{$parent-selector} details.dropdown > summary + ul {
    display: flex;
    z-index: 99;
    position: absolute;
    left: 0;
    ...
    opacity: 0;

    @if $enable-transitions {
      transition:
        opacity var(#{$css-var-prefix}transition),
        transform 0s ease-in-out 1s;
    }
#{$parent-selector} details.dropdown > summary + ul {
    display: flex;
    z-index: 99;
    position: absolute;
    left: 0;
    ...
    opacity: 0;
    visibility: hidden;
    pointer-events: none;

    @if $enable-transitions {
      transition:
        opacity var(#{$css-var-prefix}transition),
        visibility 0s linear var(#{$css-var-prefix}transition),
        transform 0s ease-in-out 1s;
    }
  }

  #{$parent-selector} details[open].dropdown > summary + ul {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
98/100

Motion

1 serious
MotionSerious

scss/components/_accordion.scss:18

Accordion summary color transition ignores reduced-motion preference

The `summary` element inside `details` (accordion trigger) applies `transition: color var(#{$css-var-prefix}transition)` guarded only by `$enable-transitions`, a build-time Sass flag, with no runtime `prefers-reduced-motion` media query.

Why it matters

Vestibular-sensitive users who set 'reduce motion' at the OS level still get the animated transition on every accordion toggle, because the guard only exists at compile time, not at the user's runtime preference.

Fix

Wrap transition declarations in @media (prefers-reduced-motion: no-preference) so the OS-level setting is respected at runtime.

summary {
      line-height: 1rem;
      list-style-type: none;
      cursor: pointer;

      @if $enable-transitions {
        transition: color var(#{$css-var-prefix}transition);
      }
summary {
      line-height: 1rem;
      list-style-type: none;
      cursor: pointer;

      @if $enable-transitions {
        @media (prefers-reduced-motion: no-preference) {
          transition: color var(#{$css-var-prefix}transition);
        }
      }

Get this score on every PR.

Rams reviews each pull request on your repo and posts inline one-click fixes — about a minute per review.

Install Rams free
98/100

Craft

1 serious
Design SystemSerious

scss/components/_dropdown.scss:161

Dropdown z-index of 99 is a hardcoded magic number

The submenu rule `#{$parent-selector} details.dropdown > summary + ul` sets `z-index: 99` as a literal integer, while every other value in the same ruleset (border, radius, background, box-shadow, color) goes through a `var(#{$css-var-prefix}...)` token. The z-index is the one property that bypasses that layer.

Why it matters

A future modal, toast, or tooltip added at z-index 100+ without knowing about this arbitrary 99 creates unpredictable stacking bugs, and there is no shared scale to check against before picking a new value.

Fix

Route z-index through the same CSS custom property token layer used for every other value in this ruleset.

#{$parent-selector} details.dropdown > summary + ul {
    display: flex;
    z-index: 99;
    position: absolute;
#{$parent-selector} details.dropdown > summary + ul {
    display: flex;
    z-index: var(#{$css-var-prefix}dropdown-z-index, 99);
    position: absolute;

Typography

No issues found

Color

No issues found

Spacing

No issues found

Components

No issues found

UX

No issues found

Working well

  • The `:focus-visible` box-shadow pattern (removing the default outline but restoring a visible ring only for keyboard focus, using the `--outline-width` and `--primary-focus` tokens) is the correct way to give keyboard users a clear focus indicator without adding a ring to every mouse click.
  • The indeterminate progress bar wraps its looping gradient sweep in `@media (prefers-reduced-motion: no-preference)`, giving reduced-motion users a static bar instead of continuous motion. That's the exact pattern the dropdown and accordion transitions in this review are missing.
  • The native `<dialog>` element with `[open]`/`:not([open])` state handling gets focus trapping and top-layer stacking for free, which avoids the bugs that come with a hand-rolled overlay `div` and z-index juggling.

Scored July 25, 2026 with Rams Engine v0.0.3 · Engine changelog
First scored July 14, 2026: 74/100. This rescore on v0.0.3: 59/100.

This page is an automated design review of picocss/pico’s UI code: 30 files read against 291 versioned rules covering accessibility, color, typography, spacing, components, UX, motion, and craft. The score is out of 100; confirmed criticals cap it — one at 59, two at 49, three or more at 39.

More design scores

Score your own repo.

Free on public repos, no account. The same engine that scored this page reads your UI code and mints a score page like this one.

Public repos only. The full engine reviews the UI code and mints a public score page — we email you the link too. Already-scored repos open instantly.

Or get a design review on every pull requestInstall Rams