Here are your HTML/CSS rules so far, consolidated into one reference.

\### HTML & CSS Basics — Rules So Far

\| #  | Rule                                            | Key point                                                                                                                                                       |

\| -- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |

\| 1  | \*\*Vertical margins can collapse\*\*               | Adjacent vertical margins on normal block elements can collapse. The resulting gap is generally the larger margin, not the sum. Flex/grid items and several other layout situations do not collapse this way.               |

\| 2  | \*\*Text contrast\*\*                               | Normal text should have at least \*\*4.5:1\*\* contrast against its background. Large text can use \*\*3:1\*\*.                                                         |

\| 3  | \*\*Center a block with auto margins\*\*            | Give it an appropriate width and use \`margin-left: auto; margin-right: auto;\`, commonly \`margin: 0 auto;\`. A parent’s \`text-align: center\` does \*\*not\*\* replace this for block children. Still works on a flex \*\*container\*\* itself; use flex alignment for its \*\*children\*\*. |

\| 4  | \*\*\`text-align: center\` centers inline content\*\* | Set it on the parent to center text, images, spans, and other inline/inline-block content. It does \*\*not\*\* center normal \*\*block\*\* children — those still need \`width\` + \`margin: 0 auto\` (rule 3). |

\| 5  | \*\*Know block vs inline\*\*                        | Block elements normally start a new line and take available width. Inline elements flow with surrounding content and generally take only the space they need.   |

\| 6  | \*\*\`display\` can change default behavior\*\*       | An element's default block/inline behavior can be changed with \`display\`.                                                                                       |

\| 7  | \*\*Use Flexbox for flexible layouts\*\*            | \`display: flex\` makes the \*\*direct children\*\* flex items. The flex container is still a block-level box (full width by default) unless you change that.           |

\| 8  | \*\*\`justify-content\` controls the main axis\*\*    | Packs items along the \*\*main\*\* axis: \`flex-start\`, \`flex-end\`, \`center\`, \`space-between\`, \`space-around\`, \`space-evenly\`.                                      |

\| 9  | \*\*\`align-items\` controls the cross axis\*\*       | Aligns items along the \*\*cross\*\* axis: \`stretch\` (default), \`flex-start\`, \`flex-end\`, \`center\`, \`baseline\`.                                                     |

\| 10 | \*\*Prefer \`gap\` for spacing between flex items\*\* | \`gap\` (or \`row-gap\` / \`column-gap\`) adds space \*\*between\*\* items only — not outside the edges. Use \`margin\` when one item needs unique spacing.                 |

\| 11 | \*\*Lean on inheritance\*\*                         | Properties like \`color\`, \`font-size\`, and \`font-family\` inherit. Set them once on a parent instead of repeating them on every child.                            |

\| 12 | \*\*Keep CSS DRY\*\*                                | Share styles through common selectors or classes. Avoid copying the same declarations onto many one-off rules when one shared rule can do the job.               |

\| 13 | \*\*Understand relative paths\*\*                   | \`./\` = current directory, \`../\` = one directory up, \`../../\` = two up.                                                                                          |

\| 14 | \*\*Understand root-relative paths\*\*              | \`/\` starts from the current origin's root rather than the current file's directory. This matters when an app is deployed under a subpath such as \`/my-app/\`.                                                                                    |

\| 15 | \*\*Write meaningful \`alt\` text\*\*                 | Describe the image's relevant meaning as though explaining it to someone over the phone.                                                                        |

\| 16 | \*\*Don't write “image of” in \`alt\`\*\*             | Screen readers already communicate that the element is an image.                                                                                                |

\| 17 | \*\*Keep \`alt\` concise\*\*                          | \`<125\` characters is a useful guideline, not a strict HTML/WCAG requirement.                                                                                    |

\| 18 | \*\*Decorative images use \`alt=""\`\*\*              | This allows assistive technology to ignore images that provide no meaningful information.                                                                       |

\| 19 | \*\*\`alt\` is primarily accessibility\*\*            | It also helps when images fail to load and can help search engines understand image content.                                                                    |

\| 20 | \*\*Use system/web-safe fonts when appropriate\*\*  | They are simple, fast, and reliable. Use web fonts when the design needs them, but always include sensible fallbacks.                                                                                              |

\| 21 | \*\*Always include font backups\*\*                 | If you set \`font-family\`, never list only one font. Provide at least one named backup when useful, and \*\*always\*\* end with a generic family (\`serif\`, \`sans-serif\`, \`monospace\`, or \`cursive\`) so the browser can still pick something sensible. |

\| 22 | \*\*Box shorthand is clockwise: T → R → B → L\*\*   | Four values map to \*\*top, right, bottom, left\*\*. The same order applies to \`margin\`, \`padding\`, and border sides (\`border-width\`, \`border-style\`, \`border-color\`). |

\| 23 | \*\*Find color schemes on Coolors\*\*               | Use [coolors.co]\(https\://coolors.co) to explore, generate, or \*\*extract\*\* a palette, then apply those hex colors in your CSS (\`background\`, \`color\`, borders, accents). After picking colors, still check text contrast (rule 2). |

\| 24 | \*\*Use Unsplash, Pexels, or undraw for imagery\*\*  | Free stock photos from [Unsplash]\(https\://unsplash.com) or [Pexels]\(https\://www\.pexels.com) are fine for practice/projects. Flat illustration heroes may use [undraw.co]\(https\://undraw.co/) (or a local undraw-style SVG). Attribution is usually appreciated rather than required, but always check the current license and usage terms. |

\| 25 | \*\*\`div\` vs \`span\`\*\*                             | Use \`div\` as a generic block container and \`span\` as a generic inline container. Prefer semantic elements such as \`section\`, \`article\`, \`nav\`, \`header\`, and \`footer\` when they describe the content meaningfully. |

\| 26 | \*\*Use \`inherit\` when you want the parent’s value\*\* | \`inherit\` makes a property take its \*\*parent’s computed value\*\*. Useful to undo a browser default, pass a parent style into a child that normally would not inherit that property, or keep nested text matching its container. |

\| 27 | \*\*Google Fonts are fine for practice\*\*          | Load a font from [Google Fonts]\(https\://fonts.google.com) with \`\<link>\` tags in \`\<head>\` (not CSS \`@import\`, which blocks rendering), then use it in \`font-family\` with backups (rule 21). |

\| 28 | \*\*Local fonts via \`@font-face\` (TTF/OTF)\*\*      | Download a font (e.g. from [1001 Fonts]\(https\://www\.1001fonts.com)), put the \`.ttf\` / \`.otf\` in your project, declare it with \`@font-face\`, then use the family name — always with backups. |

\| 29 | \*\*Be careful with externally hosted animation assets\*\* | WebP can be smaller than GIF, but avoid depending on hotlinked CDN URLs unless the service permits it. Check embedding and licensing terms. |

\| 30 | \*\*Use an overlay on photo backgrounds\*\*         | Text on a busy \`background\` image often fails contrast (rule 2). Add a \*\*dark (or light) overlay\*\* between the photo and the content so text and controls stay readable. |

\| 31 | \*\*\`text-shadow\` can improve readability\*\*       | It may help text stand out on busy backgrounds, but do \*\*not\*\* rely on it to satisfy contrast requirements. Prefer a proper overlay or stronger foreground/background contrast. |

\| 32 | \*\*Always set \`lang\` on \`\<html>\`\*\*               | Use a language code such as \`lang="en"\`. Screen readers use it for pronunciation; search engines use it for language; browsers use it for language-related features (quotes, hyphenation, fonts). |

\| 33 | \*\*Circular photos: equal size + \`border-radius: 50%\`\*\* | Give the image equal \*\*width\*\* and \*\*height\*\*, add \`object-fit: cover\` to avoid distortion, then use \`border-radius: 50%\`. |

\| 34 | \*\*Pill buttons use a huge radius\*\*              | Large horizontal padding + \`border-radius: 999px\` (or another very high value) makes a capsule / pill shape.                                                    |

\| 35 | \*\*Soft card lift with \`box-shadow\`\*\*            | A light shadow (e.g. \`0 4px 12px rgba(0, 0, 0, 0.15)\`) lifts a box off the page without a hard border.                                                          |

\| 36 | \*\*Full-bleed band / breakout\*\*                   | A section with full available width and no side margins can run a color or photo \*\*edge to edge\*\* as a visual band. For partial breakout, use a 4-column grid with outer \`minmax(0, 1fr)\` gutters and inner content tracks, then \`grid-area\` so media spans into a gutter while copy stays in the constrained column. |

\| 37 | \*\*Truncate long text with ellipsis\*\*            | \`overflow: hidden; white-space: nowrap; text-overflow: ellipsis\` cuts a single line with “…”.                                                                   |

\| 38 | \*\*Soft square (squircle)\*\*                      | Medium \`border-radius\` (about \`12px\`–\`24px\`) softens corners without going fully circular.                                                                      |

\| 39 | \*\*Same-size thumbnails\*\*                        | Set both \`width\` and \`height\`, then use \`object-fit: cover\` so images stay even without being stretched.                                                                                         |

\| 40 | \*\*Two-tone section rhythm\*\*                     | Alternate backgrounds (e.g. \`.box\` / \`.box-alt\`) to create visual rhythm without complex layout.                                                                |

\| 41 | \*\*Strong header band as a visual anchor\*\*       | A tall, high-contrast header/nav band can “anchor” the page even without \`position: sticky\`.                                                                    |

\| 42 | \*\*\`flex-direction\` sets the main axis\*\*         | \`row\` (default) = main axis horizontal; \`column\` = main axis vertical. Also \`row-reverse\` and \`column-reverse\`. Changing direction swaps what justify vs align control. |

\| 43 | \*\*\`:hover\` — pointer is over the element\*\*      | Styles the “pointer over me” state. Keep contrast (rule 2); don’t hide essential info only behind hover (touch).                                                  |

\| 44 | \*\*\`:focus\` — element currently has focus\*\*       | Styles inputs, buttons, and links while focused. Keep focus obvious for accessibility. Later, learn \`:focus-visible\` for keyboard-focused UI states. Never use bare \`outline: none\` (or \`outline: 0\`) without a visible replacement in the same ruleset. |

\| 45 | \*\*\`:active\` — element is being pressed\*\*        | Applies during the click/press. Often a slightly darker or tighter look than \`:hover\`.                                                                          |

\| 46 | \*\*\`:visited\` — link already opened\*\*            | Styles \`a\` links the user has visited. Browsers limit what you can change (often mainly \`color\`) for privacy.                                                   |

\| 47 | \*\*\`:first-child\` — first among siblings\*\*       | Targets the first child element in a parent (e.g. first \`li\` in a list).                                                                                        |

\| 48 | \*\*\`:nth-child(...)\` — child by pattern\*\*        | Picks children by number or pattern, e.g. \`:nth-child(odd)\` / \`:nth-child(even)\` for zebra rows, or \`:nth-child(3)\` for the third.                              |

\| 49 | \*\*Specificity decides which selector wins\*\*        | When multiple CSS rules target the same property on the same element, the selector with higher specificity usually wins. Think roughly: inline styles > IDs > classes/attributes/pseudo-classes > element selectors. |

\| 50 | \*\*Later rules win when specificity ties\*\*           | If two competing rules have the same specificity and both apply, the rule that appears later in the stylesheet wins. |

\| 51 | \*\*Avoid overly specific selectors\*\*                 | Prefer simple reusable classes over long selector chains or IDs for styling. High specificity makes later overrides harder. \`\:is()\` can shorten lists, but its specificity is that of its most specific argument. |

\| 52 | \*\*Group selectors to share styles\*\*                 | Separate selectors with commas when they need the same declarations, e.g. \`h1, h2, h3 { font-family: Georgia, serif; }\`. Prefer \`\:is(h1, h2, h3)\` when nesting or repeating the same list. |

\| 53 | \*\*Group related content semantically\*\*              | Use meaningful containers such as \`section\`, \`article\`, \`header\`, \`nav\`, \`main\`, and \`footer\` when they describe the content. Use \`div\` when no semantic element fits. |

\| 54 | \*\*Understand the complete box model\*\*                | Every element is built from the inside out: \*\*content → padding → border → margin\*\*. With the default \`content-box\`, declared \`width\` and \`height\` apply only to the content. |

\| 55 | \*\*Prefer \`box-sizing: border-box\` for predictable sizing\*\* | With \`border-box\`, declared \`width\` and \`height\` include content, padding, and border. Margin always remains outside the declared size. |

\| 56 | \*\*Combine \`width\` with \`min-width\` and \`max-width\`\*\* | \`width\` proposes a size, while \`min-width\` and \`max-width\` set lower and upper limits. A common responsive pattern is \`width: 100%; max-width: 960px;\`. Use \`min-width\` carefully because it can force horizontal overflow. |

\| 57 | \*\*Prefer flexible height constraints\*\*               | Use \`min-height\` when a box needs a minimum size but may grow with content. Use \`max-height\` only when you have decided what excess content should do; a fixed \`height\` can clip or overflow changing content. |

\| 58 | \*\*Choose CSS units by what should control the size\*\* | Use \`px\` for deliberate fixed details, \`%\` for a containing block, \`rem\` for root-relative sizing, \`em\` for component-relative sizing, and viewport units when the viewport should control the result. |

\| 59 | \*\*Choose overflow behavior deliberately\*\*            | \`visible\` is the default; \`hidden\` clips; \`auto\` adds scrolling only when needed; \`scroll\` reserves scrolling behavior even when content fits. Prefer \`auto\` for content users must still reach. |

\| 60 | \*\*Element selectors target a tag name\*\*                | A selector such as \`h2\` matches every \`h2\` element. Use it for broad defaults that should apply to every instance of an element. |

\| 61 | \*\*Class selectors create reusable styles\*\*             | A selector such as \`.card\` matches every element with \`class="card"\`. Prefer classes for reusable component and utility styles. |

\| 62 | \*\*Descendant selectors use ancestry\*\*                  | A selector such as \`.card img\` matches every \`img\` anywhere inside an element with class \`card\`. Keep descendant selectors short so they remain easy to override. |

\| 63 | \*\*Attribute selectors match attributes\*\*               | A selector such as \`input[type="email"]\` matches inputs whose \`type\` is \`email\`. They are especially useful for distinguishing form controls. |

\| 64 | \*\*Commas group selectors\*\*                            | A selector list such as \`h1, h2, h3\` applies one declaration block to every listed selector and avoids duplicated CSS. \`\:is()\` groups the same way inside a larger selector (e.g. \`nav \:is(a, button):hover\`). |

\| 65 | \*\*\`static\` keeps normal flow\*\*                       | \`position: static\` is the default. The element stays in normal flow, and offset properties do not move it. |

\| 66 | \*\*\`relative\` preserves layout space\*\*                 | A relatively positioned element keeps its original place in normal flow, while offsets move only its rendered box. It can also establish the containing block for absolute descendants. |

\| 67 | \*\*\`absolute\` leaves normal flow\*\*                     | An absolutely positioned element no longer reserves layout space. It uses the nearest positioned ancestor as its containing block, or an initial containing block when none exists. |

\| 68 | \*\*\`fixed\` follows the viewport\*\*                      | A fixed element normally stays at the same viewport location while the document scrolls. Reserve space and test zoom so it does not hide content or controls. |

\| 69 | \*\*\`sticky\` needs a threshold\*\*                        | A sticky element participates in normal flow until scrolling reaches an offset such as \`top: 0\`. Ancestor overflow and available scroll space affect whether it sticks. |

\| 70 | \*\*\`z-index\` controls intentional overlap\*\*            | Positioned or layered elements with a larger z-index appear above lower layers within the same stacking context. Prefer a small documented scale instead of arbitrary huge values. |

\| 71 | \*\*Stacking contexts contain z-index\*\*                   | A child cannot use a large z-index to escape its ancestor’s stacking context. Compare ancestors when a z-index seems ineffective. Use \`isolation: isolate\` on a section root to create a local stacking context without changing layout. |

\| 72 | \*\*Use one primary \`main\`\*\*                            | Put the page’s unique primary content in one visible \`main\`. Repeated site navigation, page headers, and page footers normally remain outside it. |

\| 73 | \*\*\`section\` groups a theme\*\*                          | Use \`section\` for a thematic group that normally has a heading. Do not use it as a generic styling wrapper. |

\| 74 | \*\*\`article\` stands independently\*\*                    | Use \`article\` for content that can make sense on its own or be reused, such as a post, product card, review, or news item. |

\| 75 | \*\*\`nav\` identifies major navigation\*\*                 | Wrap major navigation link groups in \`nav\`. Label multiple navigation regions so users can distinguish them. |

\| 76 | \*\*\`header\` and \`footer\` follow their scope\*\*         | At page level they introduce or conclude the document; inside a section or article they introduce or conclude that nearest piece of content. |

\| 77 | \*\*\`aside\` is complementary\*\*                          | Use \`aside\` for related but nonessential content. Visual placement in a sidebar does not by itself make content an aside. |

\| 78 | \*\*Use \`figure\` for a referenced unit\*\*                 | Group media with its caption in \`figure\` and \`figcaption\` when they form one self-contained unit referenced by the surrounding content. |

\| 79 | \*\*Prefer native meaning over redundant ARIA\*\*           | Choose the correct HTML element first. Do not add a role that merely repeats the element’s built-in semantics. |

\| 80 | \*\*Keep headings logical\*\*                              | Use headings to describe the document hierarchy, not to obtain a particular font size. Keep one \`\<h1>\` per page, never skip levels (e.g. \`h2\` → \`h4\`), and use paragraphs for ordinary body copy. |

\### Semantic HTML

Semantic HTML communicates what content means and how regions relate. It does
not prescribe a visual design; CSS can restyle semantic elements without
removing their meaning.

Use this decision order:

| Content relationship | Element |
| --- | --- |
| Unique primary page content | `main` |
| Thematic group with a heading | `section` |
| Independently meaningful or reusable item | `article` |
| Major navigation link group | `nav` |
| Introductory content for a page, section, or article | `header` |
| Closing metadata for a page, section, or article | `footer` |
| Complementary content | `aside` |
| Media and caption that form one unit | `figure` + `figcaption` |
| No accurate semantic relationship | `div` |

A page should normally have one visible `main`. A `section` usually needs a
heading, while an `article` should still make sense when separated from the
surrounding page. Headers and footers are scoped by where they are nested.

Use **one** `<h1>` for the page’s primary title. Nest headings without skipping
levels — an `h2` is followed by `h3`, not `h4`. Skipping (for example `h2` →
`h4`) treats heading level as a font-size shortcut and breaks the outline
assistive technology exposes.

Multiple navigation regions need distinct accessible names:

```html
<nav aria-label="Primary navigation">...</nav>
<nav aria-label="Related articles">...</nav>
```

Use native elements instead of duplicating their semantics:

```html
<main>...</main>
```

Do not write `<div role="main">` when `main` itself is available, and do not add
`role="navigation"` to `nav`. ARIA is useful when native HTML cannot express the
needed name, state, or relationship; it is not a replacement for choosing the
correct element.

\### Common CSS selectors

Selectors appear before the opening brace of a CSS rule and decide which HTML
elements receive its declarations. Start with these common forms:

| Selector type | Example | What it matches |
| --- | --- | --- |
| Element | `h2` | Every `h2` element |
| Class | `.card` | Every element with `class="card"` |
| Descendant | `.card img` | Every `img` inside `.card` |
| Attribute | `input[type="email"]` | Email inputs |
| Grouped | `h1, h2` | Every `h1` and every `h2` |

Prefer simple classes for reusable styles. Use descendant selectors when the
ancestor is an important part of the context, and group selectors when they
share the same declarations.

\### Positioning and stacking

Normal flow should remain the default. Position an element only when its visual
relationship cannot be expressed clearly by ordinary document flow or layout.

| Value | Flow behavior | Positioned relative to |
| --- | --- | --- |
| `static` | Remains in normal flow | Normal layout; offsets are ignored |
| `relative` | Keeps its original space | Its normal position |
| `absolute` | Leaves normal flow | Nearest positioned ancestor |
| `fixed` | Leaves normal flow | Usually the viewport |
| `sticky` | Keeps flow space, then sticks | Its scroll container and offset threshold |

Offsets (`top`, `right`, `bottom`, and `left`) describe where a positioned edge
should sit. Avoid setting opposing offsets unless the intended size behavior is
clear.

For an anchored badge, position the parent and then position the badge:

```css
.card {
  position: relative;
}

