From hl-design-systems
**Core rule:** ALL buttons are sharp rectangles — `border-radius: 0`. NEVER use pill or rounded buttons.
npx claudepluginhub horizenlabs/hl-claude-marketplace --plugin hl-design-systemsdesign-systems/horizenlabs-design-system/references/# Horizen Labs Components ## Buttons **Core rule:** ALL buttons are sharp rectangles — `border-radius: 0`. NEVER use pill or rounded buttons. ### Base Button Styles ### Variants | Variant | Background | Text | Border | Hover | |---|---|---|---|---| | Primary | `--hl-navy` | `--hl-white` | none | `--hl-teal` bg, `--hl-navy` text | | Secondary | transparent | `--hl-navy` | 2px solid `--hl-navy` | `--hl-navy` bg, white text | | Teal | `--hl-teal` | `--hl-navy` | none | `--hl-teal-text` bg | | Ghost | transparent | `--hl-navy` | 1px solid `--hl-grey` | `--hl-grey-light` bg | | Link | tran...
/componentsSafely update or add shadcn/ui components in a RedwoodSDK project with backup/restore
Core rule: ALL buttons are sharp rectangles — border-radius: 0. NEVER use pill or rounded buttons.
.hl-btn {
font-family: 'Roboto', sans-serif;
font-weight: 700;
font-size: 14px;
letter-spacing: 2.8px;
text-transform: uppercase;
padding: 20px 30px;
border-radius: 0;
border: none;
cursor: pointer;
transition: var(--hl-transition-fast);
display: inline-flex;
align-items: center;
gap: 10px;
}
| Variant | Background | Text | Border | Hover |
|---|---|---|---|---|
| Primary | --hl-navy | --hl-white | none | --hl-teal bg, --hl-navy text |
| Secondary | transparent | --hl-navy | 2px solid --hl-navy | --hl-navy bg, white text |
| Teal | --hl-teal | --hl-navy | none | --hl-teal-text bg |
| Ghost | transparent | --hl-navy | 1px solid --hl-grey | --hl-grey-light bg |
| Link | transparent | --hl-teal-text | none | underline + arrow-box hover |
translateY(-2px) lift + shadow escalation to --hl-shadow-lgtranslateY(0) (pressed)opacity: 0.5; cursor: not-allowed; transform: none (no lift)outline: 2px solid var(--hl-teal); outline-offset: 2px.hl-btn-primary:hover {
background: var(--hl-teal);
color: var(--hl-navy);
transform: translateY(-2px);
box-shadow: var(--hl-shadow-lg);
}
.hl-btn-secondary:hover {
background: var(--hl-navy);
color: var(--hl-white);
transform: translateY(-2px);
}
Key rule: Primary hover flips from navy bg/white text to teal bg/navy text — a high-contrast color shift that provides strong visual feedback. Every button variant gets translateY(-2px) on hover. Disabled buttons must override with transform: none.
Used with link buttons and card CTAs. A square icon container with a directional chevron.
.hl-arrow-box {
display: inline-flex;
align-items: center;
justify-content: center;
width: 25px;
height: 25px;
border: 2px solid currentColor;
border-radius: 0;
position: relative;
}
.hl-arrow-box::after {
content: '';
width: 8px;
height: 8px;
border-right: 2px solid currentColor;
border-top: 2px solid currentColor;
transform: rotate(45deg);
margin-left: -2px;
}
Hover behavior: Arrow translates slightly right, box border color shifts to teal.
Core rule: ALL cards are sharp rectangles — border-radius: 0.
.hl-card {
background: var(--hl-white);
border: 1px solid var(--hl-border);
border-radius: 0;
padding: 20px;
box-shadow: var(--hl-shadow-sm);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.hl-card:hover {
transform: translateY(-4px);
border-color: var(--hl-border-hover);
box-shadow: var(--hl-shadow-card-hover);
}
Every card uses a three-part hover: lift + shadow escalation + accent reveal.
Left-border reveal (feature cards):
.hl-card::before {
content: '';
position: absolute;
top: 0; left: 0;
width: 3px; height: 0;
background: linear-gradient(180deg, var(--hl-teal), var(--hl-magenta));
transition: height 0.4s ease;
}
.hl-card:hover::before { height: 100%; }
Bottom-border reveal (reason/info cards):
.hl-card::after {
content: '';
position: absolute;
bottom: 0; left: 0; right: 0;
height: 2px;
background: linear-gradient(90deg, var(--hl-teal), var(--hl-magenta));
transform: scaleX(0);
transition: transform 0.4s ease;
transform-origin: left;
}
.hl-card:hover::after { transform: scaleX(1); }
Key rules:
translateY(-4px) to translateY(-6px) depending on card size--hl-shadow-sm → --hl-shadow-card-hover0.4s ease (slightly slower than the lift for staggered feel)| Variant | Background | Border | Hover | Special |
|---|---|---|---|---|
| Standard | --hl-white | 1px --hl-grey-input | --hl-teal-light bg | Default shadow |
| Grey | --hl-grey-light | none | --hl-teal-light bg | No shadow |
| Teal | --hl-white | 2px --hl-teal | --hl-teal-light bg | Teal border accent |
| Dark | --hl-navy | none | --hl-navy-hover bg | White text, rare usage |
| Expertise | --hl-white | 1px --hl-grey-input | --hl-teal-light bg | Fixed width 330px |
| Blog | --hl-white | none | --hl-teal-light bg | No border, image top |
| Research | --hl-white | 1px --hl-grey-input | --hl-teal-light bg | Horizontal layout |
[Optional Image — sharp, no border-radius]
[Badge — sharp, uppercase]
[Title — Azeret Mono, bold]
[Description — Roboto, grey-text]
[Link with Arrow Box]
.hl-modal-overlay {
background: rgba(4, 23, 66, 0.7);
z-index: var(--hl-z-modal);
}
.hl-modal {
background: var(--hl-white);
border-radius: 0;
max-width: 480px;
width: 90%;
padding: 40px;
box-shadow: var(--hl-shadow-lg);
}
.hl-modal-title {
font-family: 'Azeret Mono', monospace;
font-weight: 700;
font-size: 22px;
color: var(--hl-navy);
}
.hl-modal-close {
width: 25px;
height: 25px;
border: 2px solid var(--hl-grey);
border-radius: 0;
background: none;
cursor: pointer;
}
Key difference: Navigation uses WHITE/frosted background (not dark like other brands).
.hl-nav {
background: rgba(255, 255, 255, 0.85);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
height: 64px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 clamp(16px, 4vw, 48px);
position: fixed;
top: 3px; /* Below gradient accent bar */
left: 0; right: 0;
z-index: var(--hl-z-nav);
border-bottom: 1px solid var(--hl-border);
}
/* Gradient accent bar sits ABOVE the navbar */
.hl-gradient-accent {
position: fixed;
top: 0; left: 0; right: 0;
height: 3px;
background: linear-gradient(90deg, var(--hl-magenta), var(--hl-teal));
z-index: 1000;
}
.hl-nav-link {
font-family: 'Roboto', sans-serif;
font-weight: 600;
font-size: 14px;
letter-spacing: 3.2px;
text-transform: uppercase;
color: var(--hl-navy);
text-decoration: none;
}
.hl-nav-link:hover {
color: var(--hl-teal-text);
}
.hl-nav-cta {
background: var(--hl-navy);
color: var(--hl-white);
font-family: 'Roboto', sans-serif;
font-weight: 700;
font-size: 14px;
letter-spacing: 2.8px;
text-transform: uppercase;
padding: 0 30px;
height: 80px;
display: flex;
align-items: center;
border: none;
border-radius: 0;
margin-right: -40px; /* Flush with nav edge */
}
.hl-input {
font-family: 'Roboto', sans-serif;
font-size: 16px;
padding: 18px 30px;
border: 1px solid var(--hl-grey-input);
border-radius: 0;
background: var(--hl-white);
color: var(--hl-navy);
width: 100%;
transition: var(--hl-transition-fast);
}
.hl-input:focus {
border-color: var(--hl-teal);
outline: none;
box-shadow: 0 0 0 2px rgba(76, 223, 221, 0.2);
}
.hl-input::placeholder {
color: var(--hl-grey);
}
.hl-label {
font-family: 'Roboto', sans-serif;
font-weight: 600;
font-size: 11px;
letter-spacing: 2.4px;
text-transform: uppercase;
color: var(--hl-grey-text);
margin-bottom: 8px;
display: block;
}
.hl-newsletter-combo {
display: flex;
border: 1px solid var(--hl-grey-input);
border-radius: 0;
}
.hl-newsletter-combo .hl-input {
border: none;
flex: 1;
}
.hl-newsletter-combo .hl-btn {
border-radius: 0;
white-space: nowrap;
}
Style: Left-border alerts — 4px solid left border with status color, status color bg at 12%.
.hl-alert {
padding: 16px 20px;
border-radius: 0;
border-left: 4px solid;
display: flex;
align-items: flex-start;
gap: 12px;
}
.hl-alert-success {
border-color: var(--hl-success);
background: rgba(16, 185, 129, 0.12);
}
.hl-alert-error {
border-color: var(--hl-error);
background: rgba(239, 68, 68, 0.12);
}
.hl-alert-warning {
border-color: var(--hl-warning);
background: rgba(245, 158, 11, 0.12);
}
.hl-alert-info {
border-color: var(--hl-info);
background: rgba(59, 130, 246, 0.12);
}
.hl-badge {
font-family: 'Roboto', sans-serif;
font-weight: 700;
font-size: 12px;
letter-spacing: 2.4px;
text-transform: uppercase;
padding: 6px 14px;
border: 2px solid;
border-radius: 0;
display: inline-block;
}
| Variant | Background | Border | Text |
|---|---|---|---|
| Default | transparent | --hl-navy | --hl-navy |
| Teal | --hl-teal-badge-bg | --hl-teal | --hl-teal-text |
| Magenta | rgba(242,81,234,0.12) | --hl-magenta | --hl-magenta |
| Success | rgba(16,185,129,0.12) | --hl-success | --hl-success |
| Error | rgba(239,68,68,0.12) | --hl-error | --hl-error |
| Grey | --hl-grey-light | --hl-grey | --hl-grey-text |
.hl-toast {
background: var(--hl-navy);
color: var(--hl-white);
font-family: 'Roboto', sans-serif;
font-weight: 600;
font-size: 14px;
letter-spacing: 2.4px;
text-transform: uppercase;
padding: 16px 24px;
border-radius: 0;
box-shadow: var(--hl-shadow-lg);
display: flex;
align-items: center;
gap: 12px;
z-index: var(--hl-z-toast);
}
.hl-table {
width: 100%;
border-collapse: collapse;
}
.hl-table th {
font-family: 'Roboto', sans-serif;
font-weight: 700;
font-size: 12px;
letter-spacing: 2.4px;
text-transform: uppercase;
color: var(--hl-navy);
padding: 12px 16px;
text-align: left;
border-bottom: 2px solid var(--hl-teal);
}
.hl-table td {
font-family: 'Roboto', sans-serif;
font-size: 14px;
padding: 14px 16px;
border-bottom: 1px solid var(--hl-grey-input);
color: var(--hl-navy);
}
.hl-table tr:hover td {
background: var(--hl-teal-light);
}
.hl-numbered-item {
background: var(--hl-grey-light);
padding: 25px;
border-radius: 0;
display: flex;
gap: 20px;
align-items: flex-start;
}
.hl-numbered-item-number {
font-family: 'Azeret Mono', monospace;
font-weight: 700;
font-size: 22px;
color: var(--hl-teal-text);
min-width: 40px;
}
/* Number format: "01", "02", "03" — always two digits */
.hl-tab {
font-family: 'Azeret Mono', monospace;
font-weight: 700;
font-size: 22px;
color: var(--hl-grey);
padding: 16px 24px;
border-left: 6px solid transparent;
cursor: pointer;
transition: var(--hl-transition-fast);
}
.hl-tab:hover {
color: var(--hl-navy);
border-color: var(--hl-grey);
}
.hl-tab.active {
color: var(--hl-navy);
border-color: var(--hl-teal);
}
.hl-accordion-header {
font-family: 'Azeret Mono', monospace;
font-weight: 700;
font-size: 22px;
color: var(--hl-navy);
padding: 20px 0;
border-bottom: 1px solid var(--hl-grey-input);
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
}
.hl-accordion-header:hover {
color: var(--hl-teal-text);
}
.hl-accordion-icon {
font-size: 24px;
transition: var(--hl-transition-normal);
}
/* Closed: "+" icon. Open: rotates to "x" (45deg rotation) */
.hl-accordion-header.open .hl-accordion-icon {
transform: rotate(45deg);
}
.hl-accordion-body {
padding: 20px 0;
font-family: 'Roboto', sans-serif;
font-size: 16px;
line-height: 1.7;
color: var(--hl-grey-text);
}
.hl-wallet-modal {
background: var(--hl-white);
border-radius: 0;
max-width: 480px;
padding: 40px;
}
.hl-wallet-option {
display: flex;
align-items: center;
gap: 16px;
padding: 16px;
border: 1px solid var(--hl-grey-input);
border-radius: 0;
cursor: pointer;
transition: var(--hl-transition-fast);
}
.hl-wallet-option:hover {
background: var(--hl-teal-light);
border-color: var(--hl-teal);
}
.hl-wallet-icon-box {
width: 36px;
height: 36px;
border-radius: 0;
display: flex;
align-items: center;
justify-content: center;
}
.hl-wallet-status {
font-family: 'Roboto', sans-serif;
font-weight: 700;
font-size: 12px;
letter-spacing: 2.4px;
text-transform: uppercase;
}
.hl-tx-modal {
background: var(--hl-white);
border-radius: 0;
max-width: 480px;
padding: 40px;
text-align: center;
}
.hl-tx-hash {
font-family: 'Azeret Mono', monospace;
font-size: 13px;
color: var(--hl-grey-text);
background: var(--hl-grey-light);
padding: 8px 12px;
border-radius: 0;
word-break: break-all;
}
.hl-network-badge {
font-family: 'Roboto', sans-serif;
font-weight: 700;
font-size: 13px;
letter-spacing: 2.4px;
text-transform: uppercase;
padding: 6px 14px;
border: 2px solid var(--hl-teal);
border-radius: 0;
display: inline-flex;
align-items: center;
gap: 8px;
}
.hl-network-dot {
width: 8px;
height: 8px;
border-radius: 50%; /* One of the few round elements */
background: var(--hl-success);
}
.hl-address {
font-family: 'Azeret Mono', monospace;
font-size: 14px;
color: var(--hl-navy);
background: var(--hl-grey-light);
padding: 10px 16px;
border-radius: 0;
display: inline-flex;
align-items: center;
gap: 8px;
}
.hl-address-copy {
width: 25px;
height: 25px;
border: 2px solid var(--hl-grey);
border-radius: 0;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
}
CRITICAL: Avatars are SHARP SQUARES, not circles. This is a key brand distinction.
.hl-avatar {
width: 40px;
height: 40px;
background: var(--hl-navy);
border-radius: 0; /* SQUARE, not circle */
display: flex;
align-items: center;
justify-content: center;
color: var(--hl-white);
font-family: 'Azeret Mono', monospace;
font-weight: 700;
font-size: 14px;
}
/* Sizes: sm 32px, md 40px, lg 56px, xl 72px */
viewBox="0 0 76 76" for each icon#041742 (navy).hl-icon-grid.hl-icon-itemarrow-right, arrow-left, arrow-up, arrow-down, chevron-right, chevron-left, chevron-up, chevron-down, close, menu, search, settings, home, user, users, mail, phone, link, external-link, copy, check, plus, minus, edit, trash, download, upload, filter, sort, calendar, clock, globe, lock, unlock, eye, eye-off, code, terminal, database, server, shield, zap, layers, grid
viewBox="0 0 152 152" for each illustration#illus-1 through #illus-29.hl-icon-tile {
width: 70px;
height: 70px;
border-radius: 0;
display: flex;
align-items: center;
justify-content: center;
}
.hl-icon-tile--mint {
background: var(--hl-teal-light);
}
.hl-icon-tile--teal {
background: var(--hl-teal);
}
<use> pattern:
<svg class="hl-icon" width="25" height="25">
<use href="#icon-arrow-right"></use>
</svg>
<body> tag.fill from parent via currentColor.aria-hidden="true" on decorative icons.aria-label on interactive icon-only buttons.Soft glows around interactive and status elements:
/* Teal glow on active progress dots */
.step-active .progress-dot {
box-shadow: 0 0 16px rgba(76, 223, 221, 0.4);
}
/* Status dot glow */
.status-dot.online {
box-shadow: 0 0 8px rgba(34, 197, 94, 0.5);
}
/* Spinner glow */
.spinner-large {
box-shadow: 0 0 24px rgba(76, 223, 221, 0.3);
}
/* Teal shadow token for balloons/tooltips */
--shadow-teal: 0 4px 24px rgba(76, 223, 221, 0.15);
Rules:
Subtle grid and dot patterns add texture to sections without competing with content:
.grid-bg {
position: absolute;
inset: 0;
background-image:
linear-gradient(rgba(4, 23, 66, 0.05) 1px, transparent 1px),
linear-gradient(90deg, rgba(4, 23, 66, 0.05) 1px, transparent 1px);
background-size: 60px 60px;
mask-image: radial-gradient(ellipse 60% 50% at 50% 50%, black 0%, transparent 100%);
pointer-events: none;
z-index: 0;
}
.dot-pattern {
position: absolute;
inset: 0;
background-image: radial-gradient(circle, rgba(4, 23, 66, 0.1) 1px, transparent 1px);
background-size: 24px 24px;
mask-image: radial-gradient(ellipse 50% 60% at 50% 30%, black 0%, transparent 100%);
pointer-events: none;
z-index: 0;
}
.dark-section .grid-bg {
background-image:
linear-gradient(rgba(255,255,255,0.04) 1px, transparent 1px),
linear-gradient(90deg, rgba(255,255,255,0.04) 1px, transparent 1px);
}
Rules:
mask-image so patterns fade out toward edgesLarge blurred circles placed behind hero content create atmosphere:
.bg-glow {
position: absolute;
border-radius: 50%;
filter: blur(120px);
pointer-events: none;
z-index: 0;
}
/* Typical placement */
.hero .glow-teal { width: 700px; height: 700px; background: rgba(76, 223, 221, 0.08); top: 5%; right: -15%; }
.hero .glow-magenta { width: 600px; height: 600px; background: rgba(242, 81, 234, 0.05); bottom: 5%; left: -15%; }
Rules:
z-index: 0, content must have z-index: 1Use for hero headings or emphasis words — sparingly:
.gradient-text {
background: linear-gradient(135deg, var(--hl-teal-text) 0%, var(--hl-magenta) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
Rules:
A consistent label format used above every section heading:
.section-label {
font-family: var(--hl-font-heading); /* Azeret Mono */
font-size: 11px;
font-weight: 600;
letter-spacing: 4px;
text-transform: uppercase;
color: var(--hl-teal-text);
display: flex;
align-items: center;
gap: 12px;
}
.section-label::before {
content: '';
width: 24px;
height: 1px;
background: var(--hl-teal);
}
Rules:
[teal dash] SECTION LABEL → heading → optional subhead::before dash is 24px wide, 1px tall, tealA centered decorative label with gradient dashes on both sides:
.hero-eyebrow {
font-family: var(--hl-font-heading);
font-size: 12px;
font-weight: 600;
letter-spacing: 5px;
text-transform: uppercase;
color: var(--hl-teal-text);
display: flex;
align-items: center;
justify-content: center;
gap: 16px;
}
.hero-eyebrow::before { content: ''; width: 40px; height: 1px; background: linear-gradient(90deg, transparent, var(--hl-teal)); }
.hero-eyebrow::after { content: ''; width: 40px; height: 1px; background: linear-gradient(90deg, var(--hl-teal), transparent); }
.log-entry.highlight {
border-left-color: var(--hl-teal);
background: rgba(76, 223, 221, 0.05);
animation: log-blink 0.6s ease 3;
}
@keyframes log-blink {
0%, 100% { background: rgba(76, 223, 221, 0.05); }
50% { background: rgba(76, 223, 221, 0.15); }
}
@keyframes pulse-text {
0%, 100% { opacity: 1; }
50% { opacity: 0.4; }
}
/* Usage: animation: pulse-text 2s ease-in-out infinite; */
.arrow-dot {
width: 12px; height: 12px;
border-radius: 50%;
animation: arrow-move 1s ease-in-out infinite alternate;
}
.arrow-dot.teal { background: var(--hl-teal); box-shadow: 0 0 16px var(--hl-teal); }
.arrow-dot.magenta { background: var(--hl-magenta); box-shadow: 0 0 16px var(--hl-magenta); }
@keyframes arrow-move { from { left: 0; } to { left: calc(100% - 12px); } }
prefers-reduced-motion: reduceFor sections on navy backgrounds (architecture diagrams, demo panels):
.dark-section {
background: var(--hl-navy-deep); /* #020e2b — slightly darker than navy */
}
/* Frosted glass cards within dark sections */
.dark-section .card {
border: 1px solid rgba(255,255,255,0.1);
background: rgba(255,255,255,0.05);
backdrop-filter: blur(8px);
}
.dark-section .card:hover {
border-color: var(--hl-teal);
box-shadow: 0 0 40px rgba(76, 223, 221, 0.2);
}
Rules:
rgba(255,255,255,*) for borders and text (not named colors)Use consistent color coding for semantic categories:
| Color | Meaning | Examples |
|---|---|---|
| Navy (#041742) | User/system, primary actions | Buyer column, buttons, headings |
| Teal (#4CDFDD) | Platform/TEE, active states | Vela column, active dots, highlights |
| Magenta (#F251EA) | Accent, gradients, special emphasis | Seller column, gradient endpoints |
| Specific blues (#6C8EFF) | Buyer-specific UI elements | Buyer header dots |
Rules:
::-webkit-scrollbar { width: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: rgba(4, 23, 66, 0.15); }
::-webkit-scrollbar-thumb:hover { background: rgba(4, 23, 66, 0.25); }
Instead of rigid breakpoints for type and spacing, use clamp():
/* Heading sizes */
font-size: clamp(28px, 4vw, 48px); /* Section headings */
font-size: clamp(36px, 6vw, 72px); /* Hero h1 */
font-size: clamp(32px, 5vw, 56px); /* Page hero h1 */
/* Section padding */
padding: clamp(60px, 10vw, 120px) 0;
/* Content container */
padding: 0 clamp(20px, 4vw, 48px);
Rules:
clamp() for all heading font sizes and section paddingvw as the preferred unit (2vw–6vw range)When building any new page, ensure these are present:
prefers-reduced-motion respected