المكونات
عقد كل مكون: navbar، hero، بطاقات، sidebar، أزرار، dropzone، والمزيد.
navbar
| container | <nav id="navbar"> position: sticky; top: 0; z-index: 50 |
| background | rgba(10, 10, 15, 0.95) |
| backdrop | blur(4px) |
| border-bottom | 1px solid #1a1a2e |
| height | 48px (var(--nav-height)) |
| scrolled | adds box-shadow: var(--shadow-md) |
brand.json path: /component/navbar
hero
| container | section.hero-brand with optional bg-brand-gradient-animated |
| min-height | calc(100svh - 5rem) |
| shield-flank | two decorative shield SVGs at 6% opacity, hidden below 768px |
brand.json path: /component/hero
section-badge
| recipe | uppercase pill, cyan text on rgba(0,184,212,0.12), 1px border rgba(0,184,212,0.25), padding 4-8 vertical 10-14 horizontal, radius 4-20 |
brand.json path: /component/section-badge
breadcrumb
| padding | var(--space-md) 0 |
| size | 14px |
| color | #6E6E73 |
| separator | 8px margin both sides, 0.5 opacity, user-select none |
brand.json path: /component/breadcrumb
card-feature
| background | rgba(255, 255, 255, 0.03) |
| backdrop | blur(16px) |
| border | 1px solid rgba(255, 255, 255, 0.08) |
| radius | 16px |
| padding | 40px |
| hover | translateY(-4px), surface-hover bg, cyan-tint border, shadow card-hover |
| icon-tile | 48x48 with 12px radius and --icon-bg-* tint |
brand.json path: /component/card-feature
card-pricing
| grid | .pr-plans-grid max-width 1120px, 3 columns at >=768px |
| card-base | rgba(255,255,255,0.04) bg, blur(40px) saturate(180%), 1px solid rgba(255,255,255,0.08), radius 28px, padding 40px 32px 36px |
| pro-elevated | scale(1.04), cyan-tinted bg, cyan border, outer cyan glow |
| hover | translateY(-4px); Pro keeps scale and adds lift |
brand.json path: /component/card-pricing
pricing-toggle
| wrapper | pill, padding 4px, bg rgba(255,255,255,0.05), 1px solid rgba(255,255,255,0.10) |
| active | solid teal #14b8a6, white text, shadow 0 4px 12px rgba(20,184,166,0.35) |
| inactive | transparent, text tertiary, hover white |
| save-chip | #fbbf24 (or #fde68a on active background) |
brand.json path: /component/pricing-toggle
faq
| question-button | aria-expanded, font-display 17px 600, hover cyan |
| glyph | + collapsed, - expanded; transitions on duration-fast |
| answer | max-height transition with padding-bottom |
brand.json path: /component/faq
dashboard-sidebar
| width | 260px (--sidebar-width) |
| background | linear-gradient(180deg, #121220 0%, #0f0f18 40%, #0c0c15 100%) |
| group-label | 11px 600 uppercase 0.05em tracking, color text-faint |
| nav-item-height | 40px |
| nav-item-radius | 8px |
| active-state | rgba(0,184,212,0.08) background AND a 3px LEFT BORDER in cyan #00B8D4. Hard BetterGuard rule: never bottom, never right. |
| hover | rgba(255,255,255,0.04) |
brand.json path: /component/dashboard-sidebar
plan-badge
| padding | 4px 10px |
| font | 10px 700 uppercase 0.5px tracking |
| background | linear-gradient(135deg, rgba(124,77,255,0.3) 0%, rgba(0,184,212,0.2) 100%) |
| border | 1px solid rgba(124,77,255,0.5) |
| radius | 20px |
| color | #c77dff with text-shadow 0 0 8px rgba(199,125,255,0.5) |
brand.json path: /component/plan-badge
dropzone
| default-border | 2px dashed #2a2a3e |
| background | #0f0f1a |
| hover | border #00B8D4, background rgba(0,184,212,0.05) |
| dragover | border #00B8D4, background rgba(0,184,212,0.1) |
brand.json path: /component/dropzone
btn-primary
| padding | 12px 24px |
| background | linear-gradient(135deg, #00B8D4, #9D7EFF) |
| color | #FFFFFF |
| font | Sora 17px 600 |
| radius | 8px |
| transition | transform, box-shadow on 200ms ease-out |
| hover | translateY(-2px), glow-brand |
| focus-visible | 2px solid #00B8D4 outline, 2px offset, 8px radius |
brand.json path: /component/btn-primary
btn-secondary
| background | transparent |
| color | #00E5FF |
| border | 2px solid #00E5FF |
| radius | 8px |
| hover | rgba(255,255,255,0.1) background, white text |
brand.json path: /component/btn-secondary
cta-link
| color | #00B8D4 |
| glyph | U+203A right single angle bracket |
| transition | color, gap on hover (gap 4px to 8px) |
brand.json path: /component/cta-link
footer-construction-banner
| rule | transient pre-launch strip; red border, dark bg, small white text. Remove on public launch. Red accent is only allowed here. |
brand.json path: /component/footer-construction-banner
language-dropdown
| trigger | min-width 44px, min-height 44px touch target |
| panel | lists 43+ locales, alpine click-outside close, arrow-key nav |
brand.json path: /component/language-dropdown
form-input
Text-like inputs (type="text|email|url|password|tel" and type="search") on a dark surface. Chrome / Edge / Brave force #e8f0fe on :-webkit-autofill; a plain background-color cannot beat it. The brand defeat is a 1000px inset shadow at the parent surface color plus -webkit-text-fill-color for the foreground.
| surface | rgba(17, 19, 26, 0.99) (matches .bg-picker-panel) OR rgba(15, 17, 23, 0.99) (matches .bg-lang-panel). Use the actual parent panel color, never #e8f0fe. |
| foreground | #E6EAF2 via -webkit-text-fill-color (plain `color` is ignored on autofill) |
| caret | #00B8D4 (brand cyan) |
| border | 1px solid rgba(255, 255, 255, 0.10); focus uses rgba(0, 184, 212, 0.5) |
| focus-ring | outline 2px solid #00B8D4, outline-offset 1px (matches .bg-picker-search__input:focus-visible) |
| min-height | 36px desktop; 44px touch target on coarse pointers |
| font-size | 14px desktop, 16px on <=480px (16px prevents iOS Safari auto-zoom on focus) |
| placeholder | #6c7a8d (muted slate). Existing reference: .bg-picker-search__input::placeholder. |
| autofill-defeat | box-shadow: 0 0 0 1000px <surface> inset !important; -webkit-text-fill-color: <foreground> !important; caret-color: #00B8D4 !important; transition: background-color 5000s ease-in-out 0s. |
| autofill-states | apply to :-webkit-autofill AND :-webkit-autofill:hover, :focus, :active (all four). Anything less leaves a flash on interaction. |
| edge-ie-mute | ::-ms-reveal, ::-ms-clear { display: none } to hide the legacy Edge/IE password-reveal eye and clear-X. |
| reference-selectors | .bg-picker-search__input (assets/css/picker.css), .bg-lang-search__input (assets/css/site.css). Copy that block when adding a new input class. |
Focus the field, save the value to Chrome, then reload. The autofill defeat keeps the surface near-black, the text brand-foreground, and the caret cyan.
brand.json path: /component/form-input
select-dropdown
Custom listbox dropdown for dark-themed UI. Native <select> option lists are drawn by the OS and ignore CSS on Chrome / Windows: the popup paints with a white OS-themed background. Replacement: a button trigger plus a sibling listbox panel, driven by assets/js/select.js (vanilla ES module, no Alpine, no dependency).
| trigger | <button type="button"> min-height 44px, rgba(255,255,255,0.05) bg, 1px solid rgba(255,255,255,0.10), 10px radius, 7px 12px padding, Sora 14px, chevron rotates 180deg when open. |
| trigger-aria | aria-haspopup="listbox"; aria-expanded toggled by select.js. |
| panel | <div data-select-panel> positioned absolute top calc(100% + 4px), z-index 70, bg rgba(17,19,26,0.99), 1px solid rgba(255,255,255,0.10), 10px radius, overflow hidden. Wraps the search input + the listbox. |
| panel-open | .demo-select.is-open > .demo-select__trigger flips border-color to #00B8D4 (mirrors the Laravel admin language-switcher pattern). |
| search | Optional <input type=search data-select-search> at the top of the panel. Filters <li> rows live by label text and machine value (case-insensitive substring). Hides empty rows via the hidden attribute; .demo-select__empty shows when every row is filtered out. |
| listbox | <ul data-select-list role=listbox> max-height 240px; overflow-y auto; 3px scrollbar. |
| option | role="option"; min-height 36px; 7px 10px padding; Sora 13px; 3px transparent left border by default. |
| option-active | aria-selected="true"; rgba(0,184,212,0.08) bg; cyan #00B8D4 text; 3px LEFT BORDER cyan. Matches the brand sidebar active-state rule (never bottom, never right). |
| option-hover | rgba(255,255,255,0.04) background. |
| option-focus | outline 2px solid #00B8D4, outline-offset -2px so the ring sits inside the row. |
| keyboard | Trigger: Enter / Space / ArrowDown / ArrowUp open the panel. Search input takes focus on open if present, ArrowDown from search jumps to the first visible row. Panel rows: ArrowUp/Down navigate visible rows (wrap), Home / End jump, Enter commits, Escape closes and returns focus to the trigger. |
| dismiss | Click outside, Escape, or selecting an option closes the panel. |
| form-post | Sibling <input type="hidden" name="..." data-select-input> holds the canonical machine value (e.g. github) for traditional form posts. The visible label is the translated text; the posted value is the machine key. |
| i18n | Translate every visible option label through the consumer app's i18n layer. The data-value attribute on each <li> is the machine key and must never be translated. |
| markup-hooks | data-select (wrapper), data-select-trigger, data-select-label, data-select-panel (the dropdown surface), data-select-search (optional filter input), data-select-list (the <ul role=listbox>), data-select-option (per row), data-select-input (sibling hidden input). The controller auto-initialises every [data-select] on DOMContentLoaded. |
| reduced-motion | Chevron rotation and option hover transitions are disabled under prefers-reduced-motion: reduce. |
No matches.
brand.json path: /component/select-dropdown