.badge {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
}
```

For sticky positioning, provide a threshold:

```css
.section-nav {
  position: sticky;
  top: 0;
  z-index: 10;
}
```

`z-index` matters only when elements can overlap, and its comparison is bounded
by stacking contexts. Start with source order, then use a small scale such as
content `0`, sticky navigation `10`, and fixed utility controls `20`. Do not use
values such as `999999` as a substitute for understanding the relevant
ancestors.

When a section contains layered decoration (absolute media, accents, floating
UI), create a local stacking context on that section root with
`isolation: isolate`. Internal `z-index` values then stay local and cannot paint
over a neighbouring section.

\### CSS specificity

Specificity is the browser's way of deciding which CSS rule should win when more than one rule tries to set the **same property** on the **same element**.

A useful beginner order is:

| Selector type | Example | Relative strength |
| --- | --- | --- |
| Element | `p` | Low |
| Class / attribute / pseudo-class | `.card`, `[type="text"]`, `:hover` | Medium |
| ID | `#hero` | High |
| Inline style | `style="color: red"` | Very high |

```css
p {
  color: black;
}

.notice {
  color: blue;
}

#warning {
  color: red;
}
```

```html
<p id="warning" class="notice">Important</p>
```

The text is red because the ID selector is more specific than the class and element selectors.

