# Work block 1 — Builder talent-selection workspace

Interactive HTML prototype. Design only. Nothing here was implemented in
`plutino-eps/`, and no production file was edited.

Open `index.html` for the review page (state switcher + desktop 1440 and
mobile 390 frames side by side). Open `app.html` directly to use the design
full-size in a real browser window.

| File | What it is |
| --- | --- |
| `index.html` | Review page. State strip, viewport switcher, two live frames. |
| `app.html` | The design itself. Standalone; accepts `?state=…`. |
| `styles.css` | All visual tokens and responsive rules. |
| `app.js` | Selection, ordering, filtering, and the state presets. |
| `data.js` | Real Plutino roster fixture (53 records, 39 Plutino Group). |
| `screenshots/` | PNG exports of the seven required states, desktop and mobile. |
| `screenshot-frame.html` | Utility used to capture true-390px screenshots. |

---

## 1. What changed and why

The current modal is two `<select multiple>` lists with four transfer arrows
(`>`, `>>`, `<`, `<<`), no grouping, no thumbnails, and last-name sorting. It
answers "which artists exist" badly and "what order will the client see" not at
all.

| Current | This prototype |
| --- | --- |
| Four equally prominent arrows | One primary **Add selected** action with a live count |
| Flat list, division-only grouping | Division header → primary-specialty header → A–Z names |
| Sorted by last name, emerging first | Sorted by the spec comparator: division rank → specialty rank → complete display name |
| No indication of package order | Numbered Selected list with an explicit Default / Manual order state |
| One `<` and one `<<` doing three different jobs | Three distinct, separately labelled actions: remove one, clear all, reset order |
| No thumbnails | 26px 3:4 thumbnails with a monogram fallback |
| Native multi-select (invisible on touch) | Checkbox rows, group select, shift-click ranges, live "N highlighted" counter |

---

## 2. Taxonomy and ordering — unchanged, only made visible

Everything about grouping and sorting comes from
`plutino-eps/docs/talent-taxonomy-ordering-spec-2026-08-10.md`. The prototype
does not reinterpret it.

- **Divisions** in fixed order: Beauty, Style, Production Design.
- **Primary specialties** in the configured rank per division
  (`app.js` → `SPECIALTY_ORDER`), keyed, never sorted by rendered string.
- **Within a specialty**, `Intl.Collator('en', {sensitivity:'base', numeric:true})`
  over the **complete display name** — not surname, not `emerging`, not click
  order. Tie-breakers: exact name → `source_artist_book_id` → EPS id.
- `Makeup & Hair` and `Hair & Makeup` stay separate groups. `Barbering` stays
  separate from `Hair`. `Food Styling` stays visible inside Production Design.
- Filter hashtags appear only as muted **capabilities** on the right of each
  available row (e.g. `Grooming`), never as the group. A capability that
  repeats the department is suppressed, so Anna Barseghian reads
  `Hair & Makeup` with `Grooming · Hair`, never `Makeup and Hair`.

The specialty filter chips are a good acceptance check on their own: opening
them under Beauty shows `Makeup 1 · Makeup & Hair 11 · Hair & Makeup 3 ·
Hair 3 · Manicure 3 · Barbering 1`, which matches the spec's live department
counts exactly (`screenshots/desktop-7-specialty-filters.png`).

### Fixture provenance

`data.js` was generated from `plutino-eps/storage/talents-cache.json` (synced
2026-08-09, 53 records). The cache stores the **current, incorrect**
`sub_group`, so `primary_specialty` was re-derived from each record's
artist-book slug and cross-checked against the spec — one override was needed,
Aniya Nandy, whose live URL says `hair-makeup` but whose department is
`Makeup & Hair`. The resulting counts reproduce the spec's department table
exactly (22 Beauty / 8 Style / 9 Production Design / 14 Culinary).

Culinary (Chefs, Food Experts) is in `data.js` but filtered out of the picker,
which is scoped to the brand chosen on the builder page. The same division →
specialty → A–Z structure applies to it unchanged.

---

## 3. Interaction contract

### Selecting (left pane)

- **Click a row** — toggles highlight. Checkbox and tinted row make the state
  obvious; nothing depends on a native multi-select gesture.
- **Shift-click** — range from the last clicked row, across group headers.
- **Group header** — tri-state checkbox, selects/clears that primary specialty.
- **Select all shown** — everything currently passing search + filters.
- **Double-click** — adds that one artist immediately. A shortcut, never the
  only route; the checkbox and the primary button always work.
- **Keyboard** — ↑/↓ move focus, Space highlights, Enter adds.
- Rows already in the package are struck out, labelled `Added`, and inert.

### Moving (one action)

One filled **Add N selected** button sits where the four arrows were. It is
disabled with a plain label until something is highlighted, then names the
count. There is no reverse arrow — removal lives on the artists themselves.

