@tidyfactor/design 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.tidyfactor +52 -0
- package/AGENTS.md +75 -0
- package/CHANGELOG.md +210 -0
- package/LICENSE +17 -0
- package/README.ar.md +398 -0
- package/README.de.md +44 -0
- package/README.es.md +44 -0
- package/README.fa.md +44 -0
- package/README.fr.md +44 -0
- package/README.md +418 -0
- package/README.pt.md +44 -0
- package/README.zh.md +44 -0
- package/SKILL-REGISTRY.md +69 -0
- package/SKILL.md +46 -0
- package/VISION.md +43 -0
- package/assets/blog.png +0 -0
- package/assets/content_layout.png +0 -0
- package/assets/content_output.png +0 -0
- package/assets/dark.png +0 -0
- package/assets/dashboard_layout.png +0 -0
- package/assets/dashboard_output.png +0 -0
- package/assets/ecommerce_layout.png +0 -0
- package/assets/ecommerce_output.png +0 -0
- package/assets/github-social-preview-2.png +0 -0
- package/assets/github-social-preview.png +0 -0
- package/assets/hero-banner.png +0 -0
- package/assets/light.png +0 -0
- package/assets/media_layout.png +0 -0
- package/assets/media_output.png +0 -0
- package/assets/og-default.png +0 -0
- package/assets/video.png +0 -0
- package/bin/add-skill.js +31 -0
- package/bin/create-kit.js +372 -0
- package/bin/remove-skill.js +137 -0
- package/brand.json +279 -0
- package/memory/01-design-schools.md +85 -0
- package/memory/02-design-tokens.md +41 -0
- package/memory/03-narrative-conversion.md +47 -0
- package/memory/04-motion-principles.md +44 -0
- package/memory/05-component-anatomy.md +34 -0
- package/memory/06-quality-bar.md +83 -0
- package/memory/07-consistency-contract.md +33 -0
- package/memory/08-arabic-bilingual.md +54 -0
- package/memory/09-prototype-flow.md +36 -0
- package/memory/10-python-tooling.md +64 -0
- package/memory/11-brand-json-v2.md +86 -0
- package/memory/12-typography-matrix.md +31 -0
- package/memory/13-layout-archetypes.md +30 -0
- package/memory/14-nav-footer-catalog.md +26 -0
- package/memory/15-performance-budget.md +18 -0
- package/memory/16-design-movements-guide.md +1084 -0
- package/memory/17-storytelling-industries-ux.md +143 -0
- package/memory/18-design-decision-engine.md +81 -0
- package/package.json +64 -0
- package/references/commands/_template.md +27 -0
- package/references/commands/assets.md +35 -0
- package/references/commands/audit.md +15 -0
- package/references/commands/brand.md +85 -0
- package/references/commands/brief.md +107 -0
- package/references/commands/clone.md +26 -0
- package/references/commands/components.md +46 -0
- package/references/commands/dashboard.md +45 -0
- package/references/commands/deploy.md +45 -0
- package/references/commands/flow.md +44 -0
- package/references/commands/handoff.md +53 -0
- package/references/commands/i18n.md +64 -0
- package/references/commands/init.md +30 -0
- package/references/commands/layout.md +81 -0
- package/references/commands/motion.md +62 -0
- package/references/commands/nav-footer.md +54 -0
- package/references/commands/page.md +45 -0
- package/references/commands/palette.md +35 -0
- package/references/commands/perf.md +57 -0
- package/references/commands/retrofit.md +15 -0
- package/references/commands/school.md +41 -0
- package/references/commands/states.md +48 -0
- package/references/commands/study.md +98 -0
- package/references/commands/tokens.md +45 -0
- package/references/commands/typography.md +87 -0
- package/references/foundations/daisyui.md +44 -0
- package/references/foundations/hybrid.md +32 -0
- package/references/foundations/native.md +31 -0
- package/references/foundations/tailwind-utility.md +43 -0
- package/references/memory/01-design-schools.md +85 -0
- package/references/memory/02-design-tokens.md +41 -0
- package/references/memory/03-narrative-conversion.md +47 -0
- package/references/memory/04-motion-principles.md +44 -0
- package/references/memory/05-component-anatomy.md +34 -0
- package/references/memory/06-quality-bar.md +83 -0
- package/references/memory/07-consistency-contract.md +33 -0
- package/references/memory/08-arabic-bilingual.md +54 -0
- package/references/memory/09-prototype-flow.md +36 -0
- package/references/memory/10-python-tooling.md +64 -0
- package/references/memory/11-brand-json-v2.md +86 -0
- package/references/memory/12-typography-matrix.md +31 -0
- package/references/memory/13-layout-archetypes.md +30 -0
- package/references/memory/14-nav-footer-catalog.md +26 -0
- package/references/memory/15-performance-budget.md +18 -0
- package/references/memory/16-design-movements-guide.md +1084 -0
- package/references/memory/17-storytelling-industries-ux.md +143 -0
- package/references/memory/18-design-decision-engine.md +81 -0
- package/references/memory/architecture.md +39 -0
- package/references/memory/decision-points.md +50 -0
- package/references/memory/foundations.md +15 -0
- package/references/memory/quality-bar.md +20 -0
- package/references/tidyfactor-vision.md +66 -0
- package/references/workflow.md +49 -0
- package/references/workflows/audit-prototype.md +26 -0
- package/references/workflows/brief.md +30 -0
- package/references/workflows/clone-prototype.md +27 -0
- package/references/workflows/init-prototype.md +28 -0
- package/references/workflows/retrofit-prototype.md +25 -0
- package/scripts/__pycache__/_utils.cpython-312.pyc +0 -0
- package/scripts/_utils.py +60 -0
- package/scripts/build.py +194 -0
- package/scripts/check_alpha.py +52 -0
- package/scripts/extract_palette.py +139 -0
- package/scripts/generate_transitions.py +105 -0
- package/scripts/inspect_images.py +48 -0
- package/scripts/minify_assets.py +140 -0
- package/scripts/optimize_assets.py +91 -0
- package/scripts/optimize_images.py +176 -0
- package/scripts/prepare_images.py +67 -0
- package/scripts/remove_backgrounds.py +61 -0
- package/scripts/test_build.py +228 -0
- package/templates/design-system/base.css +75 -0
- package/templates/design-system/components.css +229 -0
- package/templates/design-system/interactions.js +31 -0
- package/templates/design-system/motion.js +42 -0
- package/templates/design-system/tokens.css +81 -0
- package/templates/design-system/utilities.css +47 -0
- package/templates/index.html +84 -0
- package/templates/proto-nav.js +56 -0
- package/tools/build-skill.js +126 -0
- package/tools/validate-skill.js +144 -0
- package/tools/validate_skill.py +121 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Motion Principles — Reference for `motion`
|
|
2
|
+
|
|
3
|
+
Adapted from the classic animation principles, applied to UI motion rather
|
|
4
|
+
than character animation.
|
|
5
|
+
|
|
6
|
+
## Staging
|
|
7
|
+
One focal change communicated at a time. A section revealing five cards
|
|
8
|
+
simultaneously reads as noise; the same five staggered by ~60-80ms each
|
|
9
|
+
read as a considered sequence.
|
|
10
|
+
|
|
11
|
+
## Anticipation
|
|
12
|
+
A small pre-state before a bigger change helps the eye track what's about
|
|
13
|
+
to happen (a button's subtle scale-down before a bigger transition, a
|
|
14
|
+
skeleton before content pops in) — used sparingly, not on every
|
|
15
|
+
interaction.
|
|
16
|
+
|
|
17
|
+
## Ease-out for entrances, ease-in for exits
|
|
18
|
+
Things entering the screen should decelerate into place (ease-out);
|
|
19
|
+
things leaving should accelerate away (ease-in). Using the same easing
|
|
20
|
+
for both reads as mechanical rather than natural.
|
|
21
|
+
|
|
22
|
+
## Follow-through / slight overshoot
|
|
23
|
+
A very small overshoot-and-settle on an entrance (a card that slightly
|
|
24
|
+
overshoots its final position before settling) reads as more alive than a
|
|
25
|
+
purely linear arrival — use subtly, it's easy to overdo into "bouncy" and
|
|
26
|
+
undermine a restrained direction like Minimalism or Swiss.
|
|
27
|
+
|
|
28
|
+
## Secondary motion
|
|
29
|
+
A primary element moving (e.g. a hero image entering) can carry a small,
|
|
30
|
+
delayed secondary motion (a shadow settling a beat later, an accent
|
|
31
|
+
element trailing slightly) — this is what separates "orchestrated" motion
|
|
32
|
+
from "everything moves in lockstep".
|
|
33
|
+
|
|
34
|
+
## Restraint is a choice, not an absence
|
|
35
|
+
Per `frontend-design`: an orchestrated single moment usually lands harder
|
|
36
|
+
than scattered effects everywhere, and excess ambient animation is one of
|
|
37
|
+
the strongest tells that a design is AI-generated. `school`'s chosen
|
|
38
|
+
direction should determine how much motion is appropriate — Minimalism and
|
|
39
|
+
Swiss call for very little; Modern SaaS and Glassmorphism can carry more.
|
|
40
|
+
|
|
41
|
+
## Non-negotiable: `prefers-reduced-motion`
|
|
42
|
+
Every entrance/scroll/parallax effect in `motion.js` must check this media
|
|
43
|
+
query and fall back to instant or opacity-only transitions — applied
|
|
44
|
+
globally in the shared file, not per page.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Component Anatomy — Reference for `components`/`states`
|
|
2
|
+
|
|
3
|
+
## Atomic hierarchy (Atomic Design, adapted)
|
|
4
|
+
- **Atoms** — button, input, label, icon, badge. The smallest named unit;
|
|
5
|
+
never composed of other named components.
|
|
6
|
+
- **Molecules** — a form field (label + input + error text), a stat
|
|
7
|
+
(label + value + trend), a nav item (icon + label + active state).
|
|
8
|
+
- **Organisms** — a card, a data table, a navbar, a pricing tile, a modal.
|
|
9
|
+
Composed from atoms/molecules, still a single reusable named unit.
|
|
10
|
+
- **Templates** (this skill's `page`/`dashboard` output) — organisms
|
|
11
|
+
arranged into a page's actual layout. This is the one level that's
|
|
12
|
+
allowed to be page-specific — it's arrangement, not new styling.
|
|
13
|
+
|
|
14
|
+
A new visual need almost always belongs at the atom/molecule/organism
|
|
15
|
+
level, added once to `components.css`/the foundation library — not
|
|
16
|
+
invented at the template level.
|
|
17
|
+
|
|
18
|
+
## The full state matrix (apply per interactive component)
|
|
19
|
+
`default → hover → focus-visible → active/pressed → disabled`, plus where
|
|
20
|
+
relevant: `loading`, `empty`, `error`, `success`. A component "supports"
|
|
21
|
+
these states means each has an intentional look, not that the browser
|
|
22
|
+
default happens to apply.
|
|
23
|
+
|
|
24
|
+
## Naming discipline
|
|
25
|
+
One canonical name per real pattern. A "featured pricing card" and a
|
|
26
|
+
"testimonial card" that share 90% of their structure should be one `.card`
|
|
27
|
+
component with modifiers (`.card--featured`), not two components that will
|
|
28
|
+
quietly diverge over time.
|
|
29
|
+
|
|
30
|
+
## When something looks like it needs a new component but doesn't
|
|
31
|
+
If the only difference from an existing component is a token value (a
|
|
32
|
+
different accent color, a different size) — that's a modifier class or a
|
|
33
|
+
data attribute, not a new component. New components are for genuinely
|
|
34
|
+
different structure/behavior, not restyled instances.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Quality Bar — Auto-Reject Checklist for `audit`
|
|
2
|
+
|
|
3
|
+
A prototype fails review if any of these are true, regardless of how good individual pages look in isolation.
|
|
4
|
+
|
|
5
|
+
## Pre-Emit Self-Critique (1–5 Scores on 6 Axes)
|
|
6
|
+
Before handing back any output, score the artifact on 6 axes:
|
|
7
|
+
- **Philosophy (P)**: Opinionated stance vs generic template default.
|
|
8
|
+
- **Hierarchy (H)**: Clear visual weight & focal structure.
|
|
9
|
+
- **Execution (E)**: Clean layout alignment, zero inline overrides, valid tokens.
|
|
10
|
+
- **Specificity (S)**: Customized specifically to the subject's world/materials.
|
|
11
|
+
- **Restraint (R)**: Zero clutter, excess gradients, or fake cards.
|
|
12
|
+
- **Variety (V)**: Non-repetitive section rhythm across project pages.
|
|
13
|
+
|
|
14
|
+
*Any score < 3 triggers an automatic revision pass. Output must be stamped:*
|
|
15
|
+
`/* Pre-emit critique: P5 H4 E5 S4 R5 V5 */`
|
|
16
|
+
|
|
17
|
+
## Compositing & Blend Rules
|
|
18
|
+
- **The Blend Trap**: `mix-blend-mode` (multiply or screen) breaks on any element transformed by GSAP or CSS 3D transforms, creating a visible light/dark rectangle. Use background-removed transparent PNG cutouts (`rembg` + `Pillow`) for animated hero assets. Reserve `mix-blend-mode` strictly for static, untransformed imagery.
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
## Structural (highest severity — breaks the skill's core promise)
|
|
22
|
+
- **Anti-Design-Soup Violation**: Combining more than 1 Primary School, 1 Secondary Influence, 1 Motion Language, 1 Storytelling Style, or 1 UX Philosophy on a single page (unless explicitly requested).
|
|
23
|
+
- Any page has an inline `<style>` block or `style="..."` attribute.
|
|
24
|
+
- Any page has a `<script>` block that isn't `src`-linked to a shared `design-system/*` file.
|
|
25
|
+
- A value (color, font-size, spacing, radius, shadow) appears as a literal in any page without tracing to a token.
|
|
26
|
+
- Two pages render visually different versions of "the same" component (drift), or two components that are 90%+ identical exist under different names (near-duplicate).
|
|
27
|
+
|
|
28
|
+
## The 16 Named AI Anti-Pattern Tells (Auto-Reject)
|
|
29
|
+
1. **Purple-Gradient Hero**: Purple-to-pink/blue background gradient with white centered text.
|
|
30
|
+
2. **Inter-Everywhere**: Single unpaired font family used across display and body.
|
|
31
|
+
3. **3-Column Feature Grid**: 3 equal columns with icon above 2-line heading above 3-line body.
|
|
32
|
+
4. **Card-in-Card**: Nested container cards with no semantic structural reason.
|
|
33
|
+
5. **Gradient Headline**: `background-clip: text` linear gradient fill on headlines.
|
|
34
|
+
6. **Side-Stripe Card**: 4–6px thick colored border on left edge of card.
|
|
35
|
+
7. **Full-Viewport Centered Hero**: `min-height: 100vh` centered short sentence + big CTA.
|
|
36
|
+
8. **Pure Black / Pure White**: Pure `#000000` or `#ffffff` flat surfaces (must use tinted neutrals).
|
|
37
|
+
9. **Default-Attractor Sameness**: Reusing the same macrostructure on consecutive project pages.
|
|
38
|
+
10. **Specimen Fall-Through**: Defaulting to editorial `01 - HELLO` specimen layout for SaaS/B2B.
|
|
39
|
+
11. **The AI Nav**: Wordmark left, 4-5 links center, CTA right, 1px bottom border.
|
|
40
|
+
12. **The AI Footer**: 4 columns (Product, Company, Resources, Legal) + social row + copyright line.
|
|
41
|
+
13. **Aurora-Blob Background**: Flowing organic mesh blobs in purple/cyan behind hero text.
|
|
42
|
+
14. **Floating-Orb Decoration**: 3D spheres or blurred circles drifting behind hero.
|
|
43
|
+
15. **Italic Headers**: Flipping one word in a headline to italic (`Built to <em>think</em>`) to "look editorial".
|
|
44
|
+
16. **Lazy-Loaded LCP**: Adding `loading="lazy"` to the main hero LCP image (tanks performance).
|
|
45
|
+
|
|
46
|
+
## Mechanical Anti-Slop & Anti-Generic UI (Rule 8)
|
|
47
|
+
- **Ubiquitous Eyebrows**: More than 1 eyebrow tag (uppercase tracking small label) per 3 sections (`count > ceil(sectionCount / 3)`).
|
|
48
|
+
- **Floating Mid-Screen Hero**: Hero top padding exceeds `pt-24` (6rem) on desktop; headline > 2 lines; subtext > 20 words / 4 lines; primary CTA not visible without scroll.
|
|
49
|
+
- **Wrapped CTA Buttons**: Primary CTA button text wraps to 2+ lines on desktop; CTA text > 3 words.
|
|
50
|
+
- **Duplicate CTA Intent**: Multiple CTAs with the same underlying intent (e.g. mixing "Contact us", "Get in touch", and "Let's talk" on one page).
|
|
51
|
+
- **Un-aligned Card CTAs**: Buttons in a card grid not pinned to the bottom (`mt-auto`), creating jagged horizontal lines.
|
|
52
|
+
- **Invented Metrics**: Inventing fake statistics (*"+47% conversion"*, *"trusted by 50,000+ teams"*)—must use real data or `—` metric placeholders.
|
|
53
|
+
- **Re-Drawn Fake Chrome**: Fake CSS browser window frames (red/yellow/green traffic lights wrapping an iframe) or fake IDE title bars.
|
|
54
|
+
- **Fake Div Screenshots**: Using `<div>` rectangles to fake product UI instead of real images or real component previews.
|
|
55
|
+
|
|
56
|
+
## ⛔ 11 Explicit Codex & AI-Slop Defect Bans
|
|
57
|
+
1. **Ghost Cards**: Pairing 1px border with soft wide drop shadows `box-shadow: 0 Npx Mpx ...` (M ≥ 16px). Pick a solid border OR a shadow under 8px blur, never both as decoration.
|
|
58
|
+
2. **Over-Rounding (32px+)**: Applying `border-radius: 24px/32px/40px` to rectangular cards and sections. Cards top out at 12–16px radius (pills strictly for tags/buttons).
|
|
59
|
+
3. **Decorative Grid Background Overlays**: Adding two-axis `linear-gradient(... 1px, transparent 1px)` grid background patterns unless the page is an actual map, blueprint, canvas, or measurement tool.
|
|
60
|
+
4. **Side-Stripe Accent Borders**: Colored `border-left` or `border-right` > 1px as a card/alert callout crutch. Rewrite with solid borders or subtle background tinting.
|
|
61
|
+
5. **Warm Cream / Sand Saturated Neutral Default**: Defaulting all body backgrounds to warm beige/sand (`#F5F2EB` or token names like `--sand`, `--cream`, `--paper`). Pick a true neutral or brand-derived hue tint.
|
|
62
|
+
6. **Side-by-Side Saturated Text Gradients**: Applying `background-clip: text` gradients for emphasis. Use weight, size, or solid accent color.
|
|
63
|
+
7. **Reflexive Glassmorphism**: Adding decorative blurs and glass cards without clear spatial/layering purpose.
|
|
64
|
+
8. **Numbered Section Markers on Non-Sequences**: Prefixing non-sequential sections with `01 / 02 / 03`. Sequence numbers earn their place only on real multi-step processes or timelines.
|
|
65
|
+
9. **Sketchy SVG Illustrations**: Using crude 5-30 path SVG illustrations or doodle filters as fallback graphics.
|
|
66
|
+
10. **Diagonal Stripe Background Overlays**: Using `repeating-linear-gradient(...)` stripe overlays in hero/section backgrounds.
|
|
67
|
+
11. **Disjointed Display Heading Letter-Spacing**: Using letter-spacing tighter than `-0.04em` on H1 display headings causing characters to collide.
|
|
68
|
+
|
|
69
|
+
## Optical Alignment & Typography Hygiene
|
|
70
|
+
- **Data Table Numbers**: Multi-digit metrics or numbers missing `font-variant-numeric: tabular-nums` or monospace font alignment.
|
|
71
|
+
- **Orphaned Headline Words**: Single hanging words on display headers missing `text-wrap: balance` or `text-wrap: pretty`.
|
|
72
|
+
- **Optical Offsets**: Inline icons adjacent to text baselines missing 1-2px vertical optical adjustment.
|
|
73
|
+
- **Sudden Dark Sections**: A random dark-mode section breaking an otherwise light-mode page (or vice versa), reading as a copy-paste AI artifact.
|
|
74
|
+
|
|
75
|
+
## Interaction Completeness
|
|
76
|
+
- An interactive component is missing hover, active (`scale-[0.98]`), focus-visible, or disabled states.
|
|
77
|
+
- Focus rings are invisible or use browser default instead of token-colored ring.
|
|
78
|
+
|
|
79
|
+
## Arabic / Bilingual & Accessibility Floor
|
|
80
|
+
- Arabic display type uses any family other than El Messiri (headings) / Tajawal (body).
|
|
81
|
+
- Contrast fails WCAG AA on any token-derived text/background pairing.
|
|
82
|
+
- Touch targets under 44px on mobile/touch viewports.
|
|
83
|
+
- `prefers-reduced-motion` not respected globally.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# The Consistency Contract — Why the Architecture Is Strict
|
|
2
|
+
|
|
3
|
+
This is the mechanism, stated once so every command can refer back to it
|
|
4
|
+
instead of re-justifying it each time.
|
|
5
|
+
|
|
6
|
+
## The problem this skill exists to solve
|
|
7
|
+
A designer (or an agent) building a website one page at a time, with each
|
|
8
|
+
page free to write its own CSS/JS, will drift — not from carelessness, but
|
|
9
|
+
because "just this once" always feels justified in the moment a page needs
|
|
10
|
+
something slightly different. At 5 pages the drift is invisible. At 50
|
|
11
|
+
pages it's the whole project.
|
|
12
|
+
|
|
13
|
+
## The rule
|
|
14
|
+
Structural separation, not review discipline, is what prevents drift: if a
|
|
15
|
+
page *cannot* carry its own styling logic (no `<style>`, no inline
|
|
16
|
+
`style=`, no per-page `.css`/`.js` file), then drift becomes structurally
|
|
17
|
+
impossible rather than merely discouraged. This is why `page`/`dashboard`
|
|
18
|
+
treat a missing component as a hard stop, not a judgment call — "just add
|
|
19
|
+
it inline this once" is exactly the failure mode being designed against.
|
|
20
|
+
|
|
21
|
+
## The escape valve
|
|
22
|
+
The rule only works long-term if extending the shared system stays easy —
|
|
23
|
+
if adding a genuinely new component to `components.css` were harder than
|
|
24
|
+
writing 10 lines of scoped CSS, people would route around the rule. The
|
|
25
|
+
`components` command exists specifically to make the correct path (extend
|
|
26
|
+
the shared system) faster than the wrong path (patch locally), not just
|
|
27
|
+
more virtuous.
|
|
28
|
+
|
|
29
|
+
## What `audit` is actually checking
|
|
30
|
+
Every finding in `audit`'s structural scan traces back to this contract:
|
|
31
|
+
inline styles, per-page scripts, untraced literal values, and near-
|
|
32
|
+
duplicate components are all the same underlying failure — a page solved
|
|
33
|
+
its own problem instead of extending the shared one.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Arabic & Bilingual Design — Reference for `i18n`
|
|
2
|
+
|
|
3
|
+
Conventions carried consistently across Alwkala's production work and the
|
|
4
|
+
rest of the TidyFactor ecosystem (`tidyfactor-html`, `tidyfactor-cinematic`)
|
|
5
|
+
— not generic RTL advice.
|
|
6
|
+
|
|
7
|
+
## Typography
|
|
8
|
+
- Headings: **El Messiri** — modern, geometric-leaning, reads as
|
|
9
|
+
contemporary rather than traditional/calligraphic.
|
|
10
|
+
- Body: **Tajawal** — high legibility at small sizes, wide weight range.
|
|
11
|
+
- **Never Amiri** for UI/display purposes — it's a naskh-style text face
|
|
12
|
+
suited to long-form literary/religious typesetting, not product/marketing
|
|
13
|
+
UI; it reads as the wrong register for almost every brief this skill
|
|
14
|
+
serves.
|
|
15
|
+
- Arabic type generally needs slightly larger sizes and more line-height
|
|
16
|
+
than the Latin equivalent at the same visual weight — don't reuse the
|
|
17
|
+
Latin type scale unchanged.
|
|
18
|
+
|
|
19
|
+
## Layout mirroring
|
|
20
|
+
- Mirrors: navigation order, breadcrumbs, form label alignment, icon
|
|
21
|
+
direction for directional affordances (back/next arrows), the reading
|
|
22
|
+
flow of card grids.
|
|
23
|
+
- Does NOT mirror: numerals (Arabic numerals in most modern digital
|
|
24
|
+
products are written left-to-right even inside RTL text), embedded Latin
|
|
25
|
+
brand names/wordmarks, code or tabular data blocks.
|
|
26
|
+
- Use `unicode-bidi: isolate` (or `dir="ltr"` spans) around any LTR content
|
|
27
|
+
embedded inside RTL flow to prevent bidi algorithm artifacts (numbers or
|
|
28
|
+
Latin words appearing in the wrong order).
|
|
29
|
+
|
|
30
|
+
## Logo & identity
|
|
31
|
+
Logo/wordmark stays pixel-identical and unmirrored across locales — brand
|
|
32
|
+
identity doesn't flip with the reading direction, even when everything
|
|
33
|
+
around it does.
|
|
34
|
+
|
|
35
|
+
## Bilingual site patterns
|
|
36
|
+
- **Separate localized pages** — clean, works with every command
|
|
37
|
+
unchanged, best when content structure genuinely differs by locale.
|
|
38
|
+
- **Single page, dual-tree toggle** — both language trees present in one
|
|
39
|
+
file, toggled via `proto-nav.js` — best for fast side-by-side prototype
|
|
40
|
+
review with a client, worse for a real production site (both trees ship
|
|
41
|
+
to every visitor).
|
|
42
|
+
Pick one per project and record it in `brand.json`; don't mix within a
|
|
43
|
+
project.
|
|
44
|
+
|
|
45
|
+
## Voice & tone
|
|
46
|
+
If `brand.json`'s `voice.*` block has a localized Arabic register, apply it
|
|
47
|
+
directly — a good Arabic UI voice is not a literal translation of the
|
|
48
|
+
English one; register, formality, and idiom differ by convention.
|
|
49
|
+
|
|
50
|
+
## Interaction states in RTL
|
|
51
|
+
Re-check, don't just assume: dropdown/menu open-direction, modal
|
|
52
|
+
close-button position, tooltip anchor side, and any icon implying
|
|
53
|
+
directionality — all need a considered RTL equivalent, not just a global
|
|
54
|
+
`transform: scaleX(-1)`.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Prototype Flow & Present Mode — Reference for `flow`
|
|
2
|
+
|
|
3
|
+
## What makes this a "prototype" rather than a set of pages
|
|
4
|
+
A Figma prototype's core value isn't the individual frames — it's the
|
|
5
|
+
click-through experience that lets a stakeholder feel the product before
|
|
6
|
+
it's built. This skill's `flow` command exists to reproduce that
|
|
7
|
+
experience in real, running HTML rather than a design tool's simulation.
|
|
8
|
+
|
|
9
|
+
## Journey-first, not link-everything
|
|
10
|
+
Map 2-4 real journeys from the brief (e.g. "visitor discovers pricing →
|
|
11
|
+
signs up → sees the empty-state dashboard → adds first item → sees
|
|
12
|
+
populated dashboard") and wire those specifically. A prototype where every
|
|
13
|
+
page links to every other page has no narrative — it's a sitemap, not a
|
|
14
|
+
journey.
|
|
15
|
+
|
|
16
|
+
## The prototype toolbar
|
|
17
|
+
A small, clearly-a-tool-not-part-of-the-design floating control
|
|
18
|
+
(`proto-nav.js`) giving:
|
|
19
|
+
- Jump to any page (for the reviewer exploring freely)
|
|
20
|
+
- "Restart flow" (return to the journey's first page)
|
|
21
|
+
- State toggles where a page/screen has meaningful alternate states
|
|
22
|
+
(empty vs. populated dashboard, logged-out vs. logged-in) without
|
|
23
|
+
needing separate physical pages for each
|
|
24
|
+
|
|
25
|
+
## State toggles without a backend
|
|
26
|
+
A dashboard's empty/loading/error/populated states can be selected via a
|
|
27
|
+
URL query parameter (`?state=empty`) read by a small inline check in the
|
|
28
|
+
shared `interactions.js`, or via the toolbar directly — this keeps the
|
|
29
|
+
prototype's states real and inspectable without simulating an actual data
|
|
30
|
+
layer.
|
|
31
|
+
|
|
32
|
+
## What to strip before a production handoff
|
|
33
|
+
`proto-nav.js` and any state-toggle scaffolding are prototype-only tools —
|
|
34
|
+
flag them explicitly in `deploy`'s output so they don't accidentally ship
|
|
35
|
+
if this project is later handed to `tidyfactor-html`/`tidyfactor-php-*` for
|
|
36
|
+
production.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# 10 · Python Tooling & Asset Refinement Guide
|
|
2
|
+
|
|
3
|
+
The **TidyFactor Design** skill includes a lightweight Python tooling suite in `scripts/` to provide AI Agents with local media manipulation, palette extraction, background removal, and image optimization capabilities.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🛠️ Tooling Suite Inventory
|
|
8
|
+
|
|
9
|
+
| Script | Primary Responsibility | Dependencies | Command Trigger |
|
|
10
|
+
|---|---|---|---|
|
|
11
|
+
| **`scripts/extract_palette.py`** | Image color quantization, WCAG 2.1 AA contrast check, `brand.json` & `tokens.css` sync | `Pillow` | `palette`, `tokens`, `init`, `clone` |
|
|
12
|
+
| **`scripts/remove_backgrounds.py`** | AI background removal (`rembg`) for transparent PNG logos, product shots, & cutouts | `rembg`, `Pillow` | `init`, `components`, `page`, `retrofit` |
|
|
13
|
+
| **`scripts/optimize_assets.py`** | Resizes heavy assets to design token bounds (heroes max 1200px, cards 400px, logos 240px) | `Pillow` | `deploy`, `audit` |
|
|
14
|
+
| **`scripts/minify_assets.py`** | Bundles & minifies CSS/JS for presentation deployment | Standard Python | `deploy` |
|
|
15
|
+
| **`scripts/inspect_images.py`** | Inspects image dimensions, color channels, and alpha channel status | Standard Python | `audit` |
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 1 · Color Palette Extraction (`scripts/extract_palette.py`)
|
|
20
|
+
|
|
21
|
+
Extracts primary, secondary, and accent colors from reference images, photos, or logos. Computes WCAG 2.1 AA contrast scores.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Extract palette and sync brand.json + tokens.css
|
|
25
|
+
python scripts/extract_palette.py assets/logo.png --json brand.json --css design-system/tokens.css
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 2 · AI Background Removal (`scripts/remove_backgrounds.py`)
|
|
31
|
+
|
|
32
|
+
Isolates product shots, logos, or hero items into transparent PNG cutouts using `rembg`:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# Single file background removal
|
|
36
|
+
python scripts/remove_backgrounds.py assets/product.jpg -o assets/product-cut.png
|
|
37
|
+
|
|
38
|
+
# Batch processing
|
|
39
|
+
python scripts/remove_backgrounds.py assets/logo1.jpg:assets/logo1.png assets/card.jpg:assets/card.png
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 3 · Asset Resizing & Optimization (`scripts/optimize_assets.py`)
|
|
45
|
+
|
|
46
|
+
Constrains image dimensions to design system tokens to prevent layout shifts and heavy page loads:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# Resize hero images to max 1200px dimension
|
|
50
|
+
python scripts/optimize_assets.py assets/hero.jpg --max-dim 1200
|
|
51
|
+
|
|
52
|
+
# Resize logo assets to max 240px dimension
|
|
53
|
+
python scripts/optimize_assets.py assets/logo.png --max-dim 240
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## 📋 Dependency Management
|
|
59
|
+
|
|
60
|
+
Dependencies are documented in `requirements.txt`:
|
|
61
|
+
```bash
|
|
62
|
+
pip install -r requirements.txt
|
|
63
|
+
```
|
|
64
|
+
If `rembg` or `Pillow` is missing, scripts output clear installation guidance without crashing.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# 11 · brand.json v2 Schema Reference
|
|
2
|
+
|
|
3
|
+
The single source of truth for brand identity across all TidyFactor surfaces. Every
|
|
4
|
+
design-system file, component, and page reads tokens from this file — never hardcode
|
|
5
|
+
a hex value or font name inline.
|
|
6
|
+
|
|
7
|
+
## Schema version
|
|
8
|
+
|
|
9
|
+
`"schemaVersion": "brand-core-v2"` — the v2 schema adds dual-mode colors, shadows, radius,
|
|
10
|
+
spacing scale, motion tokens, breakpoints, iconography, component token refs,
|
|
11
|
+
localization, and accessibility floor.
|
|
12
|
+
|
|
13
|
+
## Required sections
|
|
14
|
+
|
|
15
|
+
| Section | Purpose |
|
|
16
|
+
|---|---|
|
|
17
|
+
| `meta` | Product name, tagline, description, version, lastUpdated |
|
|
18
|
+
| `identity` | Logo paths (full, fullDark, mark, favicon), social preview (ogImage) |
|
|
19
|
+
| `voice` | Tone, personality, registers (professional/casual/error/success), doNotUse words |
|
|
20
|
+
| `colors.light` | 16 semantic tokens for light mode (background, surface, surface2, border, text, textMuted, primary, primaryForeground, secondary, secondaryForeground, accent, success, warning, danger, info, codeBackground) |
|
|
21
|
+
| `colors.dark` | Mirror 16 tokens for dark mode |
|
|
22
|
+
| `typography` | Families (heading, body, display, mono, arabicHeading, arabicBody), weights, scale, lineHeight, letterSpacing, googleFontsUrl |
|
|
23
|
+
| `spacing` | baseUnit (4px) + scale (0–24) |
|
|
24
|
+
| `radius` | none, sm, md, lg, xl, full, default |
|
|
25
|
+
| `shadows` | sm, md, lg, focusRing (uses `color-mix()`) |
|
|
26
|
+
| `motion` | duration (fast/base/slow), easing (standard/emphasized/spring), reducedMotion policy, scope |
|
|
27
|
+
| `breakpoints` | sm, md, lg, xl, 2xl |
|
|
28
|
+
| `iconography` | set (lucide), strokeWidth, sizes, rule |
|
|
29
|
+
| `components` | Token refs for button, input, card, codeBlock |
|
|
30
|
+
| `localization` | defaultLocale, supportedLocales, rtl, rtlLocales, mirrorOnRtl, dateFormat |
|
|
31
|
+
| `accessibility` | minTouchTarget (44px), focusVisible policy, altTextPolicy |
|
|
32
|
+
| `foundation` | Locked CSS foundation (native, tailwind, daisyui, hybrid, shadcn, pico, bootstrap, alpine) |
|
|
33
|
+
| `school` | Design school (minimalist, brutalist, neo-skeuomorphic, glassmorphic, editorial, playful) |
|
|
34
|
+
| `usage` | sharedBy (which kits consume this file), rules (governance) |
|
|
35
|
+
|
|
36
|
+
## Dual-mode colors rule
|
|
37
|
+
|
|
38
|
+
Brand colors (`primary`, `accent`) do NOT change between light/dark — only
|
|
39
|
+
`background`, `surface`, `border`, and `text` tokens shift. This ensures brand
|
|
40
|
+
recognition across modes.
|
|
41
|
+
|
|
42
|
+
## Token reference convention (components section)
|
|
43
|
+
|
|
44
|
+
Component specs reference other sections via dot-path strings:
|
|
45
|
+
```json
|
|
46
|
+
"button": {
|
|
47
|
+
"radius": "radius.md",
|
|
48
|
+
"primaryBg": "colors.primary",
|
|
49
|
+
"primaryFg": "colors.primaryForeground"
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
These are resolved at build-time by the design-system generator — they are NOT
|
|
53
|
+
runtime CSS variable references.
|
|
54
|
+
|
|
55
|
+
## `focusRing` shadow using `color-mix()`
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
"focusRing": "0 0 0 3px color-mix(in srgb, var(--primary) 40%, transparent)"
|
|
59
|
+
```
|
|
60
|
+
This produces a 40%-opacity brand-colored focus ring that automatically adapts
|
|
61
|
+
to the active primary color. Supported in all modern browsers (Safari 16.4+,
|
|
62
|
+
Chrome 111+, Firefox 113+).
|
|
63
|
+
|
|
64
|
+
## Backward compatibility (v1 → v2 migration)
|
|
65
|
+
|
|
66
|
+
| v1 token | v2 equivalent |
|
|
67
|
+
|---|---|
|
|
68
|
+
| `colors.primary` | `colors.light.primary` / `colors.dark.primary` |
|
|
69
|
+
| `colors.neutralDark` | `colors.light.text` |
|
|
70
|
+
| `colors.neutralLight` | `colors.light.surface` |
|
|
71
|
+
| `colors.paper` | `colors.light.background` |
|
|
72
|
+
| `colors.ink` | `colors.light.text` |
|
|
73
|
+
| `colors.inkSoft` | `colors.light.textMuted` |
|
|
74
|
+
| `typography.headings.arabic` | `typography.families.arabicHeading` |
|
|
75
|
+
| `typography.body.arabic` | `typography.families.arabicBody` |
|
|
76
|
+
| `typography.headings.latin` | `typography.families.display.primary` |
|
|
77
|
+
| `typography.body.latin` | `typography.families.body.primary` |
|
|
78
|
+
|
|
79
|
+
## Checklist
|
|
80
|
+
- [ ] `$schema` is `"brand-core-v2"`
|
|
81
|
+
- [ ] Both `colors.light` and `colors.dark` have all 16 tokens
|
|
82
|
+
- [ ] `contrastPolicy` specifies WCAG AA minimum
|
|
83
|
+
- [ ] `motion.reducedMotion` policy is stated
|
|
84
|
+
- [ ] `accessibility.minTouchTarget` is ≥ 44px
|
|
85
|
+
- [ ] `foundation` is one of the 8 supported options
|
|
86
|
+
- [ ] `googleFontsUrl` loads ONLY families referenced in `typography.families`
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# 12 · Typography Matrix — Mood-Routed Font Pairings
|
|
2
|
+
|
|
3
|
+
This document defines the 7 mood-routed typography pairings for `tidyfactor-design`.
|
|
4
|
+
While the default pairing (`El Messiri` + `Tajawal` + `Cormorant Garamond`) remains safe and clean for general builds, brand personality often demands a distinctive font pairing matching the visual layout's emotional register.
|
|
5
|
+
|
|
6
|
+
## Constraint Rules
|
|
7
|
+
1. **Clean over calligraphic for display headings**: Never use **Amiri** or any Naskh/manuscript script face above ~24px.
|
|
8
|
+
2. **Display-only font rules**: Faces like **Jomhuria** are display-only (≥48px) and must never be used for body text.
|
|
9
|
+
3. **CDN-only**: All fonts must be available via Google Fonts. No self-hosting or build step required.
|
|
10
|
+
|
|
11
|
+
## Mood → Typography Pairing Matrix
|
|
12
|
+
|
|
13
|
+
| Mood | Arabic Heading | Arabic Body | Latin Accent | Best Layouts | Avoid For |
|
|
14
|
+
|---|---|---|---|---|---|
|
|
15
|
+
| **Default luxury** | El Messiri | Tajawal | Cormorant Garamond | Any | — |
|
|
16
|
+
| **Editorial / literary** | Markazi Text | IBM Plex Sans Arabic | Fraunces | `story` (editorial) | `app` (too soft for UI chrome) |
|
|
17
|
+
| **Art-Deco / high fashion** | Jomhuria *(display ≥48px)* | Cairo | Bodoni Moda | `film` (fullbleed) | `creator` (too loud) |
|
|
18
|
+
| **Modern minimal / tech** | Cairo | Cairo (weight-differentiated) | Marcellus | `app` (interface), `creator` | `space` (reads cold) |
|
|
19
|
+
| **Warm hospitality / travel** | El Messiri | Almarai | Prata | `space` (spatial) | — |
|
|
20
|
+
| **E-Commerce & conversion** | El Messiri | Tajawal | Cormorant Garamond | `product`, `store` | — |
|
|
21
|
+
| **Automotive / performance** | El Messiri + Oswald (numerals) | Tajawal | Oswald | `film`, `story` (auto) | non-automotive |
|
|
22
|
+
|
|
23
|
+
## Google Fonts Loading Standard
|
|
24
|
+
|
|
25
|
+
Always use preconnect links and load only the required families to satisfy the performance budget (≤3 families, ≤4 weights):
|
|
26
|
+
|
|
27
|
+
```html
|
|
28
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
29
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
30
|
+
<link href="https://fonts.googleapis.com/css2?family=El+Messiri:wght@400;600;700&family=Tajawal:wght@400;500;700&display=swap" rel="stylesheet">
|
|
31
|
+
```
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# 13 · Layout Archetypes — Surface Blueprints
|
|
2
|
+
|
|
3
|
+
This document specifies the 8 macrostructure layout archetypes available in `tidyfactor-design`.
|
|
4
|
+
|
|
5
|
+
## Archetype Overview
|
|
6
|
+
|
|
7
|
+
| Layout | Codename | Hero Type | Section Rhythm | Best For |
|
|
8
|
+
|---|---|---|---|---|
|
|
9
|
+
| **Film** | `fullbleed` | Cutout + aura + motes | Hero → Film (600vh canvas) → Product reveal → Lifestyle → CTA | Physical luxury goods, brand stories |
|
|
10
|
+
| **Story** | `editorial` | Split-screen image & copy | Hero → Film (420vh) → Feature grid → Origin story → CTA | Specs-heavy products, events, founders |
|
|
11
|
+
| **Space** | `spatial` | Wide architectural shot | Hero → Spatial film (500vh) → Space details → Location → CTA | Real estate, architecture, hospitality |
|
|
12
|
+
| **App** | `interface` | Device mockup frame | Hero → UI flow film (420vh) → Feature highlights → Proof → CTA | SaaS, web/mobile applications |
|
|
13
|
+
| **Creator** | `minimal` | Centered cutout / photo | Hero → Statement → Story & Portrait → Portfolio → CTA | Personal brands, digital products |
|
|
14
|
+
| **Product** | `product` | Product + Price + Buy CTA | Hero product → Spec highlights → Reviews → Purchase CTA | High-conversion single-product store |
|
|
15
|
+
| **Store** | `store` | Banner + Category nav | Store banner → Category filter → Catalog grid → Footer | Multi-product catalog store |
|
|
16
|
+
| **Auto** | `auto` | Hero vehicle + HUD gauge | Hero → 3D stage slider → Tech specs → Performance gallery → CTA | Automotive, performance engineering |
|
|
17
|
+
|
|
18
|
+
## Hero Layering Architecture
|
|
19
|
+
|
|
20
|
+
Every cinematic or luxury layout uses nested container layers so each layer owns a single transform channel without conflicts:
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
.stage (perspective)
|
|
24
|
+
.aura → Radial background glow (CSS pulse + parallax)
|
|
25
|
+
.motes → Floating particles drift
|
|
26
|
+
.hero-inner
|
|
27
|
+
.media-float → CSS float animation (translateY bob)
|
|
28
|
+
.media-tilt → JS pointer-driven 3D rotateX/rotateY
|
|
29
|
+
img.cutout → GSAP entrance transform (scale/opacity)
|
|
30
|
+
```
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# 14 · Navigation & Footer Catalogs
|
|
2
|
+
|
|
3
|
+
Reference catalog for Navigation (N1–N9) and Footer (Ft1–Ft8) components.
|
|
4
|
+
|
|
5
|
+
## Navigation Archetypes
|
|
6
|
+
|
|
7
|
+
- **N1: Floating Pill** — Glassmorphic floating navigation pill (`max-w-fit mx-auto`), rounded corners. Ideal for modern SaaS and mobile interfaces.
|
|
8
|
+
- **N2: Newspaper Masthead** — Traditional publishing layout with centered brand title, divider rule, and category links below.
|
|
9
|
+
- **N3: Brutal Slab** — Stark 4px bottom border, monochrome uppercase labels, sharp edges.
|
|
10
|
+
- **N4: Terminal / CLI** — Monospace typography with prompt caret `>` markers on dark background.
|
|
11
|
+
- **N5: Edge-Aligned Minimal** — Wordmark aligned hard left, navigation links hard right. Zero center clutter.
|
|
12
|
+
- **N6: Split Brand** — Centered brand emblem with links balanced on left and right sides.
|
|
13
|
+
- **N7: Double-Decker Utility** — Top notification/language bar paired with main brand header.
|
|
14
|
+
- **N8: Vertical Rail** — Fixed left/right navigation rail for web app dashboards.
|
|
15
|
+
- **N9: Fullscreen Overlay** — Trigger button opening full-viewport navigation overlay.
|
|
16
|
+
|
|
17
|
+
## Footer Archetypes
|
|
18
|
+
|
|
19
|
+
- **Ft1: Mast-Headed** — Giant brand wordmark overlaying top of footer section with multi-column links below.
|
|
20
|
+
- **Ft2: Minimal Inline** — Clean single-line layout containing wordmark, links, and copyright notice.
|
|
21
|
+
- **Ft3: Colophon / Credits** | Displays build metadata, typography credits, server location, and license.
|
|
22
|
+
- **Ft4: Big Statement** | Prominent quote or mission statement block preceding link navigation.
|
|
23
|
+
- **Ft5: Letter Close** | Personal signed letter from founder/creator with CTA before footer links.
|
|
24
|
+
- **Ft6: Newsletter-First** | Large email signup form occupying primary focal space.
|
|
25
|
+
- **Ft7: Marquee Scroll** | Continuous horizontal text ticker banner above secondary links.
|
|
26
|
+
- **Ft8: Sitemap Grid** | Comprehensive multi-column link directory with locale and theme switchers.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# 15 · Performance Budget Specification
|
|
2
|
+
|
|
3
|
+
Mechanical performance budgets for asset weight and DOM performance across all prototypes in `tidyfactor-design`.
|
|
4
|
+
|
|
5
|
+
## Asset Class Budget Table
|
|
6
|
+
|
|
7
|
+
| Asset Class | Budget Limit | Validation Command / Check |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| Frame Sequence (`assets/seq/*.jpg`) | ≤ 6.0 MB total | Sum of directory file sizes |
|
|
10
|
+
| Individual Frame JPG | ≤ 60 KB at 1280px | Individual file size check |
|
|
11
|
+
| Hero Cutout Image | ≤ 400 KB | Image optimizer `scripts/optimize_assets.py` |
|
|
12
|
+
| Logo / Emblem Asset | ≤ 40 KB | Image optimizer check |
|
|
13
|
+
| Font Families | ≤ 3 families, ≤ 4 weights | Count in Google Fonts `<link>` tag |
|
|
14
|
+
| Design System CSS | ≤ 150 KB total | Combined size of `design-system/*.css` |
|
|
15
|
+
|
|
16
|
+
## LCP Image Optimization Rule
|
|
17
|
+
Hero LCP (Largest Contentful Paint) images MUST NOT use `loading="lazy"`. Doing so degrades load performance and violates Quality Bar Rule #16.
|
|
18
|
+
Below-the-fold images MUST use `loading="lazy"`.
|