If specificity is equal, the rule written **later** wins:

```css
.card { color: blue; }
.card { color: green; } /* wins */
```

Prefer simple class-based styling. Avoid fighting specificity with very long selectors or `!important` unless you have a clear reason.

### Grouping elements and selectors

There are two related ideas worth separating:

#### Grouping HTML content

Use containers to group related content. Prefer semantic elements when they describe what the group means:

```html
<section class="services">
  <h2>Services</h2>
  <p>What we offer.</p>
</section>
```

Use `div` when you need a generic grouping box and no semantic element fits:

```html
<div class="card-actions">
  <button>Save</button>
  <button>Cancel</button>
</div>
```

Use `span` when you need to group or style part of a line without creating a new block:

```html
<p>Total: <span class="price">$99</span></p>
```

#### Grouping CSS selectors

If several selectors share the same declarations, separate them with commas:

```css
h1,
h2,
h3 {
  font-family: Georgia, serif;
}

/* Same idea with :is() when the list sits inside a larger selector */
nav :is(a, button):hover {
  color: #0e7490;
}
```

This keeps CSS DRY and prevents repeated declarations. `:is()` takes the
specificity of its **most specific** argument, so prefer simple arguments.

### Pseudo-classes

Pseudo-classes style an element in a special \*\*state\*\* or \*\*position\*\*. Write them with a colon: \`button\:hover\`, \`input\:focus\`, \`li\:first-child\`.

Style the \*\*default\*\* rule first, then add pseudo-class overrides. Live demos: \`pseudo-classes/\`.

\#### Interaction states

\| Pseudo-class | When it applies | Typical use |

\| ------------ | --------------- | ----------- |

\| \`:hover\` | Pointer is over the element | Buttons, links, cards |

\| \`:focus\` | Element is focused (Tab / click into field) | Inputs, buttons, links — visible focus for a11y |

\| \`:active\` | Element is being pressed | Brief “pressed” look on buttons |

\| \`:visited\` | Link has been visited | \`a\` color after the user opens it |

\`\`\`css

button {

  background: #0e7490;

  color: #ecfeff;

}

button\:hover {

  background: #155e75;

}

button\:active {

  background: #0f766e;

}

input\:focus {

  border: 2px solid #0e7490;

  background: #ecfeff;

}

a\:visited {

  color: #6b21a8; */\* browsers may restrict other properties \*/*

}

\`\`\`

Tips:

\- You can change more than color: \*\*background\*\*, \*\*background-image\*\*, \*\*font-size\*\*, \*\*padding\*\*, \*\*border\*\*, even \*\*which text shows\*\* (two \`span\`s, toggle with \`display\`)

\- Hover/focus/active text and backgrounds must still meet contrast (rule 2)

\- Never hide critical content only behind \`:hover\`

\- \`:focus\` matters for keyboard users — don’t remove focus styles without a clear replacement

\- Never use bare \`outline: none\` or \`outline: 0\`. If you restyle focus, put the replacement outline (or equivalent ring) in the same ruleset as the removal

\- Live demos in \`pseudo-classes/\` show size, image, and label swaps — not only color

\`\`\`css

*/\* Font grows on hover \*/*

.grow\:hover {

  font-size: 20px;

}

*/\* Background image swaps on hover \*/*

.photo-card\:hover {

  background: url("other.jpg") center center no-repeat;

  background-size: cover;

}

*/\* Swap visible text with two spans \*/*

.btn .alt {

  display: none;

}

.btn\:hover .main {

  display: none;

}

.btn\:hover .alt {

  display: inline;

}

\`\`\`

\#### Structural (position among siblings)

\| Pseudo-class | When it applies | Typical use |

\| ------------ | --------------- | ----------- |

\| \`:first-child\` | Element is the first child of its parent | Emphasize the first list item or card |

\| \`:nth-child(odd)\` / \`:nth-child(even)\` | Odd or even children | Zebra-stripe rows |

\| \`:nth-child(3)\` | The 3rd child | Spot-target one item |

\`\`\`css

.list li\:first-child {

  font-weight: 700;

}

.list li\:nth-child(odd) {

  background: #f8fafc;

}

.list li\:nth-child(even) {

  background: #dceaf7;

}

\`\`\`

\### Document language (\`lang\`)

Every page should open with a language on the root element:

\`\`\`html

\<!DOCTYPE html>

\<html lang="en">

\`\`\`

\- \*\*Accessibility\*\* — screen readers pick the correct voice and pronunciation for that language

\- \*\*Search / indexing\*\* — helps search engines understand the page language

\- \*\*Browser features\*\* — supports consistent language-related behavior (e.g. hyphenation, typographic defaults)

Match the code to the content (\`en\`, \`fil\`, \`ja\`, …). If a passage is in another language, you can set \`lang\` on that element too.

\### Circular photos

To make an image look round (avatars, profile shots):

1\. Set a \*\*width\*\* (and usually the same \*\*height\*\*) so the box is square

2\. Set \`border-radius: 50%\` — half of each side curves into a full circle

\`\`\`css

.avatar {

  width: 160px;

  height: 160px;

  border-radius: 50%;

}

\`\`\`

If width and height differ, \`50%\` makes an \*\*ellipse\*\*, not a perfect circle. Prefer a square box for circular photos.

\### Simple cool tricks

Handy one-liners and small patterns (live demos: \`special/tricks.html\`):

\| Trick | Recipe | Also see |

\| ----- | ------ | -------- |

\| Circular photo | Square \`width\`/\`height\` + \`border-radius: 50%\` | Rule 33 |

\| Pill button | Padding + \`border-radius: 999px\` | Rule 34 |

\| Soft card lift | \`box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15)\` | Rule 35 |

\| Full-bleed band / breakout | Full-width band, or 4-track grid with gutter breakout | Rule 36 |

\| Centered page column | \`width\` + \`margin: 0 auto\` | Rule 3 |

\| Truncate text | \`overflow: hidden; white-space: nowrap; text-overflow: ellipsis\` | Rule 37 |

\| Soft square | \`border-radius: 12px\`–\`24px\` | Rule 38 |

\| Tinted / readable photo text | Overlay \`div\` or layered \`background\` | Rule 30 |

\| Halo text | \`text-shadow: 0 0 5px black\` | Rule 31 |

\| Even icon/item row | \`display: flex\` + \`justify-content: space-between\` or \`center\` | Rules 7–8 |

\| Skip decorative images | \`alt=""\` | Rule 18 |

\| Same-size thumbnails | Fixed \`width\` and \`height\` on each \`img\` | Rule 39 |

\| Accent a word | \`\<span class="accent">…\</span>\` inside the sentence | Rule 25 |

\| Two-tone sections | Alternate background classes | Rule 40 |

\| Visual page anchor | High-contrast header/nav band | Rule 41 |

\### Flexbox

Set \*\*\`display: flex\`\*\* on a parent. Only its \*\*direct children\*\* become flex items.

\#### Main axis vs cross axis

\| \`flex-direction\`   | Main axis (→ \`justify-content\`) | Cross axis (→ \`align-items\`) |

\| ------------------ | ------------------------------- | ---------------------------- |

\| \`row\` (default)    | left → right                    | top ↕ bottom                 |

\| \`row-reverse\`      | right → left                    | top ↕ bottom                 |

\| \`column\`           | top → bottom                    | left ↔ right                 |

\| \`column-reverse\`   | bottom → top                    | left ↔ right                 |

\`\`\`css

.row {

  display: flex;

  flex-direction: row; */\* main axis horizontal \*/*

}

.stack {

  display: flex;

  flex-direction: column; */\* main axis vertical \*/*

}

\`\`\`

\#### \`justify-content\` (main axis)

\| Value            | Effect                                      |

\| ---------------- | ------------------------------------------- |

\| \`flex-start\`     | Pack toward the start of the main axis      |

\| \`flex-end\`       | Pack toward the end                         |

\| \`center\`         | Center along the main axis                  |

\| \`space-between\`  | First at start, last at end; equal gaps between |

\| \`space-around\`   | Equal space around each item (half-size at edges) |

\| \`space-evenly\`   | Equal space everywhere, including edges     |

\#### \`align-items\` (cross axis)

\| Value         | Effect                                              |

\| ------------- | --------------------------------------------------- |

\| \`stretch\`     | Items fill the cross size (default)                 |

\| \`flex-start\`  | Align to the start of the cross axis                |

\| \`flex-end\`    | Align to the end                                    |

\| \`center\`      | Center on the cross axis                            |

\| \`baseline\`    | Align text baselines                                |

To center a group both ways inside a tall/wide box:

\`\`\`css

.stage {

  display: flex;

  justify-content: center; */\* main \*/*

  align-items: center;     */\* cross \*/*

  height: 200px;

}

\`\`\`

\#### \`gap\`

\`\`\`css

.row {

  display: flex;

  gap: 16px; */\* space between items only \*/*

}

\`\`\`

\`gap\` does not add padding on the outside of the container. Live demos: \`flexbox/01-playground.html\`.

\### Overlay for background contrast

Photo heroes and posters look great with \`background-size: cover\`, but bright/busy areas can wash out text. Put a translucent layer on top of the image, then put your content on that layer.

\*\*Option A — nested overlay \`div\` (clear and easy to tune):\*\*

\`\`\`html

\<div class="hero">

  \<div class="hero-overlay">

    \<h1>Title\</h1>

  \</div>

\</div>

\`\`\`

\`\`\`css

.hero {

  background: url("photo.jpg") center center no-repeat;

  background-size: cover;

}

.hero-overlay {

  padding: 48px 24px;

  background: rgba(15, 23, 42, 0.65); */\* dark scrim \*/*

  color: #f8fafc;

}

\`\`\`

\*\*Option B — layered \`background\` (image + gradient scrim in one box):\*\*

\`\`\`css

.hero {

  background:

    linear-gradient(rgba(15, 23, 42, 0.65), rgba(15, 23, 42, 0.65)),

    url("photo.jpg") center center no-repeat;

  background-size: cover, cover;

  color: #f8fafc;

}

\`\`\`

Use a light overlay (\`rgba(255, 255, 255, 0.75)\`) when the text is dark. Re-check contrast after you pick the opacity.

\### \`text-shadow\`

\`text-shadow\` paints a shadow behind glyphs. The common form is:

\`\`\`css

text-shadow: offset-x offset-y blur-radius color;

\`\`\`

\| Part          | Meaning                                      | Example in \`0px 0px 5px black\` |

\| ------------- | -------------------------------------------- | ------------------------------ |

\| \`offset-x\`    | Horizontal shift (positive = right)          | \`0px\` (no side shift)          |

\| \`offset-y\`    | Vertical shift (positive = down)             | \`0px\` (no up/down shift)       |

\| \`blur-radius\` | How soft/wide the shadow is                  | \`5px\`                          |

\| \`color\`       | Shadow color                                 | \`black\`                        |

When \*\*background/text contrast is weak\*\* (busy photo, similar colors), zero the offsets and use a \*\*higher blur\*\* so the shadow acts like a soft halo or outline around the letters:

\`\`\`css

*/\* Soft readable glow — offsets zeroed, blur does the work \*/*

h1 {

  color: #ffffff;

  text-shadow: 0px 0px 5px black;

}

*/\* Stronger haze on a very busy image \*/*

h1 {

  text-shadow: 0 0 8px rgba(0, 0, 0, 0.9);

}

\`\`\`

Light text usually needs a \*\*dark\*\* shadow; dark text usually needs a \*\*light\*\* shadow (\`0 0 6px white\`). You can stack multiple shadows if needed. Still aim for solid contrast with an overlay when possible (rules 2 and 30).

\### \`div\` vs \`span\`

\| Tag    | Default display | Use it when…                                                                 |

\| ------ | --------------- | ---------------------------------------------------------------------------- |

\| \`div\`  | block           | You need a \*\*box/section\*\* for layout: page wrapper, card, nav group, row.   |

\| \`span\` | inline          | You need to style \*\*part of a sentence\*\* without starting a new line.        |

\`\`\`html

*\<!-- layout chunk → div -->*

\<div class="card">...\</div>

*\<!-- phrase inside text → span -->*

\<h3>Hello, \<span class="accent">Alex\</span>\</h3>

\`\`\`

\### How \`inherit\` works

Most text properties (\`color\`, \`font-family\`, \`font-size\`) already inherit. \`inherit\` \*\*forces\*\* any property to copy the parent:

\`\`\`css

body {

  color: #1a1a1a;

  font-family: "Georgia", serif;

}

*/\* Links often keep a browser-blue color — inherit pulls the parent's color \*/*

a {

  color: inherit;

}

*/\* Non-inherited properties can also inherit if you ask \*/*

.child {

  background: inherit; */\* same background as parent \*/*

}

\`\`\`

Set shared styles on a parent (\`body\` / \`.page\`), let children inherit, and only override when needed (rules 11–12).

\### Google Fonts

1\. Pick a font on [fonts.google.com]\(https\://fonts.google.com).

2\. Add the provided \`\<link>\` tags in \`\<head>\` (often a stylesheet link; preconnect links help too). Do **not** load fonts with CSS \`@import\` — that waits for the stylesheet first and blocks rendering longer than a \`\<link>\` in \`\<head>\`.

3\. Use the family in CSS with backups:

\`\`\`html

\<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=Outfit\:wght\@400;700&display=swap" rel="stylesheet">

\`\`\`

\`\`\`css

body {

  font-family: "Outfit", Arial, sans-serif;

}

\`\`\`

\### Local TTF / OTF fonts (1001 Fonts and similar)

1\. Download a font from [1001 Fonts]\(https\://www\.1001fonts.com) (or another licensed source). Read the license; give credit if required.

2\. Put the file in your project, e.g. \`fonts/MyFont.ttf\`.

3\. Declare it once in CSS, then use the name:

\`\`\`css

@font-face {

  font-family: "MyFont";

  src: url("./fonts/MyFont.ttf") format("truetype");

*/\* OTF example: url("./fonts/MyFont.otf") format("opentype"); \*/*

}

.hero-title {

  font-family: "MyFont", Georgia, serif;

}

\`\`\`

Multi-word family names need quotes. Always end with a generic fallback (rule 21).

\### The complete box model

Every rendered element is a set of nested boxes:

1\. \*\*Content\*\* — text, images, or child elements

2\. \*\*Padding\*\* — space between the content and border

3\. \*\*Border\*\* — the edge surrounding content and padding

4\. \*\*Margin\*\* — transparent space outside the border

The default sizing mode is \`content-box\`:

\`\`\`css

.card {

  box-sizing: content-box;

  width: 300px;

  padding: 20px;

  border: 2px solid;

}

\`\`\`

Its visible width is \`300 + 40 + 4 = 344px\`, before margins.

With \`border-box\`, the declared width includes content, padding, and border:

\`\`\`css

.card {

  box-sizing: border-box;

  width: 300px;

  padding: 20px;

  border: 2px solid;

}

\`\`\`

The visible width remains \`300px\`. Margin is always outside that width.

\#### Width constraints

\`\`\`css

.page {

  box-sizing: border-box;

  width: 100%;

  max-width: 960px;

  min-width: 280px;

  margin: 0 auto;

}

\`\`\`

\- \`width\` supplies the preferred size.

\- \`max-width\` prevents the box from becoming too wide.

\- \`min-width\` prevents it from becoming too narrow, but can cause horizontal overflow on a smaller viewport.

\#### Height constraints

\`\`\`css

.card {

  min-height: 240px;

}

\`\`\`

\`min-height\` creates a minimum while still allowing content to make the box taller. Prefer it over a fixed \`height\` for text-heavy components.

\`max-height\` limits growth, but it does not decide how excess content is handled. Content may spill out unless an appropriate \`overflow\` rule is also chosen. Do not use \`max-height\` blindly on changing text.

\### CSS units

Choose a unit based on what should control the size:

\| Unit | Relative to | Common use |

\| ---- | ----------- | ---------- |

\| \`px\` | A CSS reference pixel | Borders, small fixed details, deliberate component limits |

\| \`%\` | Usually the relevant size of the containing block | Fluid widths and proportional layouts |

\| \`rem\` | The root element’s font size | Consistent spacing and type across the page |

\| \`em\` | Font size in the element’s current context | Components that scale with their text |

\| \`vw\` | 1% of viewport width | Viewport-relative widths and display type |

\| \`vh\` | 1% of viewport height | Viewport-height sections |

\`em\` needs context: for \`font-size\`, it is based on the parent’s font size; for many other properties, it is based on the element’s computed font size. Nested \`em\` sizing can compound. \`rem\` avoids that compounding by always returning to the root.

\#### Modern viewport units

Mobile browser controls can change the visible viewport. Newer units make the intended behavior explicit:

\- \`svh\` / \`svw\` — small viewport; assumes browser controls take their largest space.

\- \`lvh\` / \`lvw\` — large viewport; assumes browser controls are retracted.

\- \`dvh\` / \`dvw\` — dynamic viewport; updates as browser controls appear and disappear.

Use \`dvh\` for a section that should follow the currently visible height. Use \`svh\` when content must fit even while browser controls are visible. Test viewport-sized layouts on mobile.

\### Overflow

Overflow occurs when content is larger than the dimensions or constraints of its box.

\| Value | Result |

\| ----- | ------ |

\| \`visible\` | Default. Content may paint outside the box. |

\| \`hidden\` | Clips content outside the box. Do not use it to hide information users need. |

\| \`auto\` | Adds scrolling only when content does not fit. Usually the safest choice for reachable content. |

\| \`scroll\` | Creates a scroll container even when content fits; scrollbars may remain visible depending on the platform. |

\`\`\`css

.panel {

  max-height: 20rem;

  overflow: auto;

}

\`\`\`

A size constraint and overflow answer different questions: the constraint defines how large the box may become; \`overflow\` defines what happens to excess content.

\### Box shorthand (margin, padding, border)

Values go \*\*clockwise\*\*, starting at the top:

\| Position | Longhand example   | In \`margin: 10px 20px 30px 40px\` |

\| -------- | ------------------ | ------------------------------- |

\| Top      | \`margin-top\`       | \`10px\`                          |

\| Right    | \`margin-right\`     | \`20px\`                          |

\| Bottom   | \`margin-bottom\`    | \`30px\`                          |

\| Left     | \`margin-left\`      | \`40px\`                          |

So these are equivalent:

\`\`\`css

margin-top: 10px;

margin-right: 20px;

margin-bottom: 30px;

margin-left: 40px;

*/\* same as \*/*

margin: 10px 20px 30px 40px;

\`\`\`

\#### Two values: \`margin: 10px 20px\`

With \*\*two\*\* values, the first is \*\*top and bottom\*\*, the second is \*\*left and right\*\*:

\| Position | Longhand         | In \`margin: 10px 20px\` |

\| -------- | ---------------- | ---------------------- |

\| Top      | \`margin-top\`     | \`10px\`                 |

\| Right    | \`margin-right\`   | \`20px\`                 |

\| Bottom   | \`margin-bottom\`  | \`10px\`                 |

\| Left     | \`margin-left\`    | \`20px\`                 |

\`\`\`css

margin-top: 10px;

margin-right: 20px;

margin-bottom: 10px;

margin-left: 20px;

*/\* same as \*/*

margin: 10px 20px;

\`\`\`

The \*\*same top → right → bottom → left\*\* order applies to:

\- \`padding\` (e.g. \`padding: 10px 20px 30px 40px\`)

\- border sides via \`border-width\`, \`border-style\`, and \`border-color\` (e.g. \`border-width: 1px 2px 3px 4px\`)

Value counts:

\- \*\*1 value\*\* — all four sides

\- \*\*2 values\*\* — top/bottom, then left/right

\- \*\*3 values\*\* — top, left/right, bottom

\- \*\*4 values\*\* — top, right, bottom, left

\### Font categories (generic families)

\| Category       | What it looks like                                                                 | Common use                          |

\| -------------- | ---------------------------------------------------------------------------------- | ----------------------------------- |

\| \`serif\`        | Letters have small decorative strokes (“feet”) at the ends of strokes.             | Body text, traditional / print feel |

\| \`sans-serif\`   | Without those feet — cleaner, more geometric letterforms.                          | UI, headings, screen reading        |

\| \`monospace\`    | Every character takes the same width (like a typewriter).                          | Code, IDs, aligned columns          |

\| \`cursive\`      | Looks like handwriting or calligraphy.                                             | Decorative accents (use sparingly)  |

Pick a named font that matches the category you want, then end the stack with that same generic category.

\### Web-safe fonts (W3Schools)

\| Font             | Generic fallback |

\| ---------------- | ---------------- |

\| Arial            | \`sans-serif\`     |

\| Verdana          | \`sans-serif\`     |

\| Tahoma           | \`sans-serif\`     |

\| Trebuchet MS     | \`sans-serif\`     |

\| Times New Roman  | \`serif\`          |

\| Georgia          | \`serif\`          |

\| Garamond         | \`serif\`          |

\| Courier New      | \`monospace\`      |

\| Brush Script MT  | \`cursive\`        |

Example: \`font-family: Arial, Helvetica, sans-serif;\`

A useful theme behind all of these: \*\*HTML describes the content and its meaning; CSS controls how that content is presented and laid out.\*\* Prefer inheritance and shared rules so you repeat less.

\### Advanced Flexbox

81. Use \`flex-wrap: wrap\` when a row should form additional lines instead of squeezing or overflowing. \`wrap-reverse\` reverses the cross-axis line direction, not the source order.
82. Treat \`flex-basis\` as an item’s starting main size before the flex algorithm distributes free space.
83. Use \`flex-grow\` to divide positive free space by relative factors; a value of \`0\` opts out of growth.
84. Use \`flex-shrink\` to resolve negative free space. Content and minimum-size constraints can limit how far an item shrinks.
85. Read the common shorthand \`flex: grow shrink basis\` in that order. For example, \`flex: 1 1 14rem\` means grow 1, shrink 1, basis 14rem.
86. Use \`align-self\` to override cross-axis alignment for one flex item. It does not move an entire flex line.
87. Use \`align-content\` only for multiple wrapped lines with spare cross-axis space. Use \`align-items\` or \`align-self\` for items within each line.
88. Keep HTML in a meaningful reading and keyboard order. \`order\` changes visual placement only and must not be used to repair poor source order.

Advanced Flexbox separates three decisions: wrapping decides whether new lines form, flexible sizing distributes main-axis space, and alignment controls items or lines on the cross axis. Visual rearrangement is optional; accessible source order is not.

\### CSS Grid

89. Use `display: grid` when rows and columns should work together as a two-dimensional layout. Grid properties apply to the container's direct children.
90. Define explicit columns with `grid-template-columns` and explicit rows with `grid-template-rows`. Grid lines are the numbered boundaries around those tracks.
91. Use `grid-column` and `grid-row` to place an item by start and end lines. A value such as `1 / span 2` starts at line 1 and covers two tracks.
92. Use `grid-template-areas` and matching `grid-area` names when a readable layout map is clearer than line numbers. Every named area must form one complete rectangle.
93. Keep source order meaningful. Grid placement changes visual position, not reading or keyboard order.
94. Use `repeat()` to express repeated track patterns without copying the same track size.
95. Use `minmax()` to give a track a useful minimum and flexible maximum, such as `minmax(14rem, 1fr)`.
96. Inside `repeat()`, `auto-fit` collapses empty repeated tracks so existing items can expand; `auto-fill` preserves the empty tracks.
97. Use `justify-items` and `align-items` to align grid items inside their own grid areas on the inline and block axes.
98. Use `justify-content` and `align-content` to align the whole track collection inside the container. They need spare space to produce a visible result.

Full-bleed **breakout** (rule 36): a page-wide grid of four columns — outer `minmax(0, 1fr)` gutters plus two inner content tracks — lets copy sit in a constrained column while an image uses `grid-area` to spill into a side gutter on wide viewports.

Grid separates track sizing, item placement, and alignment. Item alignment moves boxes inside cells; content alignment moves the track collection inside its container.

\### Responsive CSS and pseudo-elements

99. Choose media-query breakpoints where the content needs a different layout. Do not build a breakpoint list from device names.
100. Prefer a mobile-first base when practical: write a usable narrow layout first, then add `@media (min-width: ...)` or equivalent range-syntax enhancements such as `@media (width >= ...)` as space becomes available.
101. Keep media-query overrides near or after the base declarations they change so the cascade remains easy to follow.
102. Use `max-width: 100%` with `height: auto` when an image should shrink inside its container while preserving its intrinsic proportions.
103. Use `aspect-ratio` when the layout needs a predictable image slot. Pair it with an intentional width or height.
104. Use `object-fit: cover` to fill an image slot when cropping is acceptable; use `contain` when the entire image must remain visible.
105. `::before` and `::after` generate child boxes around an element's content. They need the `content` property to appear.
106. Keep essential words, instructions, status, and controls in HTML. Pseudo-element content is presentation and is not a reliable replacement for accessible document content.

Responsive design starts with content that can adapt, then adds conditional layout changes only where needed. Responsive images protect their containers; pseudo-elements add optional presentation without changing source meaning.

\### Responsive navigation without JavaScript

107. Use native `details` and `summary` for a simple disclosure menu when JavaScript is not available. The browser provides keyboard operation and exposes the open/closed state to assistive technology.
108. Give the control an accessible name. Visible `Menu` text is clearest; when the design requires an icon-only hamburger, use `aria-label="Menu"` on `summary` and keep the three lines decorative.
109. Keep navigation links in meaningful source order. At the content-driven breakpoint, hide the desktop link group and show the disclosure menu so only one navigation set is exposed at a time.
110. Treat the CSS-only pattern as progressive navigation, not a full application menu. It does not automatically close after a link is chosen or when a user clicks elsewhere; add JavaScript later only when that extra behavior is required.

```html
<details class="mobile-menu">
  <summary aria-label="Menu">
    <span class="hamburger-icon"><span></span><span></span><span></span></span>
  </summary>
  <div class="mobile-menu-panel">
    <a href="#features">Features</a>
    <a href="#pricing">Pricing</a>
  </div>
