A. Uppercase micro
- CSS
12px/700, 0.025em, uppercase; padding 9px 14px; no border- Height
- 36px
- Contrast
- navy 12.4:1; white on navy 12.4:1
Brand exploration · 14 October 2026
Tabs, chips, form controls, tables, breadcrumb, pager, code box, empty state and dialog for Honor Society®. Nine places had competing versions or a gap. Each shows the versions side by side on real site copy, with exact CSS, contrast and a house-style check. All nine choices are decided. The decided version is outlined in navy, and it is what components/ builds. The losing versions stay here for the record. Components with no conflict are at the bottom, with their HTML. All components, with code: components gallery.
| Choice | Decision | Status |
|---|---|---|
| 1. Filter chip label | B: 16px/600 sentence case, 40px | Decided |
| 2. Field label | C: 16px/600 ink | Decided |
| 3. Hint position | B: below the control | Decided |
| 4. Control border | C: slate 500, 3.7:1 | Decided |
| 5. Control focus | B: the shared focus style | Decided |
| 6. Password strength meter | B: brand bar, danger / warning / success | Decided |
| 7. Comparison table current column | B: light head, navy column | Decided |
| 8. “Load more” button | B: navy button, “Show the next 12 articles” | Decided |
| 9. Code box | B: soft panel, monospace, copy button | Decided |
| Settled | Tabs, chips and tags, controls, checks, form alert, password field, data table, breadcrumb, pager, empty state, dialog | Decided |
Decided: B
Which label size and case does a filter chip use? The current chip fills navy in both (decided).
Today on: A on the category bar of /articles and every article page (.hs-mag-nav). B on the Articles tab filter of the member profile (.hs-member-filter__chip). The Benefits jump pills on /benefits are a third shape (13.76px, tier fill); they become B.
12px/700, 0.025em, uppercase; padding 9px 14px; no border16px/600, sentence case; padding 0 16px; 1px #D9DDE7; whiteDecided: C
Which size, weight and colour does the label above a control use?
Today on: A in the theme (theme.css:1523): the legacy forms such as /user/login and the old webforms. B in the profile edit dialogs and on /member/induction (hs_user.form.css). Registration (registration.css) has a fourth label, 14px #5A6270.
12px/600, uppercase, #7E858E (Open Sans, never loaded)14px/600, #59617216px/600, #2B3142Decided: B
Does the hint for a field sit above the control or below it?
Today on: A in the profile edit dialogs (hs-user-form-element.tpl.php). B on every core Drupal form (the field description prints after the control) and in the password rules on /member/induction.
Include the country code, for example +1 for the United States.
Include the country code, for example +1 for the United States.
Decided: C
Which colour is the 1px border of an empty text field, select or textarea?
Today on: A everywhere: #D9DDE7 in the profile dialogs and on /member/induction, #D7DFE9 in the theme forms. B and C are new.
1px solid #D9DDE71px solid #949FB71px solid #7E858E; hover #596172Decided: B
What does a text field look like while the cursor is in it? (Each example shows the focus state without focus.)
Today on: A in the profile dialogs and on /member/induction. B on links and buttons in every new file (round 1). C on the hub and blog files (hs_user.membership.css, hs_blogs.css); the password toggle uses a fourth, 2px #4A90D9.
border #1F2F6E; box-shadow 0 0 0 3px rgba(31,47,110,.12)border #1F2F6E; outline 3px #FAF053, offset 3px; box-shadow 0 0 0 1px #1F2F6Eoutline 2px solid #1F2F6E; offset 2pxDecided: B
How does the meter under the new password show weak, fair and strong? (All three show “fair”: two of three rules met.)
Today on: A on /member/induction and the single-password registration (hs_user.password.css). B and C are new.
#E0E0E0 track; #D9534F / #F0AD4E / #5CB85C at 33/66/100%#E6E8EF track; danger / warning / success at 33/66/100%Decided: B
How does the tier comparison table mark the tier the page is about? (Example: the Gold tier page.)
Today on: A on /membership-tiers and the four tier pages (hs_pages/css/tier-comparison.css). B and C are new.
| Benefit | Free | Bronze | Silver | Gold (this page) | Signature |
|---|---|---|---|---|---|
| Apply to scholarships | Included | Included | Included | Included | Included |
| Career guides by Vault.com | Not included | Included | Included | Included | Included |
| Restaurant.com gift card | Not included | $50 | $150 | $250 | $250 |
| Roadside assistance | Not included | Not included | Included | Included | Included |
| Priority support | Not included | Not included | Not included | Included | Included |
| Sterling silver class ring ($599 value) | Not included | Not included | Not included | Not included | Included |
#1F2F6E, white text#FAF053; cells #FEFBE0; 2px gold sides| Benefit | Free | Bronze | Silver | Gold (this page) | Signature |
|---|---|---|---|---|---|
| Apply to scholarships | Included | Included | Included | Included | Included |
| Career guides by Vault.com | Not included | Included | Included | Included | Included |
| Restaurant.com gift card | Not included | $50 | $150 | $250 | $250 |
| Roadside assistance | Not included | Not included | Included | Included | Included |
| Priority support | Not included | Not included | Not included | Included | Included |
| Sterling silver class ring ($599 value) | Not included | Not included | Not included | Not included | Included |
#D9DDE7 under it#EAF0FF; 2px navy sides#EAF0FF| Benefit | Free | Bronze | Silver | Gold (this page) | Signature |
|---|---|---|---|---|---|
| Apply to scholarships | Included | Included | Included | Included | Included |
| Career guides by Vault.com | Not included | Included | Included | Included | Included |
| Restaurant.com gift card | Not included | $50 | $150 | $250 | $250 |
| Roadside assistance | Not included | Not included | Included | Included | Included |
| Priority support | Not included | Not included | Not included | Included | Included |
| Sterling silver class ring ($599 value) | Not included | Not included | Not included | Not included | Included |
#EAF0FF; 2px navy sidesDecided: B
What does the action under a card grid look like when it shows the next page of cards?
Today on: A on /articles outside the magazine (theme.css:1686, “See more”). B on the Elevate magazine (.hs-mag, hs_blogs.magazine.css:215). C and D are new.
Showing 12 of 48 articles
Show the next 12 articles1.5px solid #1F2F6E; transparent; radius 30pxShowing 12 of 48 articles
Show the next 12 articles.hs-button--navy: 48px, navy fill, white labelShowing 12 of 48 articles
Show the next 12 articles.hs-button--secondary: #EAF0FF fill, navy labelShowing 12 of 48 articles
Show the next 12 articles.hs-link: navy, 2px gold underlineDecided: B
How does the page show the coupon code a member gets after “Redeem benefit”? (Example: the Restaurant.com gift card benefit.)
Today on: A on every coupon benefit page under /benefits-coupons/* after redeem (HsBenefits\Redeemer: a bold label, a line break and the code as plain text, inside style="padding:10px"). B and C are new.
Thank you for your interest in redeeming the benefit, Restaurant.com gift card.
Your promotion code or link:
HSRDC-7Q4M-2K9P
Your promotion code
We emailed this code to you as well.
#F7F8FB, 1px #D9DDE7, radius 8px.hs-button--secondary.hs-button--sm, shown by JSYour promotion code
We emailed this code to you as well.
#7E858E, radius 8pxThese follow the decisions already made, or the site has one version only. Each is live; open “HTML” for the snippet to copy.
Slate 16px/600 labels, 48px tall. Current: navy text and a 3px navy underline on a 1px baseline (decided). Count pill: 13px/600 white with a hairline; navy fill on the current tab. The colours follow the ground, so it works on the plate band of the member profile. Scrolls sideways on a phone. tabs.css.
<nav class="hs-tabs" aria-label="Member pages">
<ul class="hs-tabs__list">
<li class="hs-tabs__item"><a class="hs-tabs__tab" href="#settled" aria-current="page">Profile</a></li>
<li class="hs-tabs__item"><a class="hs-tabs__tab" href="#settled">Articles <span class="hs-tabs__count">12</span></a></li>
</ul>
</nav>Filter chip: the decided B above. A button chip uses aria-pressed. Add hs-chips--scroll for one line that scrolls. Tag: static, 14px/600 ink on soft, 1px line, with an optional slate part for a level. Not a link. chips.css.
<nav aria-label="Benefit categories">
<ul class="hs-chips">
<li><a class="hs-chip" href="?category=all">All benefits</a></li>
<li><a class="hs-chip" href="?category=careers" aria-current="page">Careers</a></li>
<li><a class="hs-chip" href="?category=education">Education</a></li>
</ul>
</nav>
<ul class="hs-chips" aria-label="Skills">
<li class="hs-tag">Public speaking</li>
<li class="hs-tag">Spanish <span class="hs-tag__meta">Fluent</span></li>
<li class="hs-tag">Data analysis</li>
</ul>One class, .hs-control: 40px, 12px side padding, 16px ink, 1px slate 500, radius 4px. Select: navy chevron drawn from the token. Textarea: 120px, grows down. Error: aria-invalid="true" gives a 2px danger edge, and .hs-field-error (14px/600 danger, 5.4:1) under the control says what to fix. Disabled: soft ground. --short 10rem, --medium 20rem. form.css.
<form class="hs-form" action="#" novalidate>
<div class="hs-field">
<label class="hs-label" for="role">Role</label>
<input class="hs-control" id="role" name="role" type="text" autocomplete="organization-title">
</div>
<div class="hs-field">
<label class="hs-label" for="month">Start month <span class="hs-optional">(optional)</span></label>
<select class="hs-control hs-control--medium" id="month" name="month">
<option value="">Month</option>
<option>September</option>
<option>October</option>
</select>
</div>
<div class="hs-field">
<label class="hs-label" for="gpa">GPA</label>
<input class="hs-control hs-control--short" id="gpa" name="gpa" type="text" inputmode="decimal" value="4.3" aria-invalid="true" aria-describedby="gpa-error">
<p class="hs-field-error" id="gpa-error">Enter your GPA as a number from 0 to 5, for example 3.75.</p>
</div>
<div class="hs-field">
<label class="hs-label" for="about">About <span class="hs-optional">(optional)</span></label>
<textarea class="hs-control" id="about" name="about" aria-describedby="about-hint"></textarea>
<p class="hs-hint" id="about-hint">A few sentences about your goals. Members and schools see this on your profile.</p>
</div>
<div class="hs-field">
<label class="hs-label" for="email">Email</label>
<input class="hs-control" id="email" type="email" value="avery.example@example.com" disabled>
</div>
</form>Native 20px box in navy (accent-color): the browser keeps every state, including forced colours. The row is 40px tall, and the whole label is the tap target. A group is a fieldset whose legend uses the label style; its hint and error follow the options. form.css.
<fieldset class="hs-fieldset" aria-describedby="status-hint">
<legend class="hs-label">Educational or professional status</legend>
<div class="hs-fieldset__options">
<div class="hs-check">
<input class="hs-check__input" id="st-ug" type="checkbox" name="status" value="undergraduate" checked>
<label class="hs-check__label" for="st-ug">Undergraduate student</label>
</div>
<div class="hs-check">
<input class="hs-check__input" id="st-gr" type="checkbox" name="status" value="graduate">
<label class="hs-check__label" for="st-gr">Graduate student</label>
</div>
<div class="hs-check">
<input class="hs-check__input" id="st-pro" type="checkbox" name="status" value="professional">
<label class="hs-check__label" for="st-pro">Working professional</label>
</div>
</div>
<p class="hs-hint" id="status-hint">Check all that apply.</p>
</fieldset>
<fieldset class="hs-fieldset">
<legend class="hs-label">Preferred contact</legend>
<div class="hs-fieldset__options">
<div class="hs-check">
<input class="hs-check__input" id="ct-email" type="radio" name="contact" value="email" checked>
<label class="hs-check__label" for="ct-email">Email</label>
</div>
<div class="hs-check">
<input class="hs-check__input" id="ct-phone" type="radio" name="contact" value="phone">
<label class="hs-check__label" for="ct-phone">Phone</label>
</div>
</div>
</fieldset>Fix 2 fields to save your academic record
The danger callout from round 1 at the top of a form that failed, with one link per error that moves focus to the field. It takes role="alert" and receives focus after submit. Ink text on the danger surface, 11.3:1. Replaces .hs-form__alert (danger text on #FDECEC, 4.8:1).
<div class="hs-callout hs-callout--danger hs-form-alert" role="alert" tabindex="-1">
<svg class="hs-callout__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="9"/><path d="M12 7.5v5.5"/><path d="M12 16.4v.1"/></svg>
<div class="hs-callout__body">
<p class="hs-callout__title">Fix 2 fields to save your academic record</p>
<ul class="hs-form-alert__list">
<li><a href="#gpa">Enter your GPA as a number from 0 to 5, for example 3.75.</a></li>
<li><a href="#school">Enter your school.</a></li>
</ul>
</div>
</div>Type in it: the meter bar and the rules react. The reveal toggle is a 40px button inside the control, slate (6.2:1), navy on hover, with aria-pressed and a label that flips between “Show password” and “Hide password”. It ships hidden; password.js shows it. The rules are the site’s HsUser\PasswordRules.
<div class="hs-field hs-password">
<label class="hs-label" for="new-pass">Password</label>
<div class="hs-password__input">
<input class="hs-control" id="new-pass" name="pass" type="password" autocomplete="new-password" aria-describedby="new-pass-rules">
<button class="hs-password__toggle" type="button" aria-label="Show password" aria-pressed="false" hidden>
<svg class="hs-password__icon hs-password__icon--show" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M2 12s3.6-7 10-7 10 7 10 7-3.6 7-10 7S2 12 2 12z"/><circle cx="12" cy="12" r="3"/></svg><svg class="hs-password__icon hs-password__icon--hide" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10.6 5.1A10.4 10.4 0 0 1 12 5c6.4 0 10 7 10 7a17.6 17.6 0 0 1-2.6 3.5M6.6 6.6C3.7 8.5 2 12 2 12s3.6 7 10 7a9.9 9.9 0 0 0 5.4-1.6"/><path d="M9.9 9.9a3 3 0 0 0 4.2 4.2"/><path d="M3 3l18 18"/></svg>
</button>
</div>
<div class="hs-meter">
<span class="hs-meter__fill"></span>
<span class="hs-meter__label hs-visually-hidden" aria-live="polite"></span>
</div>
<ul class="hs-password__rules" id="new-pass-rules">
<li class="hs-password__rule" data-rule="length" data-min="8">8+ characters</li>
<li class="hs-password__rule" data-rule="letter" data-min="1">1 letter</li>
<li class="hs-password__rule" data-rule="digit" data-min="1">1 number</li>
</ul>
</div>| Scholarship | Award | Next deadline |
|---|---|---|
| Core Values Scholarship | $1,000 | Oct 28, 2026 |
| Undergraduate Achiever Scholarship | $2,000 | Nov 14, 2026 |
| Graduate Student Achiever Scholarship | $2,000 | Nov 14, 2026 |
| Society Involvement Award | $1,000 | Oct 28, 2026 |
White panel, 8px radius, 1px line. Cells 12px × 16px, 16px ink, tabular numbers; navy 600 heads over a line-strong rule; hairlines between rows, no stripe. .hs-table__num ends a number column. The wrapper scrolls; the page never does. The comparison table adds --compare (choice 7). table.css.
<div class="hs-table-wrap" role="region" aria-label="Scholarship deadlines" tabindex="0">
<table class="hs-table">
<caption>Member scholarships and their next deadline</caption>
<thead>
<tr><th scope="col">Scholarship</th><th scope="col" class="hs-table__num">Award</th><th scope="col">Next deadline</th></tr>
</thead>
<tbody>
<tr><th scope="row"><a href="/core-values-scholarship">Core Values Scholarship</a></th><td class="hs-table__num">$1,000</td><td>Oct 28, 2026</td></tr>
<tr><th scope="row"><a href="/undergraduate-achiever-scholarship">Undergraduate Achiever Scholarship</a></th><td class="hs-table__num">$2,000</td><td>Nov 14, 2026</td></tr>
<tr><th scope="row"><a href="/graduate-achiever-scholarship">Graduate Student Achiever Scholarship</a></th><td class="hs-table__num">$2,000</td><td>Nov 14, 2026</td></tr>
<tr><th scope="row"><a href="/society-involvement-award">Society Involvement Award</a></th><td class="hs-table__num">$1,000</td><td>Oct 28, 2026</td></tr>
</tbody>
</table>
</div>Only for a trail of at least three steps, above the eyebrow in the page head. 14px slate links with a hairline underline; the slash is CSS; the current page is ink 500, not a link. The site prints no breadcrumb today; Zendesk uses “>”. breadcrumb.css.
<nav class="hs-breadcrumb" aria-label="Breadcrumb">
<ol class="hs-breadcrumb__list">
<li class="hs-breadcrumb__item"><a class="hs-breadcrumb__link" href="/">Home</a></li>
<li class="hs-breadcrumb__item"><a class="hs-breadcrumb__link" href="/scholarships">Scholarships</a></li>
<li class="hs-breadcrumb__item" aria-current="page">Graduate Student Achiever Scholarship</li>
</ol>
</nav>Real links, 40px round targets, 16px/600 navy, tabular numbers. Current page: navy fill, white (12.4:1), as a current chip. On a phone, Previous and Next keep only the arrow (the word stays for screen readers). Replaces the unstyled core Drupal pager. pager.css.
<nav class="hs-pager" aria-label="Pages">
<ul class="hs-pager__list">
<li class="hs-pager__item"><a class="hs-pager__link" href="?page=1" rel="prev"><svg class="hs-pager__arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M15 6l-6 6 6 6"/></svg><span class="hs-pager__word">Previous</span></a></li>
<li class="hs-pager__item"><a class="hs-pager__link" href="?page=1">1</a></li>
<li class="hs-pager__item"><a class="hs-pager__link" href="?page=2" aria-current="page">2</a></li>
<li class="hs-pager__item"><a class="hs-pager__link" href="?page=3">3</a></li>
<li class="hs-pager__item"><span class="hs-pager__gap" aria-hidden="true">…</span></li>
<li class="hs-pager__item"><a class="hs-pager__link" href="?page=8">8</a></li>
<li class="hs-pager__item"><a class="hs-pager__link" href="?page=3" rel="next"><span class="hs-pager__word">Next</span><svg class="hs-pager__arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M9 6l6 6-6 6"/></svg></a></li>
</ul>
</nav>Your articles appear on your profile, under the Articles tab.
Soft panel, 8px, 1px line, centred. Didot title in navy says what is missing; one slate line; one action that fills the list. When the viewer cannot fill it (another member’s articles), drop the icon and the action: “Avery Example hasn’t published any articles yet.” Replaces .hs-blog-empty. empty-state.css.
<div class="hs-empty">
<svg class="hs-empty__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4 20h4L19 9a2.8 2.8 0 0 0-4-4L4 16v4z"/><path d="M13.5 6.5l4 4"/></svg>
<h3 class="hs-empty__title">You have not published an article yet.</h3>
<p class="hs-empty__text">Your articles appear on your profile, under the Articles tab.</p>
<div class="hs-empty__actions">
<a class="hs-button" href="/blog/new" data-ph-capture-attribute-cta="start_article" data-ph-capture-attribute-cta-loc="member-articles">Write an article</a>
</div>
</div>Native <dialog> with showModal(); dialog.js (about 15 lines) opens it, closes it from any data-hs-dialog-close and on a backdrop click. Sizes: --sm 440px, default 560px, --lg 720px. White, 8px, 1px line, dialog shadow; backdrop navy 40%. Didot 22px title; 40px round close button. The body scrolls; the footer stays in view: primary button first, then the secondary pill. Below 480px the actions stack, full width. Try the three buttons.
<button class="hs-button hs-button--secondary hs-button--sm" type="button" data-hs-dialog-open="edit-academic">Edit academic record</button>
<dialog class="hs-dialog" id="edit-academic" aria-labelledby="edit-academic-title">
<header class="hs-dialog__header">
<h2 class="hs-dialog__title" id="edit-academic-title">Edit academic record</h2>
<button class="hs-dialog__close" type="button" aria-label="Close" data-hs-dialog-close>
<svg class="hs-dialog__close-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" aria-hidden="true" focusable="false"><path d="M6 6l12 12M18 6 6 18"/></svg>
</button>
</header>
<form class="hs-dialog__form" action="/user/profile/academic" method="post">
<div class="hs-dialog__body">
<div class="hs-form">
<div class="hs-field">
<label class="hs-label" for="dlg-school">School</label>
<input class="hs-control" id="dlg-school" name="school" type="text" value="Sample College">
</div>
<div class="hs-field">
<label class="hs-label" for="dlg-gpa">GPA <span class="hs-optional">(optional)</span></label>
<input class="hs-control hs-control--short" id="dlg-gpa" name="gpa" type="text" inputmode="decimal" value="3.75">
</div>
</div>
</div>
<footer class="hs-dialog__footer">
<button class="hs-button hs-button--sm" type="submit">Save</button>
<button class="hs-button hs-button--secondary hs-button--sm" type="button" data-hs-dialog-close>Cancel</button>
</footer>
</form>
</dialog>--hs-font-mono is in tokens.css: ui-monospace, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace. code-box.css reads it.dialog.css as --hs-dialog-w. The backdrop has an rgba() literal before a color-mix() of navy, because older engines do not pass custom properties to ::backdrop.--hs-ring-input had no user, so it is removed from the tokens. Focus A above keeps its value as a literal, for the record.dialog.js, code-box.js and password.js are plain scripts with no build step. Each control they drive ships working or hidden without them.components/index.css. The scripts stay separate files.