# OpenSpec Spec: UI Polish Round — Config Sections, Home Paddings, Project Repos

## Change
`ui-polish-round-config-sections-home-projects`

## Parent Proposal
`openspec/proposals/ui-polish-round-config-sections-home-projects.md`

## Status
spec

---

## 1. Scope

This spec covers three UI polish fixes:

1. **Unify config sections** across Tool Workshop and Config Profiles.
2. **Restore paddings** on the Home page cards.
3. **Improve project repository layout** in the expandable project card.

---

## 2. Shared Config Section

### 2.1 New CSS classes

Add to `apps/web/src/styles/global.css`:

```css
.config-section {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-4);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}

.config-section-title {
  margin: 0 0 var(--space-1);
  font-size: var(--font-size-base);
  font-weight: 600;
  line-height: var(--line-height-tight);
  color: var(--ink);
}

.config-section-subtitle {
  margin: calc(var(--space-1) * -1) 0 var(--space-2);
  font-size: var(--font-size-sm);
  color: var(--muted);
  line-height: var(--line-height-normal);
}

.config-section > .config-section-title + .config-section-subtitle {
  margin-top: calc(var(--space-2) * -1);
}
```

### 2.2 Tool Workshop migration

In `apps/web/src/components/features/tool/manifest-editor.tsx`:

- Replace every occurrence of:
  ```tsx
  <div className="card-md stack stack-md">
    <h4 className="m-0">Title</h4>
    ...
  </div>
  ```
  with:
  ```tsx
  <section className="config-section">
    <h4 className="config-section-title">Title</h4>
    ...
  </section>
  ```

- Keep `.card-md` on the preview block if it is not a config section.

### 2.3 Config Profiles migration

In `apps/web/src/components/features/config-profiles/ConfigProfileEditorPanel.tsx`:

- Replace every occurrence of:
  ```tsx
  <div className="form-section">
    <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: "0.75rem" }}>
      <h4 style={{ margin: 0 }}>Title</h4>
      ...
    </div>
    ...
  </div>
  ```
  with:
  ```tsx
  <section className="config-section">
    <div className="config-section-header">
      <div>
        <h4 className="config-section-title">Title</h4>
        {subtitle && <p className="config-section-subtitle">{subtitle}</p>}
      </div>
      ...actions...
    </div>
    ...
  </section>
  ```

- Add `.config-section-header` CSS:
  ```css
  .config-section-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-3);
    margin-bottom: var(--space-2);
  }

  .config-section-header .config-section-title {
    margin-bottom: 0;
  }
  ```

### 2.4 Backward compatibility

Keep `.form-section` defined as an alias so existing consumers outside Config Profiles are not broken.

---

## 3. Home Page Padding

### 3.1 Target classes

In `apps/web/src/styles/global.css`:

```css
.home-hero {
  padding: var(--space-4);
}

.home-summary-card {
  padding: var(--space-4);
}

.home-section {
  padding: var(--space-4);
}
```

If `.home-hero` already has padding from a previous rule, override/ensure it uses `--space-4`.

### 3.2 Mobile adjustments

At `max-width: 767px`, reduce padding to `--space-3`:

```css
@media (max-width: 767px) {
  .home-hero,
  .home-summary-card,
  .home-section {
    padding: var(--space-3);
  }
}
```

---

## 4. Project Repository Layout

### 4.1 Component markup

In `apps/web/src/components/features/project/ProjectCard.tsx`:

Change the expanded detail block from:

```tsx
{expanded && (
  <div className="project-detail">
    {(project.repositories || []).length === 0 ? (
      <p className="muted">No repositories yet.</p>
    ) : (
      <div className="repo-list">...</div>
    )}
    {onAddRepository && (
      <div className="project-add-repo">...</div>
    )}
  </div>
)}
```

to:

```tsx
{expanded && (
  <div className="project-detail">
    <section className="project-repos">
      <div className="project-repos-header">
        <div>
          <h4 className="config-section-title">Repositories</h4>
          <p className="config-section-subtitle">
            {project.repositories?.length ?? 0} repo
            {(project.repositories?.length ?? 0) !== 1 ? "s" : ""}
          </p>
        </div>
        {onAddRepository && (
          <button
            className="btn btn-sm btn-secondary"
            onClick={onAddRepository}
            type="button"
          >
            <Icon name="add" size="sm" /> Add Repository
          </button>
        )}
      </div>

      {(project.repositories || []).length === 0 ? (
        <p className="muted">No repositories yet.</p>
      ) : (
        <div className="repo-list">
          {(project.repositories || []).map((repo) => (
            <div key={repo.id} className="card card-md repo-block">
              ...
            </div>
          ))}
        </div>
      )}
    </section>
  </div>
)}
```

Remove the old `.project-add-repo` block.

### 4.2 CSS changes

In `apps/web/src/styles/pages/projects.css`:

```css
.project-detail {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border);
}

.project-repos {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.project-repos-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
}

.project-repos-header .config-section-title {
  margin-bottom: 0;
}

.repo-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.repo-block {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  background: var(--bg);
}

.repo-block,
.repo-block.card-md {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}

/* Remove old .project-add-repo rules */
.project-add-repo {
  display: none;
}
```

### 4.3 Mobile

At `max-width: 767px`, stack `.project-repos-header` vertically:

```css
@media (max-width: 767px) {
  .project-repos-header {
    flex-direction: column;
    gap: var(--space-2);
  }
}
```

---

## 5. Acceptance Criteria

- [ ] `.config-section`, `.config-section-title`, `.config-section-subtitle`, `.config-section-header` exist in `global.css`.
- [ ] `manifest-editor.tsx` uses `.config-section` for its grouped blocks.
- [ ] `ConfigProfileEditorPanel.tsx` uses `.config-section` for its grouped blocks.
- [ ] `.form-section` remains as a backward-compatible alias.
- [ ] `.home-hero`, `.home-summary-card`, and `.home-section` have `--space-4` padding (desktop) and `--space-3` padding (mobile).
- [ ] `ProjectCard.tsx` shows a "Repositories" header with repo count and an "Add Repository" button in the section header.
- [ ] Repository blocks are left-aligned under the project header and fill the available width.
- [ ] Old `.project-add-repo` standalone block is removed.
- [ ] `npm run typecheck` passes.
- [ ] `npm run lint` passes.

---

## 6. Verification Plan

1. Run `cd apps/web && npm run typecheck`.
2. Run `cd apps/web && npm run lint`.
3. Open Tool Workshop → create/edit a tool type → verify section styling matches Config Profiles.
4. Open Config Profiles → verify section headers and subtitles render correctly.
5. Open Home → verify hero, summary cards, and section cards have comfortable padding.
6. Open Projects → expand a project → verify repositories are left-aligned, have a "Repositories" header with count, and the "Add Repository" button is in the header.
7. Test project card on mobile viewport.

---

## 7. Next Phase

After approval, create tasks and delegate to `sdd-apply`.