</details>
```

Use a media query to keep this disclosure hidden while the full navigation fits, then swap the two presentations when the links need more room. For an icon-only control, `list-style: none` and `summary::-webkit-details-marker { display: none; }` remove the native chevron. Every clickable target needs a hit area of at least **24×24 CSS pixels** (WCAG 2.2 Target Size Minimum); about **44×44 px** remains a comfortable touch target for primary controls. Do not use a hidden checkbox as a substitute for a button: a checkbox communicates form state rather than menu disclosure state.

\### Accessible forms

111. Give every form control a visible label. Prefer an explicit `label` whose `for` value matches the control's unique `id`.
112. Treat placeholders as examples or short hints, never as replacements for labels. Placeholder text disappears during entry and may be missed or misunderstood.
113. Choose an input `type` that matches the requested data. Appropriate types can provide suitable mobile keyboards, browser validation, and autofill behavior.
114. Give every submitted control a meaningful `name`. In ordinary form submission, successful controls without names do not contribute values.
115. Use recognized `autocomplete` tokens when a field requests familiar user information such as a name, email address, telephone number, or address.
116. Use `fieldset` and `legend` to give a shared name to related radio buttons or checkboxes that answer one question.
117. Keep detailed instructions visible. Associate separate help text with its control using `aria-describedby` when the relationship would otherwise be unclear.
118. Prefer native constraints such as `required`, `minlength`, `maxlength`, `min`, and `max` before recreating those meanings with ARIA.
119. Identify required fields and errors in text, not through colour alone. A coloured border can support a message but cannot replace it.
120. Give every `button` an explicit `type`: `submit` sends the form, `reset` restores initial values, and `button` has no default submission action.
121. Preserve a logical source and keyboard order, and keep focus indicators clearly visible on every interactive control.
122. Use native inputs, selects, textareas, and buttons instead of rebuilding their behavior with generic elements and ARIA.

```html
<form method="get">
  <label for="email">Email address</label>
  <input id="email" name="email" type="email" autocomplete="email" required>

  <label for="topic">Topic</label>
  <select id="topic" name="topic">
    <option value="accessibility">Accessibility</option>
    <option value="layout">Layout</option>
  </select>

  <label for="message">Message</label>
  <textarea id="message" name="message" aria-describedby="message-help"></textarea>
  <p id="message-help">Include the result you expected.</p>

  <button type="submit">Send</button>
