---
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"
---

<objective>
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.
</objective>

<execution_context>
@/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
</execution_context>

<context>
@/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
</context>

<tasks>

<task type="auto">
  <name>Task 1: Tablo detail header and metadata CSS</name>
  <files>go-backend/internal/web/ui/app.css</files>
  <read_first>
    - 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)
  </read_first>
  <action>
    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.
  </action>
  <verify>
    <automated>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</automated>
  </verify>
  <done>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)".</done>
</task>

<task type="auto">
  <name>Task 2: Kanban board, task card, etapes section, files table, and task-list gap CSS</name>
  <files>go-backend/internal/web/ui/app.css</files>
  <read_first>
    - 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)
  </read_first>
  <action>
    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
  </action>
  <verify>
    <automated>grep "background: var(--color-brand-primary)" /Users/arthur.belleville/Documents/perso/projects/xtablo-source/go-backend/internal/web/ui/app.css</automated>
  </verify>
  <done>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.</done>
</task>

</tasks>

<threat_model>
## 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 |
</threat_model>

<verification>
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)
</verification>

<success_criteria>
- 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)
</success_criteria>

<output>
Create `.planning/phases/20-tablo-detail-kanban-restyle/20-03-SUMMARY.md` when done.
</output>
