/wire-template.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ARTSABERS — Form Component Spec V1</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700&family=Space+Grotesk:wght@400;500;600;700&family=Orbitron:wght@400;500;600;700;800&family=Onest:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
:root {
/* Ember ombre — the ONE brand voice */
--ember-glow: #FFB347;
--ember-bright: #FF9540;
--ember: #FF7A2E;
--ember-forge: #E85D18;
--ember-deep: #D14810;
--ember-smoulder: #8B2E08;
--ember-scar: #5A1A00;
--on-primary-fixed: #2A0800;
/* Hull ladder */
--carbon: #060606;
--void: #0A0A0A;
--charcoal: #141414;
--charcoal-warm: #161412;
--hull-panel: #1A1A1A;
--hull-panel-lift: #242424;
--hull-panel-dark: #0F0F0F;
--hull-chrome-shadow: #2E2E2E;
--hull-edge: #363636;
/* Chrome / whites */
--chrome-highlight: #FAFAFA;
--chrome-glint: #E8E4DD;
--chrome-warm: #F5F0E8;
--chrome-dim: #B8B0A6;
/* Proposed forge-red token — SAS1 gap flagged in operator summary.
Sits in the ember family (warm red-orange) but distinguishable from
the ember gradient so error state doesn't compete with primary CTA. */
--forge-red: #E63929;
--forge-red-deep: #A82212;
/* Surface semantics */
--bg-page: var(--charcoal);
--bg-panel: var(--hull-panel);
--bg-input: var(--hull-panel-lift);
--bg-panel-dark: var(--hull-panel-dark);
--bg-elevated: var(--hull-panel-lift);
--text-primary: var(--chrome-warm);
--text-dim: var(--chrome-dim);
--text-heading: var(--chrome-highlight);
--text-on-ember: var(--on-primary-fixed);
/* Typography */
--font-display: 'Orbitron', system-ui, sans-serif;
--font-body: 'Onest', system-ui, sans-serif;
/* Shadows */
--panel-lift: inset 0 1px 0 rgba(250,250,250,0.08), 0 8px 24px -8px rgba(0,0,0,0.9);
--ember-glow-sm: 0 0 16px rgba(255,122,46,0.35);
--ember-glow-md: 0 0 24px rgba(255,122,46,0.55);
--input-focus-glow: 0 0 12px rgba(255,122,46,0.35);
--input-error-glow: 0 0 10px rgba(230,57,41,0.30);
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { background: var(--carbon); }
body {
font-family: var(--font-body);
font-size: 16px;
line-height: 1.55;
color: var(--text-primary);
min-height: 100vh;
position: relative;
background:
radial-gradient(ellipse 60% 40% at 8% 0%, rgba(255,122,46,0.12) 0%, rgba(255,122,46,0.04) 30%, transparent 60%),
linear-gradient(180deg, var(--charcoal) 0%, var(--carbon) 100%);
background-attachment: fixed;
}
/* Panel-joint hairlines every ~240px */
body::before {
content: "";
position: fixed;
inset: 0;
pointer-events: none;
background-image: repeating-linear-gradient(
to bottom,
transparent 0px,
transparent 239px,
rgba(250,250,250,0.03) 239px,
rgba(250,250,250,0.03) 240px,
transparent 240px,
transparent 241px
);
z-index: 0;
}
.layout { position: relative; z-index: 1; max-width: 1240px; margin: 0 auto; padding: 0 40px; }
/* ─── Compact reference header ─── */
.spec-header {
padding: 48px 56px 52px;
border-bottom: 1px solid rgba(255,122,46,0.25);
box-shadow: 0 1px 0 rgba(255,122,46,0.15), 0 8px 32px -12px rgba(255,122,46,0.20);
margin-bottom: 8px;
}
.spec-header__eyebrow {
font-family: var(--font-display);
font-size: 12px;
letter-spacing: 0.16em;
text-transform: uppercase;
color: var(--ember);
font-weight: 500;
margin-bottom: 16px;
}
.spec-header__title {
font-family: var(--font-display);
font-size: 64px;
line-height: 1;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.8px;
color: var(--text-heading);
margin-bottom: 20px;
}
.spec-header__lede {
font-family: var(--font-body);
font-size: 16px;
color: var(--text-dim);
max-width: 720px;
line-height: 1.6;
}
.spec-header__meta {
display: flex;
gap: 24px;
margin-top: 20px;
font-family: var(--font-display);
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--text-dim);
}
.spec-header__meta span strong { color: var(--chrome-warm); font-weight: 500; margin-left: 6px; }
/* ─── Ember panel seam divider ─── */
.seam {
height: 2px;
margin: 72px 0 40px;
background: linear-gradient(90deg, transparent 0%, var(--ember) 20%, var(--ember-glow) 50%, var(--ember) 80%, transparent 100%);
opacity: 0.75;
box-shadow: 0 0 24px rgba(255,122,46,0.45), 0 8px 32px -8px rgba(255,122,46,0.30);
}
/* ─── Section wrapper (worked example) ─── */
.example {
padding: 24px 0 48px;
}
.example__eyebrow {
font-family: var(--font-display);
font-size: 11px;
letter-spacing: 0.16em;
text-transform: uppercase;
color: var(--ember);
font-weight: 500;
margin-bottom: 10px;
}
.example__title {
font-family: var(--font-display);
font-size: 42px;
line-height: 1.05;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.8px;
color: var(--text-heading);
margin-bottom: 8px;
}
.example__caption {
font-family: var(--font-body);
font-size: 14px;
color: var(--text-dim);
max-width: 640px;
margin-bottom: 40px;
}
/* ─── Form panel (the raised plate the form sits on) ─── */
.form-panel {
background: var(--bg-panel);
padding: 32px 36px 40px;
box-shadow: var(--panel-lift);
position: relative;
}
/* Form fieldset — bordered content group, Kyber Hull hairline */
.form-fieldset {
border: 1px solid var(--hull-edge);
padding: 32px 40px 40px;
margin-bottom: 40px;
margin-inline: 0;
}
.form-fieldset:last-child { margin-bottom: 0; }
.form-fieldset__heading {
font-family: var(--font-display);
font-size: 20px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.8px;
color: var(--text-heading);
padding: 0 12px;
margin-inline-start: -4px;
margin-bottom: 24px;
}
/* Subtle ember hairline divider (for My Account sections) */
.form-divider {
margin: 40px 0 32px;
height: 1px;
background: linear-gradient(90deg, transparent, rgba(255,122,46,0.30) 50%, transparent);
}
/* ─── Field row layout ─── */
.form-grid {
display: grid;
grid-template-columns: 1fr;
gap: 22px 20px;
margin-bottom: 22px;
}
.form-grid--2col { grid-template-columns: 1fr 1fr; }
.form-grid--3col { grid-template-columns: 2fr 1fr 1.2fr; }
/* ─── Field: label + control + meta ─── */
.field { display: flex; flex-direction: column; }
.field__label-row {
display: flex;
justify-content: space-between;
align-items: baseline;
margin-bottom: 10px;
}
.field__label {
font-family: var(--font-display);
font-size: 11px;
letter-spacing: 0.16em;
text-transform: uppercase;
color: var(--chrome-warm);
font-weight: 500;
}
.field__required {
color: var(--ember);
font-size: 0.7em;
margin-left: 4px;
vertical-align: super;
}
.field__optional {
font-family: var(--font-display);
font-size: 10px;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--text-dim);
font-weight: 500;
}
.field__counter {
font-family: var(--font-display);
font-size: 11px;
letter-spacing: 0.08em;
color: var(--text-dim);
font-variant-numeric: tabular-nums;
}
.field__help {
font-family: var(--font-body);
font-size: 13px;
color: var(--text-dim);
margin-top: 8px;
line-height: 1.45;
}
.field__error {
font-family: var(--font-body);
font-size: 13px;
color: var(--forge-red);
margin-top: 8px;
display: flex;
align-items: center;
gap: 6px;
}
.field__success {
font-family: var(--font-body);
font-size: 13px;
color: var(--ember);
margin-top: 8px;
display: flex;
align-items: center;
gap: 6px;
}
/* ─── Text input ─── */
.input {
display: block;
width: 100%;
background: var(--bg-input);
border: none;
border-bottom: 1px solid var(--hull-edge);
padding: 14px 16px;
font-family: var(--font-body);
font-size: 16px;
color: var(--chrome-warm);
outline: none;
transition: border-color 120ms, box-shadow 160ms;
border-radius: 0;
}
.input::placeholder { color: var(--text-dim); font-style: normal; }
.input:focus {
border: 1px solid var(--ember);
box-shadow: var(--input-focus-glow);
}
.input--filled { color: var(--chrome-warm); }
.input--error {
border: 1px solid var(--forge-red);
box-shadow: var(--input-error-glow);
}
.input--disabled,
.input:disabled {
color: var(--text-dim);
background: repeating-linear-gradient(45deg, var(--hull-panel-dark) 0 6px, var(--hull-panel) 6px 12px);
cursor: not-allowed;
}
.input--success { border-bottom-color: var(--ember); }
/* ─── Textarea ─── */
.textarea {
display: block;
width: 100%;
background: var(--bg-input);
border: none;
border-bottom: 1px solid var(--hull-edge);
padding: 14px 16px;
font-family: var(--font-body);
font-size: 16px;
color: var(--chrome-warm);
outline: none;
resize: vertical;
border-radius: 0;
line-height: 1.5;
transition: border-color 120ms, box-shadow 160ms;
}
.textarea:focus {
border: 1px solid var(--ember);
box-shadow: var(--input-focus-glow);
}
/* ─── Select (native + custom-styled) ─── */
.select-wrap { position: relative; }
.select {
display: block;
width: 100%;
background: var(--bg-input);
border: none;
border-bottom: 1px solid var(--hull-edge);
padding: 14px 44px 14px 16px;
font-family: var(--font-body);
font-size: 16px;
color: var(--chrome-warm);
outline: none;
appearance: none;
-webkit-appearance: none;
border-radius: 0;
transition: border-color 120ms, box-shadow 160ms;
}
.select:focus {
border: 1px solid var(--ember);
box-shadow: var(--input-focus-glow);
}
.select-wrap::after {
content: "";
position: absolute;
right: 18px;
top: 50%;
width: 8px;
height: 8px;
border-right: 1px solid var(--chrome-warm);
border-bottom: 1px solid var(--chrome-warm);
transform: translateY(-70%) rotate(45deg);
pointer-events: none;
}
/* ─── Country picker (open state — dropdown shown) ─── */
.country-picker { position: relative; }
.country-picker__trigger {
display: flex;
align-items: center;
gap: 12px;
width: 100%;
background: var(--bg-input);
border: 1px solid var(--ember);
box-shadow: var(--input-focus-glow);
padding: 12px 16px;
color: var(--chrome-warm);
font-family: var(--font-body);
font-size: 16px;
cursor: pointer;
border-radius: 0;
}
.country-picker__flag { font-size: 20px; line-height: 1; }
.country-picker__value { flex: 1; text-align: left; }
.country-picker__caret {
width: 8px; height: 8px;
border-right: 1px solid var(--chrome-warm);
border-bottom: 1px solid var(--chrome-warm);
transform: rotate(-135deg);
}
.country-picker__panel {
position: absolute;
top: calc(100% + 4px);
left: 0;
right: 0;
background: var(--hull-panel-dark);
box-shadow: 0 12px 32px -8px rgba(0,0,0,0.95), 0 0 16px rgba(255,122,46,0.15);
z-index: 10;
padding: 8px 0;
max-height: 320px;
overflow: hidden;
display: flex;
flex-direction: column;
}
.country-picker__search {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 16px 12px;
border-bottom: 1px solid rgba(250,250,250,0.06);
}
.country-picker__search input {
flex: 1;
background: transparent;
border: none;
color: var(--chrome-warm);
font-family: var(--font-body);
font-size: 14px;
outline: none;
}
.country-picker__search-icon {
width: 14px; height: 14px;
border: 1px solid var(--text-dim);
border-radius: 50%;
position: relative;
}
.country-picker__search-icon::after {
content: "";
position: absolute;
right: -5px; bottom: -5px;
width: 6px;
height: 1px;
background: var(--text-dim);
transform: rotate(45deg);
transform-origin: left center;
}
.country-picker__options { flex: 1; overflow-y: auto; }
.country-picker__option {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 16px;
font-family: var(--font-body);
font-size: 14px;
color: var(--chrome-warm);
cursor: pointer;
}
.country-picker__option:hover,
.country-picker__option--hover {
background: var(--hull-panel-lift);
color: var(--chrome-highlight);
box-shadow: inset 3px 0 0 var(--ember);
}
/* ─── Checkbox ─── */
.checkbox {
display: flex;
align-items: flex-start;
gap: 12px;
cursor: pointer;
font-family: var(--font-body);
font-size: 14px;
color: var(--chrome-warm);
line-height: 1.5;
padding: 4px 0;
}
.checkbox__box {
width: 18px;
height: 18px;
background: var(--bg-input);
border: 1px solid var(--hull-edge);
flex: 0 0 18px;
position: relative;
margin-top: 2px;
transition: border-color 120ms, box-shadow 160ms;
}
.checkbox--checked .checkbox__box {
background: var(--bg-input);
border-color: var(--ember);
}
.checkbox--checked .checkbox__box::after {
content: "";
position: absolute;
left: 5px; top: 1px;
width: 5px; height: 10px;
border-right: 2px solid var(--ember);
border-bottom: 2px solid var(--ember);
transform: rotate(45deg);
}
.checkbox--focus .checkbox__box {
border-color: var(--ember);
box-shadow: 0 0 0 3px rgba(255,122,46,0.20);
}
.checkbox--indeterminate .checkbox__box::after {
content: "";
position: absolute;
left: 3px; top: 7px;
width: 10px; height: 2px;
background: var(--ember);
border: none;
transform: none;
}
.checkbox--disabled { opacity: 0.45; cursor: not-allowed; }
.checkbox--disabled .checkbox__box {
background: repeating-linear-gradient(45deg, var(--hull-panel-dark) 0 4px, var(--hull-panel) 4px 8px);
}
/* ─── Radio ─── */
.radio {
display: flex;
align-items: center;
gap: 12px;
cursor: pointer;
font-family: var(--font-body);
font-size: 14px;
color: var(--chrome-warm);
padding: 4px 0;
}
.radio__dot {
width: 18px;
height: 18px;
background: var(--bg-input);
border: 1px solid var(--hull-edge);
border-radius: 50%;
flex: 0 0 18px;
position: relative;
transition: border-color 120ms, box-shadow 160ms;
}
.radio--checked .radio__dot { border-color: var(--ember); }
.radio--checked .radio__dot::after {
content: "";
position: absolute;
left: 4px; top: 4px;
width: 8px; height: 8px;
border-radius: 50%;
background: var(--ember);
box-shadow: 0 0 6px rgba(255,122,46,0.55);
}
.radio--focus .radio__dot { box-shadow: 0 0 0 3px rgba(255,122,46,0.20); }
.radio-group__legend {
font-family: var(--font-display);
font-size: 11px;
letter-spacing: 0.16em;
text-transform: uppercase;
color: var(--chrome-warm);
font-weight: 500;
margin-bottom: 14px;
}
.radio-group__options { display: flex; flex-direction: column; gap: 6px; }
.radio-group__options--inline { flex-direction: row; gap: 32px; }
/* ─── Buttons ─── */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
font-family: var(--font-display);
font-size: 13px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.10em;
padding: 16px 32px;
border: none;
border-radius: 0;
cursor: pointer;
transition: box-shadow 200ms, filter 200ms;
text-decoration: none;
}
.btn--primary {
background: linear-gradient(180deg, var(--ember-glow) 0%, var(--ember) 50%, var(--ember-deep) 100%);
color: var(--on-primary-fixed);
box-shadow: var(--ember-glow-sm);
letter-spacing: 0.10em;
}
.btn--primary:hover {
box-shadow: var(--ember-glow-md);
filter: brightness(1.06);
}
.btn--primary.btn--loading {
background: linear-gradient(180deg, var(--ember-forge) 0%, var(--ember-deep) 100%);
}
.btn--primary.btn--disabled,
.btn--primary:disabled {
background: var(--hull-panel-lift);
color: var(--text-dim);
box-shadow: none;
cursor: not-allowed;
filter: none;
}
.btn--secondary {
background: transparent;
color: var(--chrome-warm);
padding: 16px 4px;
box-shadow: inset 0 -1px 0 var(--ember);
}
.btn--secondary:hover {
color: var(--ember-glow);
box-shadow: inset 0 -1px 0 var(--ember-glow), 0 4px 12px -6px rgba(255,122,46,0.4);
}
.btn__spinner {
width: 14px;
height: 14px;
border: 2px solid rgba(42,8,0,0.30);
border-top-color: var(--on-primary-fixed);
border-radius: 50%;
animation: spin 900ms linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
/* ─── Submit row ─── */
.submit-row {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 12px;
padding-top: 24px;
border-top: 1px solid rgba(250,250,250,0.04);
}
.submit-row--right { justify-content: flex-end; gap: 24px; }
/* ─── Password input with show/hide + strength meter ─── */
.password-wrap { position: relative; }
.password-wrap .input { padding-right: 56px; }
.password-toggle {
position: absolute;
right: 12px;
top: 50%;
transform: translateY(-50%);
background: transparent;
border: none;
color: var(--text-dim);
font-family: var(--font-display);
font-size: 10px;
letter-spacing: 0.14em;
text-transform: uppercase;
cursor: pointer;
padding: 6px 8px;
}
.password-toggle:hover { color: var(--ember); }
.strength-meter { margin-top: 10px; }
.strength-meter__bars {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 4px;
margin-bottom: 6px;
}
.strength-meter__bar {
height: 3px;
background: var(--hull-panel-dark);
}
.strength-meter__bar--filled {
background: var(--ember);
box-shadow: 0 0 6px rgba(255,122,46,0.5);
}
.strength-meter__label {
font-family: var(--font-display);
font-size: 10px;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--text-dim);
}
.strength-meter__label strong { color: var(--ember); font-weight: 500; margin-left: 6px; }
/* ─── Ship-to-different toggle band ─── */
.toggle-band {
background: var(--hull-panel-dark);
padding: 18px 24px;
margin-bottom: 24px;
box-shadow: inset 0 1px 0 rgba(250,250,250,0.05);
}
.toggle-band--collapsed .checkbox { margin: 0; }
/* ─── Quantity stepper ─── */
.stepper {
display: inline-flex;
align-items: stretch;
background: var(--bg-input);
box-shadow: inset 0 1px 0 rgba(250,250,250,0.06);
}
.stepper__btn {
width: 44px;
height: 48px;
background: transparent;
border: none;
color: var(--chrome-warm);
font-family: var(--font-display);
font-size: 18px;
font-weight: 500;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
border-radius: 0;
border-right: 1px solid var(--hull-panel-dark);
}
.stepper__btn:last-child { border-right: none; border-left: 1px solid var(--hull-panel-dark); }
.stepper__btn:hover:not(.stepper__btn--disabled) { color: var(--ember); background: rgba(255,122,46,0.06); }
.stepper__btn--disabled { color: var(--hull-chrome-shadow); cursor: not-allowed; }
.stepper__value {
width: 56px;
text-align: center;
background: transparent;
border: none;
color: var(--chrome-highlight);
font-family: var(--font-display);
font-size: 16px;
font-weight: 500;
font-variant-numeric: tabular-nums;
outline: none;
}
.stepper--focus { box-shadow: inset 0 1px 0 rgba(250,250,250,0.06), 0 0 0 1px var(--ember), var(--input-focus-glow); }
/* ─── STATES APPENDIX ─── */
.appendix { padding-top: 24px; }
.appendix__eyebrow {
font-family: var(--font-display);
font-size: 11px;
letter-spacing: 0.16em;
text-transform: uppercase;
color: var(--ember);
font-weight: 500;
margin-bottom: 10px;
}
.appendix__title {
font-family: var(--font-display);
font-size: 36px;
line-height: 1.1;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.8px;
color: var(--text-heading);
margin-bottom: 8px;
}
.appendix__caption {
font-family: var(--font-body);
font-size: 14px;
color: var(--text-dim);
max-width: 640px;
margin-bottom: 40px;
}
.state-row {
background: var(--bg-panel);
padding: 32px 40px 36px;
margin-bottom: 20px;
border: 1px solid var(--hull-edge);
box-shadow: var(--panel-lift);
}
.state-row__header {
display: flex;
justify-content: space-between;
align-items: baseline;
margin-bottom: 24px;
padding-bottom: 12px;
border-bottom: 1px solid rgba(250,250,250,0.06);
}
.state-row__title {
font-family: var(--font-display);
font-size: 16px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.8px;
color: var(--chrome-highlight);
}
.state-row__meta {
font-family: var(--font-display);
font-size: 10px;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--text-dim);
}
.state-grid {
display: grid;
gap: 32px 24px;
}
.state-grid--6 { grid-template-columns: repeat(6, 1fr); }
.state-grid--5 { grid-template-columns: repeat(5, 1fr); }
.state-grid--4 { grid-template-columns: repeat(4, 1fr); }
.state-grid--3 { grid-template-columns: repeat(3, 1fr); }
.state-grid--2 { grid-template-columns: repeat(2, 1fr); }
.state-cell {
display: flex;
flex-direction: column;
gap: 10px;
}
.state-cell__demo {
min-height: 76px;
display: flex;
align-items: flex-start;
flex-direction: column;
justify-content: flex-start;
}
.state-cell__demo--center {
align-items: flex-start;
justify-content: center;
}
.state-cell__demo--inline {
flex-direction: row;
align-items: center;
gap: 12px;
}
.state-cell__label {
font-family: var(--font-display);
font-size: 10px;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--text-dim);
padding-top: 8px;
border-top: 1px solid rgba(250,250,250,0.05);
}
.state-cell__label strong { color: var(--chrome-warm); font-weight: 500; }
/* Tick / cross / warning glyphs used inline in states */
.glyph-tick {
display: inline-block;
width: 12px; height: 12px;
position: relative;
flex: 0 0 12px;
}
.glyph-tick::after {
content: "";
position: absolute;
left: 2px; top: -1px;
width: 5px; height: 10px;
border-right: 2px solid var(--ember);
border-bottom: 2px solid var(--ember);
transform: rotate(45deg);
}
.glyph-warn {
display: inline-block;
width: 14px; height: 14px;
background: var(--forge-red);
color: var(--carbon);
font-family: var(--font-display);
font-weight: 700;
font-size: 10px;
text-align: center;
line-height: 14px;
flex: 0 0 14px;
}
/* Feedback strings row */
.feedback-string {
display: flex;
flex-direction: column;
gap: 4px;
}
.feedback-string__label {
font-family: var(--font-display);
font-size: 10px;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--chrome-warm);
display: flex;
align-items: baseline;
gap: 6px;
}
.feedback-string__demo { min-height: 22px; }
/* ─── Footer ─── */
.spec-footer {
margin-top: 72px;
padding: 32px 0 48px;
border-top: 1px solid rgba(250,250,250,0.06);
display: flex;
justify-content: space-between;
align-items: baseline;
font-family: var(--font-display);
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.14em;
color: var(--text-dim);
}
.spec-footer__pair { display: flex; gap: 24px; }
.spec-footer__pair span strong { color: var(--chrome-warm); font-weight: 500; margin-left: 6px; }
/* ─── Responsive ─── */
@media (max-width: 780px) {
.layout { padding: 0 20px; }
.spec-header__title { font-size: 40px; letter-spacing: 0.8px; }
.example__title { font-size: 30px; letter-spacing: 0.8px; }
.form-panel { padding: 28px 20px 32px; }
.form-grid--2col, .form-grid--3col { grid-template-columns: 1fr; }
.state-grid--6, .state-grid--5, .state-grid--4, .state-grid--3, .state-grid--2 { grid-template-columns: 1fr 1fr; }
.submit-row { flex-direction: column; align-items: stretch; gap: 16px; }
.btn--primary, .btn--secondary { width: 100%; text-align: center; justify-content: center; }
.spec-footer { flex-direction: column; gap: 12px; }
}
/* orbitron-retrofit: title-em italic kill */
[class*="__title"] em, [class*="__title"] i,
[class*="-title"] em, [class*="-title"] i,
[class*="__heading"] em, [class*="__heading"] i,
[class*="-heading"] em, [class*="-heading"] i { font-style: normal; }
</style>
</head>
<body>
<div class="layout">
<!-- ═══ Compact reference header ═══ -->
<header class="spec-header">
<div class="spec-header__eyebrow">ARTSABERS · Form Component Spec · V1</div>
<h1 class="spec-header__title">Form Patterns</h1>
<p class="spec-header__lede">Reference specification for every form-bearing template on the ARTSABERS site — checkout, contact, my-account, product configurator. Three worked examples show the components in real composition; the appendix at the bottom covers the states the examples don't naturally reach.</p>
<div class="spec-header__meta">
<span>Styleguide<strong>SAS1 · Kyber Hull</strong></span>
<span>Font stack<strong>Space Grotesk / Manrope</strong></span>
<span>Radius<strong>0px sitewide</strong></span>
<span>Focus<strong>Ember, not blue</strong></span>
</div>
</header>
<!-- ═══ WORKED EXAMPLE 1 — Checkout Billing + Shipping Address ═══ -->
<div class="seam" aria-hidden="true"></div>
<section class="example">
<div class="example__eyebrow">Worked Example 01 · Checkout</div>
<h2 class="example__title">Billing & Shipping Address</h2>
<p class="example__caption">Demonstrates: section headings, fieldset grouping, required indicator, optional label, two- and three-column splits, help text, country picker with flags + search (shown open), conditional field group, textarea.</p>
<a id="tf-form-1" data-tf-family="form" style="display:contents"></a>
<div class="form-panel">
<!-- BILLING ADDRESS -->
<fieldset class="form-fieldset">
<legend class="form-fieldset__heading">Billing Address</legend>
<!-- Two-column: first / last name -->
<div class="form-grid form-grid--2col">
<div class="field">
<div class="field__label-row">
<label class="field__label">First name<span class="field__required">*</span></label>
</div>
<input type="text" class="input input--filled" value="Rey">
</div>
<div class="field">
<div class="field__label-row">
<label class="field__label">Last name<span class="field__required">*</span></label>
</div>
<input type="text" class="input input--filled" value="Skywalker">
</div>
</div>
<!-- Email -->
<div class="form-grid">
<div class="field">
<div class="field__label-row">
<label class="field__label">Email address<span class="field__required">*</span></label>
</div>
<input type="email" class="input input--filled" value="rey@jakku.rim">
<p class="field__help">For order updates + delivery ETAs.</p>
</div>
</div>
<!-- Phone -->
<div class="form-grid">
<div class="field">
<div class="field__label-row">
<label class="field__label">Phone<span class="field__required">*</span></label>
</div>
<input type="tel" class="input" placeholder="+1 555 000 0000">
<p class="field__help">The courier will use this for delivery ETAs and access.</p>
</div>
</div>
<!-- Country picker — OPEN state so pattern reads -->
<div class="form-grid">
<div class="field">
<div class="field__label-row">
<label class="field__label">Country / Region<span class="field__required">*</span></label>
</div>
<div class="country-picker">
<button type="button" class="country-picker__trigger">
<span class="country-picker__flag" aria-hidden="true">🇺🇸</span>
<span class="country-picker__value">United States</span>
<span class="country-picker__caret" aria-hidden="true"></span>
</button>
<div class="country-picker__panel">
<div class="country-picker__search">
<span class="country-picker__search-icon" aria-hidden="true"></span>
<input type="text" placeholder="Search countries…" value="un">
</div>
<div class="country-picker__options">
<div class="country-picker__option"><span class="country-picker__flag">🇺🇸</span> United States</div>
<div class="country-picker__option"><span class="country-picker__flag">🇬🇧</span> United Kingdom</div>
<div class="country-picker__option country-picker__option--hover"><span class="country-picker__flag">🇦🇪</span> United Arab Emirates</div>
<div class="country-picker__option"><span class="country-picker__flag">🇦🇺</span> Australia</div>
<div class="country-picker__option"><span class="country-picker__flag">🇨🇦</span> Canada</div>
</div>
</div>
</div>
</div>
</div>
<!-- Address 1 -->
<div class="form-grid" style="margin-top: 88px;">
<div class="field">
<div class="field__label-row">
<label class="field__label">Address line 1<span class="field__required">*</span></label>
</div>
<input type="text" class="input input--filled" value="1138 Mos Espa Boulevard">
</div>
</div>
<!-- Address 2 -->
<div class="form-grid">
<div class="field">
<div class="field__label-row">
<label class="field__label">Address line 2</label>
<span class="field__optional">Optional</span>
</div>
<input type="text" class="input" placeholder="Apartment, suite, floor…">
</div>
</div>
<!-- Three column: city / postcode / state -->
<div class="form-grid form-grid--3col">
<div class="field">
<div class="field__label-row">
<label class="field__label">Town / City<span class="field__required">*</span></label>
</div>
<input type="text" class="input input--filled" value="Anchorhead">
</div>
<div class="field">
<div class="field__label-row">
<label class="field__label">Postcode<span class="field__required">*</span></label>
</div>
<input type="text" class="input input--filled" value="94103">
</div>
<div class="field">
<div class="field__label-row">
<label class="field__label">State<span class="field__required">*</span></label>
</div>
<div class="select-wrap">
<select class="select">
<option>California</option>
<option>Colorado</option>
<option>Connecticut</option>
</select>
</div>
<p class="field__help">Auto-swaps to State picker for US / CA / AU; hides for regions without one.</p>
</div>
</div>
<!-- Textarea order notes -->
<div class="form-grid">
<div class="field">
<div class="field__label-row">
<label class="field__label">Order notes</label>
<span class="field__optional">Optional</span>
</div>
<textarea class="textarea" rows="4" placeholder="Delivery instructions, buzzer code, etc."></textarea>
<p class="field__help">Delivery instructions, buzzer code, etc.</p>
</div>
</div>
</fieldset>
<!-- SHIPPING ADDRESS -->
<fieldset class="form-fieldset">
<legend class="form-fieldset__heading">Shipping Address</legend>
<div class="toggle-band">
<label class="checkbox checkbox--checked">
<span class="checkbox__box"></span>
<span>Ship to a different address</span>
</label>
</div>
<!-- Mirror address group — expanded because checkbox is checked -->
<div class="form-grid form-grid--2col">
<div class="field">
<div class="field__label-row">
<label class="field__label">First name<span class="field__required">*</span></label>
</div>
<input type="text" class="input" placeholder="Recipient first name">
</div>
<div class="field">
<div class="field__label-row">
<label class="field__label">Last name<span class="field__required">*</span></label>
</div>
<input type="text" class="input" placeholder="Recipient last name">
</div>
</div>
<div class="form-grid">
<div class="field">
<div class="field__label-row">
<label class="field__label">Address line 1<span class="field__required">*</span></label>
</div>
<input type="text" class="input" placeholder="Street address">
</div>
</div>
<div class="form-grid form-grid--3col">
<div class="field">
<div class="field__label-row">
<label class="field__label">Town / City<span class="field__required">*</span></label>
</div>
<input type="text" class="input">
</div>
<div class="field">
<div class="field__label-row">
<label class="field__label">Postcode<span class="field__required">*</span></label>
</div>
<input type="text" class="input">
</div>
<div class="field">
<div class="field__label-row">
<label class="field__label">State<span class="field__required">*</span></label>
</div>
<div class="select-wrap">
<select class="select">
<option>California</option>
</select>
</div>
</div>
</div>
</fieldset>
</div>
</section>
<!-- ═══ WORKED EXAMPLE 2 — Contact Form ═══ -->
<div class="seam" aria-hidden="true"></div>
<section class="example">
<div class="example__eyebrow">Worked Example 02 · Contact</div>
<h2 class="example__title">Get in Touch</h2>
<p class="example__caption">Demonstrates: select dropdown (closed state), character counter, checkbox (default unchecked), primary + secondary action pair. Compact form pattern suitable for the future Contact page.</p>
<a id="tf-form-2" data-tf-family="form" style="display:contents"></a>
<div class="form-panel">
<form>
<div class="form-grid form-grid--2col">
<div class="field">
<div class="field__label-row">
<label class="field__label">First name<span class="field__required">*</span></label>
</div>
<input type="text" class="input" placeholder="Your first name">
</div>
<div class="field">
<div class="field__label-row">
<label class="field__label">Last name<span class="field__required">*</span></label>
</div>
<input type="text" class="input" placeholder="Your last name">
</div>
</div>
<div class="form-grid">
<div class="field">
<div class="field__label-row">
<label class="field__label">Email<span class="field__required">*</span></label>
</div>
<input type="email" class="input" placeholder="you@yourdomain.com">
</div>
</div>
<div class="form-grid">
<div class="field">
<div class="field__label-row">
<label class="field__label">Subject<span class="field__required">*</span></label>
<span class="field__counter">42 / 100</span>
</div>
<input type="text" class="input input--filled" value="Xenopixel V3 sound-font support question">
</div>
</div>
<div class="form-grid">
<div class="field">
<div class="field__label-row">
<label class="field__label">How can we help?<span class="field__required">*</span></label>
</div>
<div class="select-wrap">
<select class="select">
<option>Choose an option…</option>
<option>Order support</option>
<option>Product question</option>
<option>Wholesale enquiry</option>
<option>Warranty claim</option>
<option>Other</option>
</select>
</div>
</div>
</div>
<div class="form-grid">
<div class="field">
<div class="field__label-row">
<label class="field__label">Message<span class="field__required">*</span></label>
<span class="field__counter">318 / 2000</span>
</div>
<textarea class="textarea" rows="6" placeholder="Tell us what's going on. If it's an order question, please include the order number so we can pull it up on our end.">Hi — I just picked up a Starkiller SE with the Xenopixel V3 core and I'm looking for the process to swap out the default sound font pack. The XenoConfigurator app is paired fine but I don't see the option in the fonts screen. Any pointers gratefully received.</textarea>
</div>
</div>
<div class="form-grid">
<label class="checkbox">
<span class="checkbox__box"></span>
<span>Subscribe to occasional updates about new hilts and offers.</span>
</label>
</div>
<div class="submit-row">
<a href="#" class="btn btn--secondary">Reset form</a>
<button type="submit" class="btn btn--primary">Send Message</button>
</div>
</form>
</div>
</section>
<!-- ═══ WORKED EXAMPLE 3 — My Account Edit Profile ═══ -->
<div class="seam" aria-hidden="true"></div>
<section class="example">
<div class="example__eyebrow">Worked Example 03 · My Account</div>
<h2 class="example__title">Edit Profile</h2>
<p class="example__caption">Demonstrates: filled state, section divider, password input with show/hide toggle + strength meter, vertical checkbox group, radio group (with selected), primary + secondary action, disabled-until-dirty submit (shown in states appendix).</p>
<a id="tf-form-3" data-tf-family="form" style="display:contents"></a>
<div class="form-panel">
<form>
<!-- ACCOUNT DETAILS -->
<fieldset class="form-fieldset">
<legend class="form-fieldset__heading">Account Details</legend>
<div class="form-grid form-grid--2col">
<div class="field">
<div class="field__label-row">
<label class="field__label">First name<span class="field__required">*</span></label>
</div>
<input type="text" class="input input--filled" value="Kanan">
</div>
<div class="field">
<div class="field__label-row">
<label class="field__label">Last name<span class="field__required">*</span></label>
</div>
<input type="text" class="input input--filled" value="Jarrus">
</div>
</div>
<div class="form-grid">
<div class="field">
<div class="field__label-row">
<label class="field__label">Display name<span class="field__required">*</span></label>
</div>
<input type="text" class="input input--filled" value="KJarrus">
<p class="field__help">How your name appears on reviews you leave.</p>
</div>
</div>
<div class="form-grid">
<div class="field">
<div class="field__label-row">
<label class="field__label">Email<span class="field__required">*</span></label>
</div>
<input type="email" class="input input--filled" value="kanan.j@spectre-two.rim">
<p class="field__help">Used for order updates + account login.</p>
</div>
</div>
</fieldset>
<div class="form-divider" aria-hidden="true"></div>
<!-- CHANGE PASSWORD -->
<fieldset class="form-fieldset">
<legend class="form-fieldset__heading">Change Password</legend>
<div class="form-grid">
<div class="field">
<div class="field__label-row">
<label class="field__label">Current password<span class="field__required">*</span></label>
</div>
<div class="password-wrap">
<input type="password" class="input" value="oldpassword">
<button type="button" class="password-toggle">Show</button>
</div>
</div>
</div>
<div class="form-grid">
<div class="field">
<div class="field__label-row">
<label class="field__label">New password<span class="field__required">*</span></label>
</div>
<div class="password-wrap">
<input type="text" class="input input--filled" value="Kyber-Crystal-42!">
<button type="button" class="password-toggle">Hide</button>
</div>
<div class="strength-meter">
<div class="strength-meter__bars">
<div class="strength-meter__bar strength-meter__bar--filled"></div>
<div class="strength-meter__bar strength-meter__bar--filled"></div>
<div class="strength-meter__bar strength-meter__bar--filled"></div>
<div class="strength-meter__bar"></div>
</div>
<div class="strength-meter__label">Strength<strong>Strong</strong></div>
</div>
</div>
</div>
<div class="form-grid">
<div class="field">
<div class="field__label-row">
<label class="field__label">Confirm new password<span class="field__required">*</span></label>
</div>
<div class="password-wrap">
<input type="password" class="input" value="Kyber-Crystal-42!">
<button type="button" class="password-toggle">Show</button>
</div>
</div>
</div>
</fieldset>
<div class="form-divider" aria-hidden="true"></div>
<!-- PREFERENCES -->
<fieldset class="form-fieldset">
<legend class="form-fieldset__heading">Preferences</legend>
<div class="form-grid">
<div class="field">
<div class="field__label-row">
<label class="field__label">Email Preferences</label>
</div>
<div style="display: flex; flex-direction: column; gap: 10px; margin-top: 4px;">
<label class="checkbox checkbox--checked">
<span class="checkbox__box"></span>
<span>Product launch emails</span>
</label>
<label class="checkbox checkbox--checked">
<span class="checkbox__box"></span>
<span>Restock alerts for wishlisted items</span>
</label>
<label class="checkbox">
<span class="checkbox__box"></span>
<span>Occasional community + duelling event updates</span>
</label>
</div>
</div>
</div>
<div class="form-grid" style="margin-top: 12px;">
<div class="field">
<fieldset style="border: none; padding: 0;">
<legend class="radio-group__legend">Newsletter frequency</legend>
<div class="radio-group__options radio-group__options--inline">
<label class="radio">
<span class="radio__dot"></span>
<span>Weekly</span>
</label>
<label class="radio radio--checked">
<span class="radio__dot"></span>
<span>Monthly</span>
</label>
<label class="radio">
<span class="radio__dot"></span>
<span>Only for major drops</span>
</label>
</div>
</fieldset>
</div>
</div>
</fieldset>
<div class="submit-row">
<a href="#" class="btn btn--secondary">Cancel</a>
<button type="submit" class="btn btn--primary">Save Changes</button>
</div>
</form>
</div>
</section>
<!-- ═══ STATES APPENDIX ═══ -->
<div class="seam" aria-hidden="true"></div>
<section class="appendix">
<div class="appendix__eyebrow">States Appendix</div>
<h2 class="appendix__title">Component States Reference</h2>
<p class="appendix__caption">Every state the three worked examples don't naturally reach — one row per component group, side-by-side variants labelled beneath. Downstream templates match these verbatim.</p>
<!-- TEXT INPUT STATES -->
<div class="state-row">
<div class="state-row__header">
<div class="state-row__title">Text Input · states</div>
<div class="state-row__meta">6 variants</div>
</div>
<div class="state-grid state-grid--6">
<div class="state-cell">
<div class="state-cell__demo">
<div class="field__label-row" style="margin-bottom: 8px;">
<label class="field__label">Email</label>
</div>
<input type="text" class="input" placeholder="you@domain.com">
</div>
<div class="state-cell__label"><strong>Default</strong> — empty, label above</div>
</div>
<div class="state-cell">
<div class="state-cell__demo">
<div class="field__label-row" style="margin-bottom: 8px;">
<label class="field__label">Email</label>
</div>
<input type="text" class="input" style="border: 1px solid var(--ember); box-shadow: var(--input-focus-glow);" value="rey@jak">
</div>
<div class="state-cell__label"><strong>Focus</strong> — ember hairline + glow</div>
</div>
<div class="state-cell">
<div class="state-cell__demo">
<div class="field__label-row" style="margin-bottom: 8px;">
<label class="field__label">Email</label>
</div>
<input type="text" class="input input--filled" value="rey@jakku.rim">
</div>
<div class="state-cell__label"><strong>Filled</strong> — has value, no focus</div>
</div>
<div class="state-cell">
<div class="state-cell__demo">
<div class="field__label-row" style="margin-bottom: 8px;">
<label class="field__label">Email</label>
</div>
<input type="text" class="input input--error" value="rey@jakku">
<p class="field__error"><span class="glyph-warn">!</span>Please enter a valid email address.</p>
</div>
<div class="state-cell__label"><strong>Error</strong> — forge-red + inline message</div>
</div>
<div class="state-cell">
<div class="state-cell__demo">
<div class="field__label-row" style="margin-bottom: 8px;">
<label class="field__label">Email</label>
</div>
<input type="text" class="input input--disabled" value="locked@field.rim" disabled>
</div>
<div class="state-cell__label"><strong>Disabled</strong> — hatched, muted</div>
</div>
<div class="state-cell">
<div class="state-cell__demo">
<div class="field__label-row" style="margin-bottom: 8px;">
<label class="field__label">Email</label>
</div>
<div style="position: relative;">
<input type="text" class="input input--filled input--success" value="rey@jakku.rim" style="padding-right: 40px;">
<span class="glyph-tick" style="position: absolute; right: 14px; top: 50%; transform: translateY(-50%);"></span>
</div>
</div>
<div class="state-cell__label"><strong>Success</strong> — ember tick to the right</div>
</div>
</div>
</div>
<!-- SELECT STATES -->
<div class="state-row">
<div class="state-row__header">
<div class="state-row__title">Select · states</div>
<div class="state-row__meta">4 variants</div>
</div>
<div class="state-grid state-grid--4">
<div class="state-cell">
<div class="state-cell__demo">
<div class="field__label-row" style="margin-bottom: 8px;">
<label class="field__label">Saber Core</label>
</div>
<div class="select-wrap">
<select class="select" style="color: var(--text-dim);">
<option>Choose a Core…</option>
</select>
</div>
</div>
<div class="state-cell__label"><strong>Default</strong> — closed, placeholder</div>
</div>
<div class="state-cell">
<div class="state-cell__demo">
<div class="field__label-row" style="margin-bottom: 8px;">
<label class="field__label">Saber Core</label>
</div>
<div class="country-picker">
<button type="button" class="country-picker__trigger" style="padding: 10px 16px;">
<span class="country-picker__value">Choose a Core…</span>
<span class="country-picker__caret" style="transform: rotate(-135deg);"></span>
</button>
<div class="country-picker__panel" style="position: static; margin-top: 4px; max-height: none;">
<div class="country-picker__options" style="overflow: visible;">
<div class="country-picker__option">S-RGB</div>
<div class="country-picker__option">RGB-X</div>
<div class="country-picker__option country-picker__option--hover">SNV4 PRO</div>
<div class="country-picker__option">Xenopixel V3</div>
<div class="country-picker__option">Proffie 2.2</div>
</div>
</div>
</div>
</div>
<div class="state-cell__label"><strong>Open</strong> — dropdown, hover on option 3</div>
</div>
<div class="state-cell">
<div class="state-cell__demo">
<div class="field__label-row" style="margin-bottom: 8px;">
<label class="field__label">Saber Core</label>
</div>
<div class="select-wrap">
<select class="select">
<option>Xenopixel V3</option>
</select>
</div>
</div>
<div class="state-cell__label"><strong>Selected</strong> — has a value</div>
</div>
<div class="state-cell">
<div class="state-cell__demo">
<div class="field__label-row" style="margin-bottom: 8px;">
<label class="field__label">Saber Core</label>
</div>
<div class="select-wrap">
<select class="select" style="border: 1px solid var(--forge-red); box-shadow: var(--input-error-glow); color: var(--text-dim);">
<option>Choose a Core…</option>
</select>
</div>
<p class="field__error"><span class="glyph-warn">!</span>Please choose a Saber Core.</p>
</div>
<div class="state-cell__label"><strong>Error</strong> — forge-red hairline</div>
</div>
</div>
</div>
<!-- CHECKBOX / RADIO STATES -->
<div class="state-row">
<div class="state-row__header">
<div class="state-row__title">Checkbox & Radio · states</div>
<div class="state-row__meta">5 variants</div>
</div>
<div class="state-grid state-grid--5">
<div class="state-cell">
<div class="state-cell__demo state-cell__demo--center">
<label class="checkbox"><span class="checkbox__box"></span><span>Checkbox</span></label>
<label class="radio" style="margin-top: 12px;"><span class="radio__dot"></span><span>Radio</span></label>
</div>
<div class="state-cell__label"><strong>Default</strong> — unchecked</div>
</div>
<div class="state-cell">
<div class="state-cell__demo state-cell__demo--center">
<label class="checkbox checkbox--checked"><span class="checkbox__box"></span><span>Checkbox</span></label>
<label class="radio radio--checked" style="margin-top: 12px;"><span class="radio__dot"></span><span>Radio</span></label>
</div>
<div class="state-cell__label"><strong>Checked</strong> — ember tick / dot</div>
</div>
<div class="state-cell">
<div class="state-cell__demo state-cell__demo--center">
<label class="checkbox checkbox--focus"><span class="checkbox__box"></span><span>Checkbox</span></label>
<label class="radio radio--focus" style="margin-top: 12px;"><span class="radio__dot"></span><span>Radio</span></label>
</div>
<div class="state-cell__label"><strong>Focus</strong> — ember ring at 20%</div>
</div>
<div class="state-cell">
<div class="state-cell__demo state-cell__demo--center">
<label class="checkbox checkbox--disabled"><span class="checkbox__box"></span><span>Checkbox</span></label>
<label class="radio" style="margin-top: 12px; opacity: 0.45; cursor: not-allowed;"><span class="radio__dot"></span><span>Radio</span></label>
</div>
<div class="state-cell__label"><strong>Disabled</strong> — hatched, muted</div>
</div>
<div class="state-cell">
<div class="state-cell__demo state-cell__demo--center">
<label class="checkbox checkbox--indeterminate"><span class="checkbox__box"></span><span>Parent (some)</span></label>
<div style="font-family: var(--font-display); font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-dim); margin-top: 20px;">Checkbox only</div>
</div>
<div class="state-cell__label"><strong>Indeterminate</strong> — parent-of-group</div>
</div>
</div>
</div>
<!-- BUTTON STATES -->
<div class="state-row">
<div class="state-row__header">
<div class="state-row__title">Button · states</div>
<div class="state-row__meta">6 variants</div>
</div>
<div class="state-grid state-grid--3">
<div class="state-cell">
<div class="state-cell__demo state-cell__demo--center"><button class="btn btn--primary">Add to Cart</button></div>
<div class="state-cell__label"><strong>Primary default</strong> — ember ombre gradient</div>
</div>
<div class="state-cell">
<div class="state-cell__demo state-cell__demo--center"><button class="btn btn--primary" style="box-shadow: var(--ember-glow-md); filter: brightness(1.06);">Add to Cart</button></div>
<div class="state-cell__label"><strong>Primary hover</strong> — brighter + intensified glow</div>
</div>
<div class="state-cell">
<div class="state-cell__demo state-cell__demo--center"><button class="btn btn--primary btn--loading"><span class="btn__spinner"></span>Sending…</button></div>
<div class="state-cell__label"><strong>Primary loading</strong> — spinner + Sending…</div>
</div>
<div class="state-cell">
<div class="state-cell__demo state-cell__demo--center"><button class="btn btn--primary btn--disabled" disabled>Save Changes</button></div>
<div class="state-cell__label"><strong>Primary disabled</strong> — muted, no glow (until dirty)</div>
</div>
<div class="state-cell">
<div class="state-cell__demo state-cell__demo--center"><a href="#" class="btn btn--secondary">Reset form</a></div>
<div class="state-cell__label"><strong>Secondary default</strong> — ember hairline underline</div>
</div>
<div class="state-cell">
<div class="state-cell__demo state-cell__demo--center"><a href="#" class="btn btn--secondary" style="color: var(--ember-glow); box-shadow: inset 0 -1px 0 var(--ember-glow), 0 4px 12px -6px rgba(255,122,46,0.4);">Reset form</a></div>
<div class="state-cell__label"><strong>Secondary hover</strong> — brighter ember underline glow</div>
</div>
</div>
</div>
<!-- QUANTITY STEPPER -->
<div class="state-row">
<div class="state-row__header">
<div class="state-row__title">Quantity Stepper · states</div>
<div class="state-row__meta">4 variants</div>
</div>
<div class="state-grid state-grid--4">
<div class="state-cell">
<div class="state-cell__demo state-cell__demo--center">
<div class="stepper">
<button class="stepper__btn">−</button>
<input class="stepper__value" value="1" readonly>
<button class="stepper__btn">+</button>
</div>
</div>
<div class="state-cell__label"><strong>Default</strong> — value 1</div>
</div>
<div class="state-cell">
<div class="state-cell__demo state-cell__demo--center">
<div class="stepper stepper--focus">
<button class="stepper__btn">−</button>
<input class="stepper__value" value="3" readonly>
<button class="stepper__btn">+</button>
</div>
</div>
<div class="state-cell__label"><strong>Focus</strong> — on the value input</div>
</div>
<div class="state-cell">
<div class="state-cell__demo state-cell__demo--center">
<div class="stepper">
<button class="stepper__btn stepper__btn--disabled" disabled>−</button>
<input class="stepper__value" value="1" readonly>
<button class="stepper__btn">+</button>
</div>
</div>
<div class="state-cell__label"><strong>At minimum</strong> — minus disabled</div>
</div>
<div class="state-cell">
<div class="state-cell__demo state-cell__demo--center">
<div class="stepper">
<button class="stepper__btn">−</button>
<input class="stepper__value" value="10" readonly>
<button class="stepper__btn stepper__btn--disabled" disabled>+</button>
</div>
</div>
<div class="state-cell__label"><strong>At maximum</strong> — plus disabled</div>
</div>
</div>
</div>
<!-- FEEDBACK STRINGS -->
<div class="state-row">
<div class="state-row__header">
<div class="state-row__title">Feedback strings · states</div>
<div class="state-row__meta">6 variants</div>
</div>
<div class="state-grid state-grid--3">
<div class="state-cell">
<div class="state-cell__demo state-cell__demo--center">
<div class="feedback-string__label">Email<span class="field__required">*</span></div>
</div>
<div class="state-cell__label"><strong>Required indicator</strong> — ember asterisk after label</div>
</div>
<div class="state-cell">
<div class="state-cell__demo state-cell__demo--center">
<div class="feedback-string__label">Address line 2 <span class="field__optional">Optional</span></div>
</div>
<div class="state-cell__label"><strong>Optional indicator</strong> — muted uppercase tag</div>
</div>
<div class="state-cell">
<div class="state-cell__demo state-cell__demo--center">
<p class="field__help" style="margin-top: 0;">For order updates + delivery ETAs.</p>
</div>
<div class="state-cell__label"><strong>Help text</strong> — muted body font below input</div>
</div>
<div class="state-cell">
<div class="state-cell__demo state-cell__demo--center">
<div class="field__counter">42 / 100</div>
</div>
<div class="state-cell__label"><strong>Character counter</strong> — right-aligned muted, tabular</div>
</div>
<div class="state-cell">
<div class="state-cell__demo state-cell__demo--center">
<p class="field__error" style="margin-top: 0;"><span class="glyph-warn">!</span>Please enter a valid email address.</p>
</div>
<div class="state-cell__label"><strong>Inline error</strong> — forge-red text + warning glyph</div>
</div>
<div class="state-cell">
<div class="state-cell__demo state-cell__demo--center">
<p class="field__success" style="margin-top: 0;"><span class="glyph-tick"></span>Preferences saved.</p>
</div>
<div class="state-cell__label"><strong>Success message</strong> — ember text + tick glyph</div>
</div>
</div>
</div>
</section>
<!-- ═══ Footer ═══ -->
<footer class="spec-footer">
<div class="spec-footer__pair">
<span>Spec version<strong>V1</strong></span>
<span>Pairs with<strong>SAS1 · Kyber Hull</strong></span>
</div>
<div class="spec-footer__pair">
<span>Build brief<strong>13056</strong></span>
<span>Consumed by<strong>Checkout · Contact · My Account · Configurator</strong></span>
</div>
</footer>
</div>
</body>
</html>