</form>
```

Accessible forms start with names and relationships, not appearance. Labels
name individual controls, legends name groups, help text explains expectations,
and native elements provide keyboard behavior and semantics before CSS is added.

\### Tables and lists

123. Use `ul` when item order does not change meaning and `ol` when sequence, ranking, or count matters.
124. Put list content inside `li` elements. A nested list belongs inside the `li` that owns that subgroup.
125. Use `dl`, `dt`, and `dd` for directly associated term/description, name/value, or question/answer groups—not merely to indent content.
126. Use `table` only for data whose row and column relationships matter. Do not use tables to arrange page layout.
127. Give each data table a concise `caption` that identifies its subject or purpose.
128. Use `th` for headers and `td` for data. Visual boldness on a data cell does not create a header relationship.
129. In a simple table, add `scope="col"` to column headers and `scope="row"` to row headers.
130. Use `thead`, `tbody`, and `tfoot` when rows have those distinct purposes. Row groups organize structure but do not replace header cells.
131. Keep table source order logical and use `colspan` or `rowspan` only when a cell truly covers related columns or rows.
132. Prefer simple tables. Complex multi-level headers need an explicit, carefully tested association strategy.
133. On narrow screens, put a wide table inside a labelled `overflow: auto` wrapper. Do not turn table elements into blocks and destroy their row/column relationships.
134. Keep list markers when they communicate grouping or sequence. If presentation removes them, provide another visible treatment that preserves that meaning.

```html
<table>
  <caption>Workshop schedule</caption>
  <thead>
    <tr>
      <th scope="col">Time</th>
      <th scope="col">Topic</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">10:00</th>
      <td>Accessible tables</td>
    </tr>
  </tbody>
