Dustin Johnson ← Design Primitives
Input Taxonomy · Color & Validation · April 2026

The Color Budget for Inputs

How many colors an input field actually needs, where each one goes, and what happens when semantic states compete for attention on a surface that the user stares at for minutes at a time.

I. Why Inputs Are Harder Than Buttons

A button has a momentary relationship with color. You glance at it, you click it, you move on. An input has a sustained relationship. You look at it while you think about what to type. You look at it while you type. You look at it again when it tells you that what you typed was wrong.

This changes the calculus of color in a fundamental way. A vivid blue that feels confident and inviting on a button can feel aggressive and distracting on an input border that you're staring at for thirty seconds while composing an email address. The sustained-viewing problem means that every color choice on an input field gets more scrutiny — from the user's eyes, not from their conscious attention — than the same color on a button.

Inputs also have more surfaces that need distinct colors than buttons do. A button's color budget is relatively simple: fill, text, border, maybe a shadow. An input's color budget includes the border, the fill, the value text, the placeholder text, the label, the description text, the focus ring, the error message, the success indicator, the icon or adornment, and the caret. That's at least ten distinct color assignments before you've even considered hover and disabled states.

And unlike a button — where the color system primarily conveys hierarchy (primary, secondary, tertiary) — an input's color system primarily conveys state. The same input field, occupying the same position in the layout, needs to look meaningfully different across seven or more states: empty, focused, filled, disabled, read-only, invalid, and valid. The color has to do this work without changing the input's size, position, or shape.

II. Ten Surfaces, One Field

Every part of an input field is a surface that receives a color assignment. The mistake most systems make is treating these as independent decisions. They are not — they are a hierarchy, and the hierarchy has a natural order determined by what the user needs to see first.

LABEL Email address DESCRIPTION We'll never share your email
FOCUS RING
← BORDER
VALUE TEXT
ERROR Please enter a valid email
The ten surfaces: label · description · border · fill · value text · placeholder · focus ring · caret · error text · adornment

The Attention Hierarchy

Not all surfaces compete equally for the user's attention. There is a natural reading order, and the color assignments should reinforce it rather than fight it:

Value text Highest contrast · User's own data
Label What this field is
Error / validation What went wrong
Border Field boundary
Placeholder Hint text
Description Supporting context
Fill / background Container surface
Attention hierarchy — darkest = most important in light mode

The value text must always be the highest-contrast element. It is the user's own data, and the entire purpose of the field is to display it. Everything else is subordinate. The label is second because it identifies the field. Validation messages are third because they require immediate attention when present. The border, placeholder, description, and fill descend from there.

This hierarchy sounds obvious, but it is routinely violated. The most common violation: placeholder text that is styled at the same weight and contrast as value text, making it impossible to tell at a glance which fields are filled and which are empty.

III. The Neutral Base

Before introducing any semantic color — blue for focus, red for error — the input needs a complete monochrome system. This neutral base should work on its own, as if color hadn't been invented yet.

Border Color

The input border is the most contested color decision in the entire field. It must be visible enough to delineate the field boundary (WCAG 1.4.11 requires a 3:1 ratio against the adjacent background for UI components), but quiet enough to not compete with the value text or labels. In practice, this means the border lives in a narrow band of acceptable lightness.

Too faint
#ddd · 1.4:1 FAIL
Safe range
#b0ada5 · 3.2:1 PASS
Too heavy
#555 · 7.5:1 LOUD

The practical range on a white background is approximately #767676 to #b5b5b5 — from the AA text contrast threshold down to just above the 3:1 non-text contrast minimum. Most leading design systems land between #a0a0a0 and #c0c0c0 for their resting border, with Atlassian, Carbon, and Spectrum all settling near the middle of that range. Material Design's outlined variant uses a lighter default border (roughly equivalent to #bbb on white) and relies on the label's movement and the border thickening to signal focus.

A warm gray for borders — one with a slight yellow or orange tint (hue 40–60 in OKLCH) — tends to feel more natural than a pure neutral gray. Compare #b0ada5 (warm) with #ababab (neutral). The warm version disappears into the page more gracefully because most off-white backgrounds carry a similar warmth.

Input Fill

Two schools dominate: white fill with a visible border, or tinted fill with no border (or a very subtle one). Material Design calls these "outlined" and "filled." Each creates a different contrast relationship with the page surface.

