---
phase: 20-tablo-detail-kanban-restyle
plan: 03
type: execute
wave: 2
depends_on:
- 20-01
files_modified:
- go-backend/internal/web/ui/app.css
autonomous: true
requirements:
- DETAIL-01
- TASK-01
must_haves:
truths:
- "app.css contains a .tablo-detail-header rule with flex-direction, padding, and border-bottom"
- "app.css contains a .tablo-detail-title rule with font-size 1.75rem and font-weight 600"
- "app.css contains a .tablo-metadata-row rule with display flex and gap 24px"
- "app.css contains a .tablo-kanban-board rule with display flex, gap 16px, and overflow-x auto"
- "app.css contains a .tablo-kanban-column rule with width 18rem, border-radius 0.75rem, and border"
- "app.css contains a .task-card rule with flex-direction column, border-radius 8px, and gap 8px"
- "app.css contains a .task-drag-handle rule with opacity 0 and a .task-card:hover .task-drag-handle rule with opacity 1"
- "app.css contains a .task-card-delete rule with opacity 0 at rest and visible on .task-card:hover"
- "app.css contains a .tablo-progress-bar rule with background var(--color-brand-primary) — NOT var(--project-color)"
- "app.css contains a .tablo-files-table-wrapper rule with border-radius 12px"
- "app.css .task-list rule is updated to include gap 8px and padding 8px"
- "app.css contains a .tablo-etapes-section rule and a .tablo-etape-row rule"
artifacts:
- path: "go-backend/internal/web/ui/app.css"
provides: "All tablo detail + kanban restyle + etapes section CSS rules"
contains: ".tablo-detail-header"
key_links:
- from: "go-backend/internal/web/views/tablo_detail.templ"
to: "go-backend/internal/web/ui/app.css"
via: "CSS class names applied to HTML elements"
pattern: ".tablo-kanban-board"
---
Apply all CSS changes from the UI-SPEC to app.css: new tablo detail header styles, kanban board layout, task card restyle (column-flex, hover shadow, opacity-based drag handle), progress bar fill fix, files table wrapper, etapes section, and updated task-list gap. This plan runs in parallel with Plan 02 since CSS class names are already locked in the UI-SPEC.
Purpose: Without these CSS rules, the templ components from Plan 02 render unstyled. This plan is the visual half of the restyle.
Output: Updated app.css with all new and modified CSS blocks from UI-SPEC.
@/Users/arthur.belleville/Documents/perso/projects/xtablo-source/.claude/get-shit-done/workflows/execute-plan.md
@/Users/arthur.belleville/Documents/perso/projects/xtablo-source/.claude/get-shit-done/templates/summary.md
@/Users/arthur.belleville/Documents/perso/projects/xtablo-source/.planning/phases/20-tablo-detail-kanban-restyle/20-UI-SPEC.md
@/Users/arthur.belleville/Documents/perso/projects/xtablo-source/.planning/phases/20-tablo-detail-kanban-restyle/20-RESEARCH.md
@/Users/arthur.belleville/Documents/perso/projects/xtablo-source/.claude/skills/sketch-findings-xtablo-source/SKILL.md
Task 1: Tablo detail header and metadata CSS
go-backend/internal/web/ui/app.css
- go-backend/internal/web/ui/app.css (read lines 1040-1080 — existing .project-progress-track, .project-progress-bar, .project-progress-label rules to understand context before modifying)
- go-backend/internal/web/ui/app.css (read lines 880-920 — existing .tab-nav, .tab-nav-item rules to confirm no tab changes needed)
- go-backend/internal/web/ui/base.css (read first 60 lines — confirm --color-brand-primary, --color-border-default, --color-surface-muted, --color-text-primary token names)
Edit go-backend/internal/web/ui/app.css. Append a new section at the end of the file titled "/* === Tablo Detail Page === */". Add the following CSS blocks in this order. Use exact property values from the UI-SPEC — do not approximate or simplify.
BLOCK 1: .tablo-detail-page — outer container
padding: 24px 32px;
BLOCK 2: .tablo-detail-header — header element
border-bottom: 1px solid var(--color-border-muted);
display: flex;
flex-direction: column;
gap: 0;
padding-bottom: 0;
BLOCK 3: .tablo-detail-title-row — flex row with avatar + h1
align-items: center;
display: flex;
gap: 16px;
margin-bottom: 0;
padding-bottom: 16px;
BLOCK 4: .tablo-detail-avatar — 48×48 colored circle
align-items: center;
border-radius: 12px;
color: #ffffff;
display: flex;
flex-shrink: 0;
font-size: 1rem;
font-weight: 700;
height: 48px;
justify-content: center;
width: 48px;
BLOCK 5: .tablo-detail-title — h1 tablo name
color: var(--color-text-primary);
font-size: 1.75rem;
font-weight: 600;
line-height: 1.2;
margin: 0;
BLOCK 6: .tablo-metadata-row — metadata flex row
align-items: center;
border-bottom: 1px solid var(--color-border-muted);
display: flex;
flex-wrap: wrap;
gap: 24px;
padding-block: 16px;
BLOCK 7: .tablo-meta-segment — each segment in metadata row
align-items: center;
color: var(--color-text-secondary);
display: flex;
font-size: 0.875rem;
gap: 8px;
BLOCK 8: .tablo-meta-progress — progress segment override
align-items: center;
display: flex;
gap: 8px;
BLOCK 9: .tablo-progress-bar — detail page progress bar fill (MUST use brand-primary, NOT project-color — Pitfall 5)
background: var(--color-brand-primary);
border-radius: 9999px;
height: 5px;
BLOCK 10: .tablo-tab-bar — tab navigation below header
border-bottom: 1px solid var(--color-border-muted);
display: flex;
gap: 24px;
margin-top: 0;
padding-top: 8px;
BLOCK 11: .tablo-tab-bar .tab-nav-item — override for tabs within tablo detail
font-size: 0.875rem;
padding-bottom: 12px;
Do NOT modify the existing .project-progress-bar rule (it is used by tablo cards on the list page which keep var(--project-color)). The tablo detail page uses .tablo-progress-bar (different class) to avoid the conflict.
Do NOT modify .tab-nav or .tab-nav-item globally — only scope changes to .tablo-tab-bar context if any override is needed.
grep -c "tablo-detail-header\|tablo-detail-title\|tablo-metadata-row\|tablo-progress-bar\|tablo-tab-bar" /Users/arthur.belleville/Documents/perso/projects/xtablo-source/go-backend/internal/web/ui/app.css
grep count returns 5 or more (one match per class block); .tablo-progress-bar uses var(--color-brand-primary) not var(--project-color); grep for "tablo-progress-bar" returns a rule with "background: var(--color-brand-primary)".
Task 2: Kanban board, task card, etapes section, files table, and task-list gap CSS
go-backend/internal/web/ui/app.css
- go-backend/internal/web/ui/app.css (read lines 1283-1350 — existing .task-list, .task-row, .task-body, .task-check rules; understand what to modify vs what to add)
- go-backend/internal/web/ui/app.css (read lines 1254-1268 — existing .tasks-section rule with border-radius: 1rem — do NOT change this; kanban column gets its own rule)
- go-backend/internal/web/ui/base.css (confirm --color-surface-default, --color-border-default, --color-border-strong, --color-surface-muted token names)
Edit go-backend/internal/web/ui/app.css. Continue the "/* === Tablo Detail Page === */" section from Task 1 (or append after it). Add the following blocks:
BLOCK 12: .tablo-kanban-board — flex container for the kanban columns
display: flex;
gap: 16px;
overflow-x: auto;
padding-bottom: 16px;
padding-top: 24px;
BLOCK 13: .tablo-kanban-column — each column card
background: var(--color-surface-default);
border: 1px solid var(--color-border-default);
border-radius: 0.75rem;
flex-shrink: 0;
overflow: hidden;
width: 18rem;
BLOCK 14: .tablo-kanban-column-header — column header area
align-items: center;
background: var(--color-surface-muted);
display: flex;
gap: 8px;
justify-content: space-between;
padding: 12px 16px;
BLOCK 15: .tablo-kanban-column-title — column h3 label
color: var(--color-text-primary);
font-size: 0.875rem;
font-weight: 600;
margin: 0;
BLOCK 16: .tablo-kanban-task-count — task count pill
background: var(--color-surface-default);
border: 1px solid var(--color-border-muted);
border-radius: 9999px;
color: var(--color-text-secondary);
font-size: 0.75rem;
padding: 0 8px;
BLOCK 17: .tablo-kanban-add-link — "+ Ajouter" link
color: var(--color-text-brand);
font-size: 0.875rem;
font-weight: 400;
margin-left: auto;
text-decoration: none;
BLOCK 18: .tablo-kanban-empty — empty column state
color: var(--color-text-faint);
font-size: 0.875rem;
padding: 24px 16px;
text-align: center;
BLOCK 19: .task-card — new card layout (replaces/supplements .task-row for tablo detail)
background: var(--color-surface-default);
border: 1px solid var(--color-border-default);
border-radius: 8px;
cursor: pointer;
display: flex;
flex-direction: column;
gap: 8px;
padding-block: 8px;
padding-inline: 12px;
transition: box-shadow 0.12s ease, border-color 0.12s ease;
BLOCK 20: .task-card:hover
border-color: var(--color-border-strong);
box-shadow: 0 8px 24px rgba(15, 23, 42, 0.08);
BLOCK 21: .task-card-top-row — row with drag handle, title, delete icon
align-items: flex-start;
display: flex;
gap: 6px;
BLOCK 22: .task-drag-handle — drag handle (Braille pattern)
color: var(--color-text-faint);
cursor: grab;
flex-shrink: 0;
font-size: 1rem;
opacity: 0;
transition: opacity 0.12s ease;
BLOCK 23: .task-card:hover .task-drag-handle — reveal on card hover
opacity: 1;
BLOCK 24: .task-card-title — task title text
color: var(--color-text-primary);
flex: 1;
font-size: 0.875rem;
font-weight: 400;
line-height: 1.4;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
BLOCK 25: .task-card-delete — delete icon wrapper (opacity hidden at rest)
flex-shrink: 0;
opacity: 0;
transition: opacity 0.12s ease;
BLOCK 26: .task-card:hover .task-card-delete — reveal on card hover
opacity: 1;
Now modify the EXISTING .task-list rule (around line 1283 in app.css):
Find the current rule:
.task-list {
display: flex;
flex-direction: column;
}
Change it to add gap and padding:
.task-list {
display: flex;
flex-direction: column;
gap: 8px;
padding: 8px;
}
This change affects both the global tasks page and the tablo detail page equally — gap between cards is desired everywhere.
Add etapes section CSS:
BLOCK 27: .tablo-etapes-section — etapes list below kanban board
border-top: 1px solid var(--color-border-muted);
margin-top: 24px;
padding-top: 24px;
BLOCK 28: .tablo-etapes-section h2, .tablo-etapes-section h3 — section heading
color: var(--color-text-primary);
font-size: 1rem;
font-weight: 600;
margin: 0 0 12px 0;
BLOCK 29: .tablo-etapes-section ul — list reset
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
gap: 8px;
BLOCK 30: .tablo-etape-row — each etape row
align-items: center;
background: var(--color-surface-default);
border: 1px solid var(--color-border-default);
border-radius: 8px;
display: flex;
gap: 12px;
justify-content: space-between;
padding: 10px 16px;
BLOCK 31: .tablo-etape-name — etape stage name
color: var(--color-text-primary);
font-size: 0.875rem;
font-weight: 500;
BLOCK 32: .tablo-etape-count — task count label
color: var(--color-text-secondary);
font-size: 0.75rem;
Add files table wrapper CSS:
BLOCK 33: .tablo-files-table-wrapper — wrapper for the files table
border: 1px solid var(--color-border-default);
border-radius: 12px;
overflow: hidden;
BLOCK 34: .tablo-files-table-wrapper thead tr
background: var(--color-surface-muted);
BLOCK 35: .tablo-files-table-wrapper thead th
color: var(--color-text-muted);
font-size: 0.75rem;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: uppercase;
BLOCK 36: .tablo-files-table-wrapper tbody tr
border-bottom: 1px solid var(--color-border-default);
BLOCK 37: .tablo-files-table-wrapper tbody tr:hover
background: var(--color-surface-subtle);
CRITICAL checks before saving:
- .tablo-progress-bar uses "background: var(--color-brand-primary)" — verify with grep after writing
- .task-card and .task-row are SEPARATE rules — .task-row must NOT be removed (it is used by the global tasks page)
- .tasks-section border-radius (1rem) must NOT be changed — only .tablo-kanban-column gets 0.75rem
- All opacity transitions use "0.12s ease" consistent with design system
grep "background: var(--color-brand-primary)" /Users/arthur.belleville/Documents/perso/projects/xtablo-source/go-backend/internal/web/ui/app.css
grep returns at least one line containing "background: var(--color-brand-primary)" (the .tablo-progress-bar rule); .task-card block exists with flex-direction: column; .task-drag-handle exists with opacity: 0; .task-card:hover .task-drag-handle exists with opacity: 1; .tablo-kanban-board exists with overflow-x: auto; .task-list updated to include gap: 8px; .task-row unchanged; .tablo-etapes-section and .tablo-etape-row rules present.
## Trust Boundaries
| Boundary | Description |
|----------|-------------|
| CSS cascade | New .task-card rules must not override or break .task-row rules used on global /tasks page |
## STRIDE Threat Register
| Threat ID | Category | Component | Disposition | Mitigation Plan |
|-----------|----------|-----------|-------------|-----------------|
| T-20-06 | Tampering | CSS cascade — .task-card vs .task-row collision | mitigate | .task-card is a new separate selector; .task-row selector is unchanged; they do not overlap since tablo-detail uses task-card and global tasks page uses task-row |
| T-20-SC | Tampering | npm/pip/cargo installs | accept | No package installs — CSS file edit only |
After Plan 03:
- grep for "tablo-kanban-board" in app.css returns at least one match with "overflow-x: auto"
- grep for ".tablo-progress-bar" in app.css returns a match with "background: var(--color-brand-primary)"
- grep for "tablo-progress-bar" does NOT return "var(--project-color)"
- grep for ".task-card" in app.css returns the column-flex card rule (flex-direction: column)
- grep for ".task-drag-handle" returns opacity: 0 rule
- grep for ".task-card:hover .task-drag-handle" returns opacity: 1 rule
- grep for ".task-row" still returns the original horizontal rule (not removed)
- grep for ".tasks-section" still has border-radius: 1rem (not changed to 0.75rem)
- grep for ".task-list" returns updated rule with gap: 8px
- grep for ".tablo-etapes-section" returns a CSS rule
- grep for ".tablo-etape-row" returns a CSS rule
- go build ./... still exits 0 (CSS is static — no compilation risk, but verify Go still compiles cleanly)
- Visual: tablo detail header shows tablo name in large font, metadata row, and progress bar with purple fill
- Visual: kanban columns are 18rem wide with rounded corners, muted header background
- Visual: task cards are white box with column layout, subtle border, hover shadow
- Visual: drag handle appears on card hover (opacity transition, not display toggle)
- Visual: delete icon appears on card hover
- Visual: empty columns show "Aucune tâche" centered
- Visual: etapes section renders below kanban board with stage names and task counts
- CSS regression: global /tasks kanban page still renders correctly (task-row unchanged)