</table>
```

Lists describe membership, sequence, or direct associations. Tables describe
two-dimensional data relationships. Choose the structure from the content
relationship first, then style it without changing what that structure means.

\### Advanced form controls and status

135. Use `optgroup` with a meaningful `label` when select options need categories. The group label organizes choices but is not itself selectable.
136. Connect an input's `list` attribute to a datalist's `id`. Datalist options are suggestions, not restrictions; users may still enter another valid value.
137. Match specialized input types to the requested data: `search`, `url`, `date`, `number`, `file`, `range`, and `color` expose useful browser behavior but still need visible labels.
138. Use native range constraints such as `min`, `max`, and `step`, and explain required formats or limits in persistent text when browser presentation may vary.
139. Use `accept` to help users choose suitable files, not as validation. Validate file type, size, and content on the server.
140. A hidden input is not interactive and does not need a visible label, but its value is neither secret nor trustworthy. Treat submitted hidden values as untrusted input.
141. Use `output` for a calculated result, give it an accessible name, and use its `for` attribute to identify the controls contributing to that result.
142. Use `progress` for completion of a task with a known maximum. Its minimum is always zero; omit `value` only when progress is genuinely indeterminate.
143. Use `meter` for a scalar measurement within a known range, such as a score or storage level. It may define `min`, `max`, `low`, `high`, and `optimum`.
144. State important output, progress, and meter values in text. Native bars and colour changes can support the message but must not be the only way the value or meaning is communicated.

```html
<label for="topic-search">Topic</label>
<input id="topic-search" name="topic" type="search" list="topics">
<datalist id="topics">
  <option value="Accessible forms"></option>
  <option value="Semantic tables"></option>
</datalist>

<label for="course-progress">Course completion</label>
<progress id="course-progress" value="4" max="6">4 of 6</progress>
<span>4 of 6 lessons complete</span>
```

Specialized controls improve input only when their native meaning matches the
content. Preserve visible labels and instructions, expect browser interfaces to
vary, validate submitted data on the server, and repeat important visual status
as understandable text.

\### CSS motion

145. Use transitions for state changes such as hover and focus. Define the base state and changed state, then add a duration greater than zero.
146. Name each property that should transition instead of using `transition: all`; explicit properties prevent unrelated future changes from animating.
147. Give pointer and keyboard users equivalent feedback. If hover and focus represent the same action, style both `:hover` and `:focus-visible`. A visible focus indicator must meet WCAG 2.2 Focus Appearance: at least **3:1** contrast against adjacent colours and at least a **2px** thick perimeter (or equivalent area). Never remove the outline with bare `outline: none` / `outline: 0` unless the same ruleset supplies that replacement.
148. `translate()`, `scale()`, and `rotate()` change the rendered box without changing the space it reserves in normal flow. Leave room when transformed content could overlap its surroundings.
149. Transform functions share one `transform` value and are applied in sequence. Changing their order can change the final result.
150. `transform-origin` sets the point around which scaling and rotation occur; its default is the element's centre.
151. Use `@keyframes` when motion needs intermediate stages or runs independently of a state change. Attach the keyframes with `animation-name` and a duration.
152. Animation properties control timing, delay, repetition, direction, and fill behavior. Prefer a finite animation and add only the controls the effect needs.
153. Prefer animating `transform` and `opacity` when practical because they usually avoid repeated layout work.
154. Keep motion brief and purposeful, never make it the only carrier of meaning, and use `@media (prefers-reduced-motion: reduce)` to remove or reduce nonessential movement.

```css
.button {
  transition: background-color 200ms ease, transform 200ms ease;
}