White fill, visible border
Outlined · most common
Tinted fill, no border
Filled · material-style
Tinted fill, subtle border
Hybrid · belt-and-suspenders

The outlined approach is more forgiving across different page backgrounds because the white fill creates an explicit container regardless of the surrounding surface color. The filled approach works beautifully on white backgrounds (where the tinted fill provides the contrast) but can get lost on pages that already use a similar gray. The hybrid — a light tint with a subtle border — is the safest option but carries a slight risk of visual heaviness.

On white backgrounds, the fill should be either pure white or a light tint in the range of oklch(0.96–0.98 0.005–0.015 50–80) — just warm enough to read as "different from the page" but not so dark that it muddies the text. On off-white or cream pages like this one, a pure white fill actually works well because the background provides the contrast. On gray surfaces (sidebars, cards), the fill should be one step lighter than the surface.

Text Hierarchy

The text elements within and around an input create their own lightness hierarchy, independent of the border.

Value #1a1a1a
Label #333
Description #6b6b6b
Placeholder #999
Border #b0ada5
Light mode neutral hierarchy — five distinct stops

Notice the gap between label (#333) and description (#6b6b6b). That jump is intentional — it prevents the description from competing with the label for the user's attention. A common mistake is making the description too dark (close to the label) or too light (close to the placeholder), which collapses the hierarchy from five steps to three.

Placeholder text is the most constrained. It needs to be light enough that users don't mistake it for a filled value, but dark enough to be legible. WCAG 1.4.3 requires 4.5:1 for text contrast, which means the lightest acceptable placeholder on white is approximately #767676. Most browser defaults are far lighter than this — Chrome's default placeholder is roughly #a9a9a9 at reduced opacity, which fails AA. If you rely on the default, you are shipping an accessibility failure.

The placeholder paradox: if placeholder text is dark enough to pass contrast requirements, it becomes dark enough to be confused with entered values. The pragmatic resolution is to use a different visual signal in addition to lightness — italic styling, a different font-weight, or a prefix symbol — to distinguish placeholder from value. Or, better yet, avoid placeholder text entirely for critical instructions and use the description field.

IV. Focus — Where Color Enters

In the resting state, the input is monochrome. On focus, color arrives. This is the moment where a single chromatic hue enters the field system, and the choice of that hue carries the same weight as the primary button color choice — because it will be seen more often, for longer, than any button.

The Focus Ring vs. The Focus Border

Two competing strategies exist for signaling focus, and the difference is more than cosmetic — it affects the entire color architecture.

Border color change
Border thickens + changes color
Outer ring
Border unchanged + ring added
Both
Border changes + ring · most robust

Border color change is the Material Design approach. The resting border transitions to the primary color and often thickens from 1px to 2px. It's elegant and compact, but it can be insufficient for users with low vision because the change is only perceptible on the thin edge of the field. It also fails WCAG 2.4.11 (Focus Appearance) if the border area is too small.

Outer ring — implemented as a box-shadow or outline — is more accessible because it adds a visible focus indicator that is distinct from the border and large enough to be noticed. Shadcn/ui, Radix, and most Tailwind-based systems use this approach. The ring is typically 2–3px wide, offset 1–2px from the border.

Both together is the safest choice. The border color change provides the aesthetic refinement; the ring provides the accessibility guarantee. This is the approach used by Adobe Spectrum and several banking and healthcare design systems where compliance is non-negotiable.

Focus Hue Selection

The dominant choice across the industry is blue — somewhere in the hue range of 220–270 in OKLCH. This is not arbitrary. Blue has several properties that make it well-suited for sustained-viewing focus indicators:

Blue · H:260
Industry standard
Indigo · H:280
Deeper · more formal
Teal · H:195
Calm · health/wellness

Blue occupies the perceptual sweet spot: it feels active without feeling urgent (unlike red or orange), it is distinguishable from all semantic validation colors (red, green, yellow), and it has the widest usable chroma range in the OKLCH gamut at mid-lightness values. It also carries a strong cultural association with interactivity — hyperlinks, selection highlights, and OS-level focus indicators have been blue for decades.

Some design systems use their brand's primary color for focus instead of blue. This works when the brand color is already in the blue-to-purple range. It becomes risky when the brand color is red, orange, or green — because those hues collide with the semantic validation palette. A red-branded focus ring on an input that is about to show a red error message creates a confusing color narrative: "Is this focused or invalid?"

Problem: Red brand focus Invalid email
Focus = red, error = red · ambiguous
Solution: Blue focus, red error Invalid email
Focus ≠ error · clear signal
The rule of thumb: if your brand's primary color falls within 30° of either semantic hue (red at ~25°, yellow at ~90°), use a neutral or blue focus color for inputs rather than the brand color. Reserve the brand color for buttons and CTAs where semantic confusion is less likely.

V. The Semantic Palette

Inputs need three semantic colors beyond the neutral base: focus (interactive), error (danger), and warning (caution). Each semantic color appears on multiple surfaces within the field — border, text, icon, background tint — and the relationship between those surfaces must be internally consistent.

The Core Three

The minimum chromatic palette for inputs requires three distinct hues. These hues need to be perceptually separable from each other under all lighting conditions and for users with the most common forms of color vision deficiency (deuteranopia and protanopia, which reduce the ability to distinguish red from green).

Focus H: 260
Error H: 25
Warning H: 90
All at L:0.55 to show comparable perceptual weight

These three hues are well-spaced on the hue wheel: focus blue at 260°, error red-orange at 25°, and warning amber at 90°. Moving error to red-orange (H:25 rather than pure red at H:0) improves visibility for dichromats. Warning at 90° sits comfortably between the other two, distinct from both.

Notice what's absent: a success (green) hue. Many design systems include one, but in practice, most correctly filled input fields should simply return to their neutral resting state. A green "valid" treatment is appropriate only for fields with real-time validation requirements — username availability, password strength meters, promo codes — where the user is actively waiting to know whether their input was accepted. For the vast majority of form fields, "no error" is sufficient signal for "correct." Adding a green border to every valid field turns the form into a stoplight display, as covered in the traps section below.

If your system does require a success state, green-cyan at H:160 works well — it's distant enough from both the warning yellow and the focus blue to remain distinguishable. But treat it as an optional extension of the core palette, not a member of the required set.

Deriving Surfaces from a Single Hue

Each semantic hue generates a set of surface colors: a full-strength version for borders and icons, a darker version for text, and a very light tint for background fills. The relationship between these should be systematic, not arbitrary.

Email address Enter a valid email address
Error state · three surfaces from H:25
Storage limit Approaching 5000 limit
Warning state · three surfaces from H:90

The pattern for deriving surfaces from a semantic hue in OKLCH:

SurfaceLightnessChromaRole
Background tint 0.96–0.98 0.01–0.02 Very faint wash inside the field
Border 0.60–0.68 0.14–0.20 Visible boundary signal
Icon / indicator 0.55–0.62 0.14–0.18 Matches border or slightly darker
Text (message) 0.45–0.52 0.12–0.18 Darkened for 4.5:1 text contrast

The key constraint: the text version of the semantic color must pass 4.5:1 contrast against the input's background. On a white background, this typically means the text needs to be at L:0.52 or darker. Many systems make the mistake of using the border color for the error text — the border color (L:0.65) might pass the 3:1 non-text contrast threshold but fail the 4.5:1 text contrast threshold. These are different WCAG success criteria with different ratios.

VI. The Background Tint Question

When a field enters an error state, should its background color change? The answer is "usually yes, but barely."

Border only Invalid input
No background tint
Border + tint Invalid input
Subtle tint · recommended
Heavy tint Invalid input
Too strong · competes with text

The subtle tint serves an important function: it provides a second, independent signal of the field's state that doesn't rely solely on the border color. This is critical for two reasons. First, WCAG 1.4.1 requires that color not be the only means of conveying information — the tint, border, and text message together provide redundant signals. Second, users who are scanning a long form can spot tinted fields faster than they can read individual border colors, because the tint affects a larger surface area.

The chroma of the tint should be extremely low — C:0.01 to C:0.02 in OKLCH. At C:0.03 or above, the tint starts to reduce the contrast of the value text against the background, which can push the text contrast ratio below 4.5:1 for lighter text colors. At C:0.04+, the tint becomes visually aggressive and makes the field look broken rather than annotated.

VII. Dark Mode — Everything Inverts, Mostly

The shift from light to dark mode is not a simple inversion. The color budget restructures entirely because the contrast relationships reverse: text becomes light-on-dark, borders become lighter than the surface, and chromatic colors that were darkened for text contrast in light mode now need to be lightened for the same reason.

Email address Light mode · resting
Email address Light mode · focused
Email address Invalid email
Light mode
Email address Dark mode · resting
Email address Dark mode · focused
Email address Invalid email
Dark mode

What Changes

Borders lighten. In light mode, borders are darker than the background. In dark mode, they must be lighter. The resting border on a #1a1a1a background needs to be approximately #555 or lighter to maintain the 3:1 contrast ratio. Many dark mode implementations make borders too subtle — a #333 border on a #1a1a1a background has only 1.4:1 contrast and is effectively invisible.

Semantic text colors lighten dramatically. An error text at L:0.50 in light mode (which reads dark red on white) needs to shift to approximately L:0.70–0.75 in dark mode (which reads light red on dark). The hue stays the same; the lightness inverts.

Chroma reduces. Colors at high chroma vibrate against dark backgrounds — a phenomenon called chromatic aberration or "color fringing." Blue text at C:0.18 on black shimmers uncomfortably. Reducing chroma by 20–30% in dark mode (from C:0.18 to C:0.12–0.14) eliminates the vibration without losing the color identity.

Background tints darken instead of lightening. A light-mode error tint at L:0.97 becomes a dark-mode error tint at approximately L:0.20–0.22 — a very slight darkening or warming of the field background rather than a lightening. The chroma should also reduce (C:0.01–0.015) because tints on dark backgrounds are more perceptible than tints on light backgrounds.

The Dark Mode Text Hierarchy

Value #e8e6e1
Label #ccc
Descript. #888
Placeholder #666
Border #555
Dark mode neutral hierarchy

The hierarchy inverts: value text is now the lightest element rather than the darkest. The relative steps between each level should remain proportionally similar to light mode, even though the absolute values are completely different.

VIII. Chroma Budget — How Much Color Is Too Much

Buttons can afford vivid, saturated colors because the interaction is brief. Inputs cannot. A fully saturated blue border on a focused input creates visual tension during the 5–30 seconds that the user is actively typing. The chroma needs to be high enough to signal "this field is active" but low enough to not feel like staring into a neon sign.

C: 0.08 · too muted
Barely reads as blue
C: 0.14 · safe zone
Clear blue, comfortable
C: 0.22 · aggressive
Vivid — tiring at 15+ seconds

The comfortable range for input focus borders is C:0.12–0.16 in OKLCH — notably lower than the C:0.14–0.22 recommended for primary button fills. The button is glanced at; the input border is stared at. This difference in viewing duration justifies a 20–30% chroma reduction.

Error borders can afford slightly more chroma (C:0.16–0.20) because error states are transient and demand immediate attention. The user needs to notice the error, fix it, and move on. The slight discomfort of a more vivid border is acceptable — even desirable — because it creates urgency.

SurfaceLight mode chromaDark mode chromaRationale
Focus border 0.12–0.16 0.10–0.14 Sustained viewing — comfort over urgency
Focus ring 0.14–0.18 at 20–30% opacity 0.12–0.16 at 15–25% opacity Ring is larger than border — opacity tempers it
Error border 0.16–0.20 0.12–0.16 Transient state — urgency is the goal
Error text 0.14–0.18 0.12–0.16 Must be readable as text, not just colored
Error tint (bg) 0.01–0.02 0.01–0.015 Must not reduce value text contrast
Warning border 0.12–0.16 0.10–0.14 Cautionary — less urgent than error
Success border (opt.) 0.10–0.14 0.08–0.12 If used — should be quieter than error
Disabled everything 0.00–0.02 0.00–0.02 Strip chroma — state, not identity

IX. Disabled & Read-Only — The Achromatic States

Disabled and read-only are often conflated in implementation but serve different purposes and should look different.

Email address
Disabled · reduced opacity
Email address
Read-only · visible but inert
Email address
Disabled · dashed border variant

Disabled means "this field exists but you cannot interact with it right now." The visual treatment should reduce all colors toward gray and lower contrast uniformly. Opacity reduction (0.4–0.5 on the whole field, or per-element) is the simplest approach and has the advantage of working automatically regardless of the field's current color state. The alternative — replacing each color with a gray equivalent — gives more control but requires maintaining a parallel set of disabled tokens.

WCAG explicitly exempts disabled elements from contrast requirements, but this exemption should not be read as permission to make disabled fields invisible. Users still need to perceive that a control exists in that position, even if they can't interact with it. A practical minimum: the disabled field should be visible enough that a user can identify it as a field and read its value, even if they can't modify it.

Read-only means "this data is here for reference; it isn't editable." The value text should remain at full contrast because the user may need to read, select, or copy it. The field's editability signals — border, background tint, focus style — should be reduced or removed to indicate that typing won't work. Removing the border entirely and showing the value on a flat surface is the cleanest approach. Some systems use a bottom-border-only style (like Material Design's filled variant without the fill) to indicate read-only.

X. Shape Affects Color Perception

The same border color reads differently at different radii and border widths. This is not a theoretical concern — it produces visible inconsistencies that need to be addressed in the color system.

Sharp · 0px radius
Border feels heavier at corners
Moderate · 8px radius
Balanced · most common
Pill · 999px radius
Border diffuses at curves

Sharp corners concentrate the border color at the point of the angle, making the same blue feel more intense than it does on a rounded field. Pill-shaped fields spread the border color along gentle curves, which softens the perceived intensity. If your system offers multiple shape variants, you may need to adjust the border's lightness or chroma slightly per shape to maintain consistent perceived weight — or accept the variation as a natural property of the shape.

Border width has a similar effect. A 1px border at C:0.16 is barely chromatic — the line is too thin for hue to fully register. A 2px border at the same chroma reads clearly as blue. A 3px border reads as a strong blue band. The practical implication: if your resting border is 1px and your focused border is 2px, the border color will appear to intensify even if you don't change the color value at all. This natural intensification from width change alone can be sufficient for the focus transition — no hue shift needed.

XI. The Full State Matrix

Here is every core state an input field can occupy, with its color assignments in light mode. Each state changes at most three surfaces from the resting state — border, fill, and one text element. Changing more than three surfaces per state transition creates visual noise.

Email address
Empty · resting
Email address
Empty · hover
Email address
Empty · focused
Email address
Filled · resting
Email address
Filled · focused
Email address Enter a valid email
Invalid · resting
Email address Enter a valid email
Invalid · focused
Email address
Disabled

A critical subtlety: the invalid + focused state. When a user tabs into an invalid field to correct it, should the focus ring show the focus color (blue) or the error color (red)? The answer from most mature systems: use the error color for the border and the focus color for the ring, or use the error color for both. The important thing is that the error signal persists — the user is in the field specifically to fix the error, and removing the red border on focus would make the field look "fixed" before anything has actually changed.

XII. The Combinatorial Traps

Certain color combinations that seem reasonable in isolation fail when deployed across a full form. These are the recurring failures from surveying production design systems:

Green for valid on every field. This is the strongest argument against including a success color in the core palette. If every correctly-filled field turns green, a six-field form with one error has five green borders and one red border. The green becomes noise, not signal — the form looks like a Christmas decoration, and the one red field that actually needs attention is harder to spot, not easier. The correct behavior for a valid field is to return to its neutral resting state. Reserve chromatic success treatment for the rare fields where real-time confirmation matters: username availability checks, coupon code validation, and similar async lookups where the user is waiting for a binary answer.

First name
Last name
Email Invalid
Phone
Green everywhere · the error is found but the form looks like a Christmas decoration

Changing the label color to match the semantic state. Turning the label red when the field is invalid makes the label harder to read (red text has lower perceived contrast than black at the same lightness) and creates a visual discontinuity when the user fixes the error and the label snaps back to black. The label should stay neutral; the error message below the field carries the semantic signal.

Using color alone for required field indication. A red asterisk next to "required" fields is so ubiquitous that it hardly seems like a mistake, but it relies solely on color for a meaning distinction. Pair the asterisk with a text cue ("required" or "optional" labels) for accessibility. Better yet, mark the minority — if most fields are required, mark the optional ones instead.

Animating between semantic colors. A border that smoothly transitions from blue (focused) to red (error) passes through purple — a color that has no semantic meaning in the system. Either switch the color instantly (within one frame) or use a brief opacity transition (fade the blue out, fade the red in). Linear color interpolation through HSL or RGB will produce mid-transition hues that confuse the signal.

XIII. Token Architecture

The full input color system in OKLCH, expressed as composable tokens. Hue stays constant across themes; lightness and chroma shift between light and dark mode.

/* ——— Semantic hue primitives ——— */ --hue-focus: 260; --hue-error: 25; --hue-warning: 90; /* ——— Light mode ——— */ --input-bg: #fff; --input-fg: oklch(0.15 0.00 0); --input-border: oklch(0.74 0.01 70); --input-border-hover: oklch(0.65 0.01 70); --input-placeholder: oklch(0.55 0.00 0); --input-label: oklch(0.25 0.00 0); --input-description: oklch(0.50 0.00 0); /* Focus (derives from --hue-focus) */ --input-focus-border: oklch(0.55 0.15 var(--hue-focus)); --input-focus-ring: oklch(0.55 0.16 var(--hue-focus) / 0.22); /* Error (derives from --hue-error) */ --input-error-border: oklch(0.63 0.18 var(--hue-error)); --input-error-text: oklch(0.50 0.17 var(--hue-error)); --input-error-bg: oklch(0.97 0.012 var(--hue-error)); /* Disabled */ --input-disabled-bg: oklch(0.95 0.005 70); --input-disabled-border: oklch(0.88 0.005 70); --input-disabled-fg: oklch(0.65 0.00 0); /* ——— Optional: success (only if real-time validation is needed) ——— */ /* --hue-success: 160; */ /* --input-success-border: oklch(0.60 0.12 var(--hue-success)); */ /* --input-success-text: oklch(0.45 0.12 var(--hue-success)); */ /* --input-success-bg: oklch(0.97 0.012 var(--hue-success)); */ /* ——— Dark mode overrides ——— */ @media (prefers-color-scheme: dark) { --input-bg: oklch(0.20 0.005 70); --input-fg: oklch(0.92 0.005 70); --input-border: oklch(0.40 0.008 70); --input-border-hover: oklch(0.50 0.008 70); --input-placeholder: oklch(0.48 0.00 0); --input-label: oklch(0.82 0.005 70); --input-description: oklch(0.58 0.00 0); --input-focus-border: oklch(0.68 0.12 var(--hue-focus)); --input-focus-ring: oklch(0.68 0.14 var(--hue-focus) / 0.18); --input-error-border: oklch(0.62 0.15 var(--hue-error)); --input-error-text: oklch(0.72 0.14 var(--hue-error)); --input-error-bg: oklch(0.22 0.012 var(--hue-error)); }

This architecture is deliberately flat. Each token references a hue primitive and defines its own L and C values rather than computing them from a base. The temptation to auto-derive every surface from a single "error color" primitive leads to too many intermediate calculations and makes the system harder to debug. Explicit L and C values per surface, per theme, are easier to audit and adjust.

XIV. The Decision Sequence

When building the input color system from scratch, the decisions cascade in this order:

1. Establish the neutral text hierarchy. Five stops from value text (darkest) to fill (lightest). Test with a monochrome display to confirm the hierarchy reads without any color at all.

2. Set the resting border. Find the lightness value that passes 3:1 against your page background and your input fill simultaneously. Decide warm or cool tint.

3. Choose the focus hue. Default to blue unless your brand color is in the safe zone (blue to purple). Test the focus hue against error and warning to confirm they are visually distinct.

4. Set the semantic hues. Error (red-orange) and warning (yellow-amber) are the required pair. If your product needs real-time validation feedback on specific fields, add success (green-cyan) — but treat it as an extension, not a default.

5. Derive surfaces from each hue. Four lightness stops per hue: background tint (L:0.96+), border (L:0.60–0.68), icon (L:0.55–0.62), text (L:0.45–0.52). Set chroma per the budget table.

6. Build the dark mode equivalents. Invert the lightness ladder, reduce chroma by 20–30%, and test for vibration on a real screen in a dim room.

7. Test the combinatorial states. Render a form with fields in every state simultaneously: resting, focused, filled, disabled, invalid-resting, invalid-focused. Place it on both light and dark backgrounds. If any two states are confusable, revisit the distinction.

8. Test with simulated color vision deficiency. Run the full state matrix through deuteranopia and protanopia simulations. If you are using a success color, the most common failure is red error and green success borders that become indistinguishable. Fix by ensuring these states differ in lightness, not just hue — a lighter green and a darker red will remain distinguishable even when the hue collapses. This is another reason to avoid success color unless it earns its place.

The test for a complete input color system: print your form on a monochrome printer. If you can still distinguish every state, the system works. If any states collapse, you are relying on hue alone — add a lightness, weight, or structural distinction (dashed borders for disabled, thicker borders for error) to make the states legible without color.

Part of the Input Taxonomy. The companion series to the Button Taxonomy (Parts I–IV).
The best input color system is the one where color confirms what structure already implies.