The stacked split nested two scroll wells (list and detail each carried
max-height + overflow-y auto) inside the page scroll - scrollbars within
scrollbars on small screens. At <=900px both panes now flow naturally in
the one page scroll, and selecting an application swaps the list out for
the detail pane with a Back to list button (standard master-detail
collapse); selection also scrolls to the top so the detail header is in
view. Desktop keeps the two-pane split unchanged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The stacked pager read as three loose rows with 'of N' printed twice.
Queue-scoped: drop the duplicate page-size total (the Showing line
already carries it), wrap page-controls with even gaps, and slim the
page buttons so all nine nav controls (4 chevrons + up to 5 numbers)
fit the ~350px split column on one row.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The unpaged switch lived only in the bottom Per-page dropdown and went
unnoticed. The bulk bar now carries a Show all (N) / Show paged button
(hidden while rows are ticked, since the bar swaps to selection
actions); it drives the same pageSize state, so the dropdown stays in
sync. The bar wraps now - four controls no longer fit one line in the
34%-wide split column at laptop widths.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- .progress-stage-grid gets the same min-width:0 blowout guard as .grid,
and stacks to one column under 400px (two columns left ~56px for a
stage label at 320)
- mobile.test.mjs: add the new progress/requisitions routes (27 total)
- __smoke__/entry.jsx: main added the /progress route but never
registered the Progress screen in the harness map, so the smoke test
rendered h(undefined) and /progress failed on main itself
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Audited all 25 routes at 320/375/390/430/768 with browser automation.
Root cause of most overflows: grid items default min-width:auto, so one
wide intrinsic child (a select option, the 620px RBAC matrix) pushed
whole cards past the viewport.
- .grid > * / .rbac-layout > * min-width:0 (CV Import, Interviews,
Tasks, Access Control card blowouts)
- calendar: minmax(0,1fr) columns — SAT was clipped off-screen at 320
- .seg wraps (Tasks filters), .card-head wraps <=900
- sticky mobile table column: first column (identity), was nth-child(2)
- tooltips display:none until hover + .content overflow-x clip (killed
a 7px sideways wiggle from invisible tooltip boxes)
- Ask Analytics form: design-system input styling, stacks on phones
- bar/grouped-bar charts thin x labels by slot width (overlap on phones)
- Candidates sort label+select wrap as one unit
- new: mobile.test.mjs + npm run test:mobile (puppeteer-core devDep,
drives installed Chrome) — fails on sideways scroll or runtime errors
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Backend: new GET /analytics/applications-per-job/fetch (analytics.view) counting
inbox + manual-upload applications per job on the same basis as the funnel, with
zero-application open reqs included. Per-job group-bys added to Inbox_Messages,
Manual_UPLOAD_CANDIDATE; JobPosts.list_open_reqs for the zero-fill.
Frontend: Dashboard rewritten as a filterable summary (Week/Month/Quarter/Year +
department) - My Tasks, Today's Schedule and Quick Actions removed; 8 KPI tiles
(Hires and Offers Sent now shown); Applications per Job hero row-list; pipeline
card refed from /analytics/funnel so it obeys filters; Offer Book, Needs
Attention and Recent Activity cards added. ChartCard and time ranges extracted
to shared modules used by both Dashboard and Analytics.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- talent_runs.cost_usd records each run's actual charge (usageTotalUsd),
accumulated across the broadened re-run ladder (migration 018).
- GET /talent/account: live balance and cycle spend from Apify
/users/me/limits (nulls when Apify is unreachable) plus the observed
$/profile over recorded runs.
- Header shows Balance / Spent / $-per-profile chips that refresh with
every search; the run status line shows the last search's cost and the
confirm dialog estimates from the live average.
- Responsive: toolbar controls stack edge-to-edge and candidate card
footers wrap instead of clipping their buttons on phones.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- List column yields (34%, floor 280px) instead of holding 420px, so the
detail pane stays readable in the 980-1200px band.
- Detail pane is a size container: its two-column info grid collapses on
the pane own width, and long names/emails wrap instead of clipping.
- Tab strip wraps on narrow screens instead of running off-canvas.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Deploy to S3 / deploy (push) Successful in 35sDetails
- Jobs list: close/reopen action per requisition with confirm on close
- Settings: real timezone and currency option lists
- Assigned-role chip: readable color pairing on soft background
- Scrollbars: Chromium honors the styled ::-webkit-scrollbar again
(scrollbar-color now gated to Firefox), slightly wider hit area
- Topbar hamburger: hidden on desktop (specificity fix) and the drawer
closes itself when the window grows past the mobile breakpoint
- Content scroller: removed overscroll containment that killed wheel
scrolling everywhere except the scrollbar thumb
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Deploy to S3 / deploy (push) Successful in 32sDetails
The create modal collected an image but dropped it. Now POST
/job/image/upload stores it on disk keyed by the post id (uuid-validated,
5 MB / png-jpg-webp-gif, replace-on-reupload; no DB migration) and GET
/job/image/fetch serves it. The create flow uploads right after the row
exists, image failure downgrades to a toast instead of failing the create,
and Job Details renders the cover via an authorized blob fetch.
E2E-verified: upload 200, fetch 200, cover renders in Job Details.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Belleza (single-weight decorative face) read thin and informal against
the dense data UI. Headings now use Inter Tight semibold with negative
tracking; hero metrics join the display face at proper optical sizes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The 380px queue rail left .ii-main only 148px: an email-style sender
name (no break points, never truncated) painted straight over the
timestamp, and the meta chips wrapped one per line. Three changes,
verified live against the dev server:
- Sender names truncate with the full value in title="" (Inbox and
Matching, which reuses the row classes).
- Older-than-a-week list timestamps show the date only, like Outlook —
the date+time form was ~105px and the detail pane has the full
instant. .ii-main grows 148 -> 195px; both status chips fit one row.
- .ii-name gets min-width: 0 and its size joins the type scale.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Skeleton loading system: .skeleton shimmer primitives in CSS (theme-
aware via --border) plus a SkeletonRows component, adopted at the
main-content loading states of Jobs, Candidates, Inbox, Interviews,
Offers, Assessments, Tasks, Managers, Notifications. Small card-level
loading states keep their EmptyState text.
- ErrorBoundary around the route outlet, keyed by pathname: a throw in
one lazy screen shows a recoverable error state instead of blanking
the whole app; navigating away resets it.
- auth.css stops hardcoding the Belleza stack twice; both sites use
var(--font-display) so the display face has one definition.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- .g-3 grids step 3 -> 2 columns at 1200px and 2 -> 1 at 900px; they
used to jump straight to one column, wasting the whole 900-1200 band
(Managers cards, Help topics, JobBoard destinations).
- The four scattered trailing @media 640px fragments (Dashboard v2
grid, candidate page, hiring forms) merged into ONE labeled block at
the end of the file, positioned after every base rule; the paired
400px override moves with it so small-phone rules still win. The
core shell 640 block stays put so the landscape-phone height rules
keep their existing precedence.
- Every breakpoint labeled; responsive section header updated.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- New ui/PageHeader.jsx emitting the existing .page-head structure;
screens adopt it in the next two passes.
- DataTable: sortable thead extracted as DataTableHead (Candidates can
drop its verbatim copy) and an onRowClick prop with keyboard support.
- Tabs: index-based ids, aria-controls, roving tabindex, arrow-key and
Home/End navigation; TabPanel labels its panel.
- Toast root announces politely to screen readers (was silent).
- Dropdown stamps aria-expanded/aria-haspopup on every trigger.
- primitives: shared PRIORITY_CLASS (Dashboard and Tasks had identical
private copies).
- Shell: skip link to #main-content, sidebar nav labeled Primary,
clickable notification rows are real buttons now.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Type scale (--fs-2xs..--fs-3xl) and line-height tokens; the 20-size
census collapses onto 9 steps. Spacing scale (--space-1..8) plus --gap
keeping the signature 18px rhythm. Colors untouched.
- Base h1-h6 rules: bare headings used to render at UA defaults, larger
and bolder than the styled card titles beside them.
- One eyebrow-label rule replacing eleven near-identical declarations at
five sizes and five letter-spacings.
- High-traffic families retrofitted to tokens (page/card/table/form/btn/
tabs/badge/sidebar/kpi); rare bolt-on sections left alone.
- New utilities: truncate, clamp-2, justify-between, flex-wrap, flex-col,
flex-1, min-w-0, w-full, mt/mb-8/12/16/24, cell-clip, row-click.
- Defined phantom classes shipped in JSX (.dt, .route-loading,
.tab-count) and a .skip-link.
- Email/role cells clip with ellipsis on all viewports, not only <640px.
- Content measure capped at 1440px on every desktop, not only >=1600.
- Sidebar: clearer group separation, active item weight 600.
- main.jsx design-contract comment amended: colors stay frozen,
typography/spacing re-tokenized.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Deploy to S3 / deploy (push) Successful in 37sDetails
Backend: new candidate_forms domain (requisition, interview analysis,
cultural fit) with XOR inbox/manual keys, server-recomputed section
averages and combined summary, INTERVIEW-stage gate (409), history
events, INTERVIEWS_* permissions + 008 RBAC seed; offers table gains
the seven Annexure-J fields.
Frontend: Forms tab in the candidate profile (paper-exact labels from
/forms/definitions, rating tables, score summary tiles, completion
dots); profile converted to a full page at /candidate/:userId opened
from Candidates, Talent Pool and Pipeline; live Advance Stage now calls
PATCH /candidate/stage; workflow-ordered tabs; responsive pass verified
by headless-Edge screenshots at 375-2400px; Stars import crash fix in
Interviews; Matching tab strip wraps on phones.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Updated the interview model to include `graph_event_id` and `web_link` for calendar integration.
- Added methods for setting calendar events and retrieving job titles associated with interviews.
- Modified serializers to include new fields in the interview response.
- Enhanced the job post model to include applicant counts.
- Updated frontend components to handle new fields and improve user experience with calendar event management.
- Introduced image upload functionality in job forms with validation for file types and sizes.
- Improved dashboard and calendar UI for better data presentation.
This commit streamlines interview scheduling and job management processes, enhancing overall application functionality.
Deploy to S3 / deploy (push) Successful in 33sDetails
- New POST /job/assist-field (job_board.create OR jobs.edit): per-field
AI fix/suggest via backend/job_assist package on the shared llm_call.
Suggest is gated on title + experience anchors; decisive typo repair;
provider failures return a generic 503.
- AiFieldAssist component: sparkle button per field with fix/suggest,
loading, preview-before-apply, abort on close; wired into JobForm and
EditJobForm with per-field suggest hints.
- Create Job no longer requires a Buffer channel: without channel_id or
platform the backend saves an internal-only requisition (platform
internal) and never calls Buffer; publishing stays on the Job Board.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>