.button:hover,
.button:focus-visible {
  background-color: #174f52;
  transform: translateY(-0.125rem);
}

@keyframes arrive {
  from {
    opacity: 0;
    transform: translateY(1rem);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .button {
    transition-duration: 0.01ms;
  }
}
```

Transitions connect known states; transforms change rendered geometry; and
keyframes describe multi-step animation. Motion should support an interface's
meaning without becoming necessary to perceive or operate it.

\### CSS variables and colour themes

155. A CSS custom property begins with two hyphens, such as `--color-brand`. The declaration stores a value but does not apply that value to a visual property by itself.
156. Use semantic names that describe a role, such as `--color-surface`, `--color-text`, and `--color-border`. Names such as `--blue` become misleading when a palette changes.
157. Declare document-wide values on `:root`, then read them with `var(--property-name)` wherever that colour role is needed.
158. Custom properties participate in the cascade and normally inherit. A declaration on a nearer ancestor can override a value from `:root` for that ancestor and its descendants.
159. Override related colour roles together on a theme or component container. Changing only one side of a text/background pair can create unreadable contrast.
160. Add a fallback with `var(--property-name, fallback)` when a missing or invalid custom property would otherwise make the whole declaration invalid.
161. A fallback is not a contrast check. The browser does not use the fallback merely because a valid custom property contains a poorly chosen colour.
162. Extract values that repeat or represent a clear design role. A custom property for every one-off literal adds indirection without making the stylesheet easier to maintain.

```css
:root {
  --color-surface: #ffffff;
  --color-text: #1f2933;
  --color-brand: #176b73;
  --color-on-brand: #ffffff;
}

.card {
  background: var(--color-surface);
  color: var(--color-text);
}

.card-featured {
  --color-surface: #0d4f56;
  --color-text: #ffffff;
}

.button {
  background: var(--button-background, var(--color-brand));
  color: var(--button-text, var(--color-on-brand));
}
```

The root palette supplies shared defaults. The featured card overrides values
only within its scope, while the button keeps readable defaults if its optional
component variables are absent. Re-check contrast and visible interaction states
for every palette; variables reduce repetition but do not guarantee accessibility.

\### Clip-path

163. Use `clip-path` to hide parts of an element's paint with a geometric shape. The layout box (space the element occupies) does not shrink to match the visible silhouette.
164. Start with basic shapes: `circle(...)`, `ellipse(...)`, `inset(...)`, and `polygon(...)`. Leave SVG `path()` and `url(#id)` clips for later work.
165. Percentages in shape arguments are relative to the clipped element's own box.
166. Keep required text, controls, and instructions inside the visible region. Content clipped away is hard or impossible to perceive.
167. When clipping a photograph, keep a meaningful `alt` on the `img`. The clip is presentation; the image meaning stays in HTML.

\### Glassmorphism

168. Glassmorphism is a CSS presentation technique. Ordinary glass panels do not require JavaScript; add JavaScript only when blur or opacity must react dynamically to scrolling, pointer movement, or application state.
169. Use a translucent `background` so detail behind the panel can remain partly visible.
170. Use `backdrop-filter: blur(...)` to blur content behind a panel. `filter: blur(...)` instead blurs the element itself and is not a substitute.
171. Include `-webkit-backdrop-filter` with the same value for WebKit/Safari compatibility.
172. Give glass a subtle translucent border, rounded corners, and a restrained shadow so its edge remains visible.
173. Put visible colour, imagery, gradients, or shapes behind the glass. A blur over a flat, featureless background may be technically active but visually imperceptible.
174. Text contrast requirements still apply: at least 4.5:1 for normal text and 3:1 for large text. Increase the panel opacity or use a darker surface when the background makes content difficult to read.

```css
body {
  background:
    radial-gradient(circle at 20% 20%, #7657ff, transparent 24rem),
    #080b18;
}

.glass {
  background: rgba(8, 11, 24, 0.65);
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 1rem;
  box-shadow: 0 0.5rem 2rem rgba(0, 0, 0, 0.2);
  color: #ffffff;
  backdrop-filter: blur(0.75rem);
  -webkit-backdrop-filter: blur(0.75rem);
}
```

The recipe is translucent background + backdrop blur + subtle edge + sufficient
contrast. The Prism combined project demonstrates the treatment without
JavaScript in `combine/16-prism-landing.html`.

\### Admin UI and form presentation

175. An admin dashboard shell usually separates a sidebar (or top navigation), a topbar with page title and actions, and a main canvas for content.
176. Prefer a muted page background with white (or tokenized) surfaces for cards and forms so work areas read as raised planes.
177. Choose one elevation system per product UI: border-only cards, soft shadow without a border, or a hairline border plus a soft shadow. Mixing all three on one screen usually looks inconsistent.
178. Structure cards with optional header, body, and footer slots. Place overflow actions in the header rather than scattering them through the body.
179. A metric card typically includes a label, a large value, and a trend line or pill. Communicate increase or decrease with text as well as colour.
180. An icon well is a fixed square with a soft radius and tinted background beside a metric label. Mark decorative icons with `aria-hidden="true"` when the label already names the metric.
181. An operational status strip (counts awaiting action) sits above the KPI row and is not a substitute for metric cards.
182. Muted secondary text (dates, “vs last month”) uses lower emphasis than body copy while remaining readable against its background.
183. Keep a radius scale: tighter radii on controls, larger radii on cards, and pill radii only for capsules and trend chips.
184. An input group is a flex row that joins addons and a field behind one continuous border. Round only the outer corners of the group.
185. Input-group addons are supplementary. Keep a visible field label (or group name) and connect helpful addon text with `aria-describedby` when needed.
186. Soft admin fields often use a thin border, comfortable height (about 2.5rem–2.75rem), and a focus ring from `outline` or from `box-shadow`. Never remove every visible focus style.
187. Size modifiers (small, default, large) should change padding, font size, and height together rather than only the corner radius.
188. Disabled and readonly fields change background and border together. Do not rely on opacity alone when the value must stay readable.
189. Form layouts include stacked fields, horizontal label/field pairs that stack on narrow viewports, multi-column grids, and compact inline toolbars.
190. A switch presentation is still a native checkbox with a visible label. Style the control with CSS; do not rebuild toggle behaviour with empty elements in the HTML/CSS workbook.
191. Floating labels still use a real `label` element. Placeholders remain examples, not names.
192. Validation presentation pairs a border or ring change with persistent text. Do not communicate errors by colour alone.
193. Dropzone chrome is presentation around a real `input type="file"`. The `accept` attribute suggests types; servers must still validate uploads.
194. Star ratings in CSS lessons are radio groups with styled labels so keyboard and assistive technology still work.
195. Multi-step wizard chrome can mark current and completed steps in HTML. Changing steps and validating each step belongs to JavaScript.

\### Storefront patterns

196. A storefront shell separates top navigation, optional category navigation, primary `main` content, and a site footer. Name each `nav` region.
197. Product cards are appropriate browsing units: image, title link, price, and rating or badge text. Do not wrap the whole page in nested decorative cards.
198. Filter catalogs place labelled fieldsets in an aside beside a product grid and stack the columns on narrow viewports.
199. Product detail pages compose a gallery and a buy box. Colour and size choices need visible group names; quantity needs a visible label.
200. Specification and invoice data belong in real tables with captions and headers, not in layout grids pretending to be tables.
201. Cart and checkout summaries may use sticky positioning, but the summary must remain reachable in source order for keyboard users.
202. Delivery and payment options are radio groups (or native selects) with helper text. Do not rely on card chrome alone to name the choice.
203. Account hubs combine profile metrics, static tab chrome, and orders or reviews tables. Status pills use text as well as colour.
204. Print-friendly invoices hide lesson and site chrome with `@media print` while keeping address blocks and line-item tables readable.

\### Admin commerce patterns

205. Table variant classes (striped, hover, bordered, compact) change presentation only. Keep semantic table structure from Chapter 13.
206. Ops table chrome includes a toolbar, status pills, scroll wrapper, and optional row-action menus. Native `details`/`summary` can provide a static action menu without Bootstrap dropdown scripts.
207. Search fields and pagination controls may appear as non-functional chrome in CSS lessons. Wiring search, sort, and pages belongs to JavaScript Phase 9.
208. Add-product layouts use a main details column and a pricing or stock sidebar. Reuse input-group prefixes for currency and vanity URLs.
209. Shipping fulfilment choices are radio cards with short helper copy describing responsibility and cost.
210. Admin list pages sit inside the dashboard shell: sidebar, topbar actions, toolbar, data table, and pagination chrome.
211. Entity detail pages lead with identity and actions, then definition cards, then a related orders or items table.

\### Travel booking patterns

212. A travel agency shell separates named primary navigation for booking verticals (such as Hotel, Flight, and Trip), primary `main` content, and a site footer.
213. Booking search chrome uses labelled native fields for trip type, places, dates, and travelers. Do not replace those controls with third-party widgets in the HTML/CSS workbook.
214. Fare catalogs place filter fieldsets in an aside beside result rows that show airline, times, duration, stops, price, and a clear Select action.
215. Experience detail pages lead with title, price per person, and meta, then overview and itinerary content, with a sticky book box that stays reachable in source order.
216. Stay detail pages offer room cards with amenities and price notes beside a sticky stay summary; hotel compare pages use a real attribute table, not a layout grid pretending to be a table.
217. Booking checkout composes guest, house-rule, and payment fieldsets with a sticky booking summary for dates, party, fees, and total.

### Landing / hero composition patterns

Named catalog demos live under `ui/heroes/` (twenty-three patterns: fifteen
foundations plus eight Phase-2 stylistic systems). Phase-2 allow-list and
technique vocabulary live in `CSS/hero-composition/allowed.md`.

218. A motif kit is two or three reusable shapes (for example teardrop, circle,
    soft square) plus an optional faint dot-grid utility. Reuse the same shapes
    as badge, cluster, and frame instead of inventing a new silhouette per accent.
219. Text on photographic heroes still needs a translucent overlay or scrim
    between the image and the copy (rules 30–31). Treat `text-shadow` as a
    secondary aid, not the only contrast strategy.
220. Mask photos with `border-radius: 50%`, organic `clip-path`, or an SVG blob
    container so the image has a deliberate footprint. Allow a controlled
    breakout (about 10–20%) past the mask edge for depth; keep headlines and
    primary CTAs in the safe unclipped region.
221. Plan an explicit z-index stack before decorating: field → geometry → media
    → floating UI → seam-overlapping pills or cards. Without a stack recipe,
    absolute accents collide and clip unpredictably on narrow viewports.
222. Dual-tone headlines (accent colour on key words, ink on the rest) and a
    short accent rule or banner under the H1 sharpen hierarchy without adding
    extra marketing blocks.
223. Compound hero widgets—contact pills, vertical social rails, multi-field
    search hubs, and overlapping feature pills—are valid when they are the
    named pattern’s job. On ordinary landing tops that are not those patterns,
    keep the first viewport to brand, one headline, one lede, one CTA group,
    and one dominant visual.
224. Prefer soft, wide, low-opacity shadows and light blurred spheres (bokeh)
    for atmosphere. Avoid harsh multi-layer glow stacks and purple-on-white
    default themes in this workbook’s studio palette.
225. A wave or soft shape under the hero is a section exit—a transition into the
    next band—not a substitute for content hierarchy or for readable type.
226. Decorative motion and carousel autoplay must honor `prefers-reduced-motion`.
    Every catalog hero includes a responsive `.hero-nav` with a burger at or
    below `48rem`.
227. Prefer inline SVG `<path>` elements with Bézier commands (`C`, `Q`, `S`)
    when a smooth irregular wave or blob is the design idea. Use
    `border-radius` or polygon `clip-path` as simpler CSS approximations while
    learning. Generators such as [freesvgwaves.com](https://freesvgwaves.com)
    (no attribution required) and [getwaves.io](https://getwaves.io) /
    Haikei can produce pasteable inline paths; prefer local SVG over hotlinked
    assets (rule 230). Hero-field SVG waves (agency backgrounds) are distinct
    from the section-exit wave in rule 225.
228. Cutout photography places a transparent PNG/WebP (or transparent SVG) over
    a field or organic shape instead of a rectangular framed photo. Give
    meaningful subjects real `alt` text; use `alt=""` when the cutout is purely
    decorative and nearby text already carries the meaning.
229. Document the stack before decorating: field → SVG geometry → cutout/media
    → copy and UI → seam-overlapping badge. Device mockups often sit on the
    seam between a light content field and a coloured SVG wave.
230. Flat illustration heroes may use [undraw.co](https://undraw.co/) or a local
    undraw-style SVG under `ui/heroes/assets/` (rule 24). Prefer local copies
    over hotlinked CDN URLs for workbook demos.
231. Geometric motif heroes can stay CSS-first: circles, small squares, short
    bars, and rotated lines aligned to a clean grid, with an overlapping badge
    connecting copy and media columns.
232. Glossary — **Bézier path**: SVG curve via control points; **organic blob**:
    freeform filled shape behind media; **editorial collage**: photo cutouts plus
    vector doodles; **geometric motif kit**: a short reusable set of CSS shapes;
    **cutout**: background-removed subject layered on the page.


### Page layout system and naming

233. Name your page-width container. Define one reusable class with `max-width`,
    horizontal centering, and side padding (often fed by `--max` / `--max-width`).
    Compose it onto semantic elements as a second class instead of inventing a
    new max-width rule per section.
234. Prefer full-bleed backgrounds on the outer section and constrained content
    inside the shared container so band colour can run edge to edge.
235. Adopt one class-naming convention per page or component set. A useful
    default is `block__element` with optional `block--modifier` or `is-state`
    classes. Nested chains such as `nav__menu__btn` appear in the wild but are
    not strict BEM — prefer flatter element names while learning.
236. Do not mix flat kebab names, `block__element`, and kebab-block `__` element
    styles inside the same component without a deliberate reason.
237. After colour tokens (rules 155–162), you may store spacing, sizing, radius,
    breakpoint documentation values, and motion timing as custom properties.
    Prefer a small role-based scale. See Chapter 24 and `ui/navbars` tokens.
238. Inline `style="--name: value"` may pass per-instance data from HTML into
    CSS (for example animating a bar to `width: var(--progress)`). Prefer that
    data channel over rewriting selectors for every numeric instance; still avoid
    inline styles for ordinary colours and spacing.

### Document metadata, performance, and UX laws

239. Ship a unique `<title>`, `<meta name="description">`, favicon
    (`rel="icon"`), and Open Graph / Twitter card tags on pages meant for the
    public web. Add `rel="canonical"` when URL variants or mirrors exist.
240. Aim for Core Web Vitals budgets: **INP ≤ 200 ms** (p75), **LCP ≤ 2.5 s**,
    **CLS ≤ 0.1**. Long tasks over **50 ms** harm INP — keep handlers short or
    yield. Intrinsic `width`/`height` on images (already taught) protect CLS.
    Keep shipped JS toward **≤ 300–400 KB gzipped** for interactive pages; this
    workbook stays far under that by design (no framework/bundler required).
241. Prefer WebP/AVIF where practical, responsive `srcset`/`sizes` or
    `<picture>`, and `loading="lazy"` on below-the-fold images. Keep the LCP
    image eager.
242. **Consistent Help (WCAG 2.2 SC 3.2.6):** if the site offers help (docs,
    contact, chat), present that mechanism in the **same relative order** on
    every page that includes it.
243. **Miller's Law:** keep a primary navigation group near **~7 items**
    (about 5 minimum comfort, **9 absolute max**). Chunk denser menus into
    labelled groups rather than one flat list of dozens.
244. Honour `prefers-color-scheme` by overriding role tokens inside
    `@media (prefers-color-scheme: dark)` (and light if needed). Re-check
    contrast after each palette. A JS theme switcher is optional later — the
    media query is enough for system preference.
245. Use **container queries** for component layout: set
    `container-type: inline-size` on the parent, then `@container` width rules
    on descendants. Keep viewport `@media` for page chrome.

### Container queries

246. Name a container with `container-name` (or the `container` shorthand) when
    more than one containment context nests on the page.
247. Default the component to a usable narrow layout; enhance inside
    `@container` when the parent is wide enough — same mobile-first habit as
    Chapter 11, scoped to the component.

### UX laws (implementable vocabulary)

248. **Fitts' Law:** make primary targets large enough and spaced — the UX
    rationale behind the ≥24×24 px floor (comfortable ≈44×44 px).
249. **Law of Proximity:** use `gap` and margin rhythm so related controls and
    copy sit closer to each other than to unrelated neighbours.
250. **Law of Common Region:** shared background, border, or `fieldset` marks
    a group; do not rely on proximity alone when the region must be obvious.
251. **Von Restorff (isolation) effect:** break visual uniformity for the one
    primary CTA — weight, colour, or size — so it is not one peer among many
    equal buttons.
252. **Serial Position Effect:** put the most important items first and last in
    nav lists, step flows, and option groups; middling items are easier to miss.
253. **Jakob's Law:** prefer familiar patterns for carts, menus, forms, and
    auth — match common affordances unless a clear product reason says otherwise.
254. **Goal-Gradient / Zeigarnik:** show progress (steps, meters, or status
    text) in multi-step flows so unfinished work stays visible and motivating.