### The three distinct "undo" actions

These were one ambiguous `<` / `<<` pair before and are now separate, with
separate wording and separate consequences:

| Action | Where | What it does |
| --- | --- | --- |
| Remove one | `×` on each selected row | Drops that artist. Positions close the gap; relative order is untouched. |
| Clear all | Selected pane header | Asks first. Inline confirmation strip inside the pane — never a modal inside a modal — naming the count and what is discarded. |
| Reset order | Selected pane header | Ordering only. Returns `talent_order_mode` to `default` and recomputes positions. Disabled while already in default order, so it can never be mistaken for a delete. |

### Order state

The Selected pane always shows which mode the job sheet is in.

- **Default order** — grouped under division and specialty headers with running
  positions, so the sort rule is visible rather than implied.
- **Manual order** — the moment ▲/▼ is used, the pill flips to `Manual order`,
  the group headers collapse into a flat numbered list, and each row gains its
  `Division · Specialty` caption so nothing is lost. New artists append at the
  end and never reshuffle existing rows (spec rule 4).
- The footnote under the list states the active rule in words.

### Lead / hero

The star on a selected row sets the lead. It never moves anyone. When a lead is
set, the footnote spells that out — *"Lead: Duyen Huynh (position 4). The lead
supplies the email hero image only — it does not move anyone in the package."*
`screenshots/desktop-4-manual-reordering.png` deliberately shows a lead at
position 4 to prove the two facts are independent.

### Reordering without drag-and-drop

▲/▼ buttons, plus Alt+↑/↓ from the keyboard. Chosen over drag-and-drop
deliberately: it is identical on desktop and touch, works with a keyboard and a
screen reader, and never fights the scrolling list on a phone. Drag can be
added later as an enhancement on pointer-fine devices, but it must not be the
only way to reorder.

### Search and filters

Search is always visible and matches name, specialty, division, and capability
tags. Division tabs are always visible. The specialty chips — the part that made
the old modal noisy — are collapsed behind a **Specialty filters** button that
carries a count badge when any are active, so an active filter is never hidden.

---

## 4. Responsive behaviour

Both frames in `index.html` are the same file. The mobile view is a media query
at 640px, not a separate design.

- The two panes become two tabs, each carrying its own count, so the Selected
  count stays visible while browsing.
- The single move action becomes a sticky bar above the dialog footer, shown
  only on the Available tab. After adding, the view switches to Selected so the
  result is visible.
- The double-click hint is dropped on touch; it is not a touch gesture.
- Row height goes 38 → 44px, reorder and remove targets grow to ≥30px.
- Division tab labels wrap to two lines rather than scrolling horizontally.
- The dialog is full-screen; the footer is sticky.

---

## 5. Visual decisions

Follows `docs/plutino-website-style-guide.md`: cream `#efeee9`, white surface,
black, Barlow / Barlow Semi Condensed, 3:4 thumbnails, no shadows on rows, no
colour accents.

Two deliberate departures, both because this is a working tool rather than a
client-facing roster:

1. **Talent names are sentence-case Barlow at 13.5px, not uppercase display
   type.** Uppercase display names are for the package and the email. At 39
   rows in a scrolling list they cost roughly 40% more vertical space and read
   more slowly. Uppercase is kept for group headers and buttons.
2. **Destructive actions carry no colour.** The style guide bans accents
   outside black, white and cream, so Clear all relies on an explicit
   confirmation step and on naming the consequence, not on red.

---

## 6. Open questions for Arseni / Roseanna

1. **Commit model.** The prototype keeps the current two-step behaviour — the
   Selected pane is staged, and `Cancel` / `Save selection · N` commits it. The
   alternative is a live Selected pane where the footer is just `Done`. Live is
   one less concept; staged is safer because Cancel really backs out. Worth one
   sentence of confirmation before build.
2. **Should the Selected pane show the chosen book?** It is currently name +
   specialty only; book choice stays on the builder card (work block 2). If
   Roseanna wants it inside the picker, the row needs a second line.
3. **Emerging.** No live artist-book currently carries it, so no filter is
   offered. It stays a badge, never a sort key, per the spec.

## 7. Notes for whoever implements this

- Grouping and sorting must use one shared comparator server-side and
  browser-side; `app.js` → `defaultCompare` is the shape, but the ranks belong
  in a generated shared table, not duplicated in PHP and JS (this is the exact
  drift the spec calls out at `public/index.php:1434-1458` vs `5275-5306`).
- `talent_order_mode` and per-row `position` are the only new persisted fields
  the picker needs; everything else is presentation.
- The `Added` state needs the picker to know the job sheet's current selection
  at open time, which the existing `talent-picker-data` payload already
  supports.
- Nothing in the prototype writes to FileMaker or sends anything.
