Files
fourge-portal/layout.md
T

269 lines
14 KiB
Markdown

# Fourge Portal Layout System
This is the single source of truth for dashboard/profile visual structure and UI geometry.
## 1) Global Frame
- Viewport app shell: `height: 100vh`, `overflow: hidden`
- Main content gutter: `24px` all sides
- Sidebar: `width: 76px`, `top: 24px`, `left: 24px`, `height: calc(100vh - 48px)`, `border-radius: 8px`
- Main wrapper offset from sidebar: `margin-left: 100px`
- Page rhythm unit: `24px` (header spacing, card gaps, section gaps)
## 2) Theme + Background
- Background ownership is `body` via `background: var(--bg)`.
- Dark base token `--bg` is full gradient:
- radial glow + vertical dark gradient.
- Light base token `--bg` is full gradient:
- gray radial glow + white vertical gradient.
- Do not use `html` theme-gradient scripting for Safari chrome behavior.
## 3) Tokens
- Accent: `#F5A523`
- Card bg dark: `rgba(255,255,255,0.02)`
- Card bg light: `rgba(0,0,0,0.02)`
- Sidebar/menu shell uses the same transparent card background token as cards
- Secondary card tone dark: `rgba(255,255,255,0.08)`
- Secondary card tone light: `rgba(0,0,0,0.08)`
- Border dark: `rgba(245,165,35,0.15)`
- Border light: `rgba(0,0,0,0.1)`
- Text primary dark/light: `#ffffff / #0d0d0d`
- Text secondary dark/light: `#a8a8a8 / rgba(0,0,0,0.6)`
- Text muted dark/light: `#666666 / rgba(0,0,0,0.38)`
## 4) Typography
- Font family: `Fourge`, then `-apple-system`, `BlinkMacSystemFont`, `'Segoe UI'`, `sans-serif`
- Base font size: `14px`
- Header title: `28px`, `500`, `line-height: 1.2`
- Header subtitle: `13px`
- Widget title: `11px`, `500`, uppercase, `letter-spacing: 0.8px`
- Body table text: `12px/13px` by column importance
## 5) Card System
- Default widget shell:
- `background: var(--card-bg)`
- `border: 1px solid var(--border)`
- `border-radius: 8px`
- `padding: 18px 21px`
- `backdrop-filter: blur(12px)` + `-webkit-backdrop-filter`
- Card width is not an intrinsic card token.
- Width is owned by the page/grid/container the card lives in.
- Cards should fill the slot provided by that page layout unless a page-level rule explicitly fixes a track.
- Compact card radius (legacy generic `.card`): `4px` (do not use for new dashboard widgets)
## 6) Header + Top Right Controls
- Site header: `padding-top: 24px`, `padding-bottom: 24px`
- Right control row:
- Search icon button: `32x32`
- Search button to theme toggle space: `7px` (`search-wrap margin-right`)
- Theme toggle: `32x32`
- Theme toggle to avatar: `14px` (`avatar-wrap margin-left`)
- Avatar button: `49x49`, circle, `2px` inner ring + `2px` accent outline
## 7) Dashboard Grids (Team)
- Stat row: `grid-template-columns: 1fr 1fr 1fr 1.5fr`, `gap: 24`, `margin-bottom: 0`
- Row 2: `grid-template-columns: 1fr 1fr 280px`, `gap: 24`, `margin-top: 24`
- Order: Recent Activity (left), Tasks In Progress (center), Calendar (right, fixed width)
- Row 3: `grid-template-columns: 1fr 1fr`, `gap: 24`, `margin-top: 24`
- Row 4 full-width: `margin-top: 24`
## 8) Stat Cards
- Card min height: `120px`
- Internal row gap: `21px`
- Label/value/sub spacing:
- Label: `margin-bottom: 5px`
- Value: `30px`, `400`, `letter-spacing: -0.5`, `line-height: 1.1`
- Sub: `12px`, `margin-top: 5px`
- Icon badge: `27x27`, circle
- Icon glyph: `13x13`
## 9) Calendar
- Card uses widget shell
- Header-to-grid gap: `14px`
- Weekday label: `10px`, `600`, `letter-spacing: 0.5`
- Day cell button: `28x28`, circular
- Day number: `12px`
- Today style: bg `#F5A523`, text `#0d0d0d`, `700`
- Dots: up to 3, each `3x3`, gap `2`
- Popover:
- Anchored left of cell: `right: calc(100% + 8px)`, vertical centered
- `width: 210px`, `padding: 10px 12px`, `border-radius: 8px`
- shadow `0 12px 32px rgba(0,0,0,0.45)`
- row dot `6x6`, row text `12px`
## 10) Activity + Performance Rows
- Visible rows target: 5
- Row layout: `display:flex`, `align-items:center`, `gap:10px`
- Row spacing: `margin-top: 10px` from second row onward
- Name text: `13px`
- Meta/date text: `11px`
- Progress track: `height: 4px`, `radius: 2px`
- Percentage width slot: `min-width: 28px`
## 11) Tables
- General table layout in dashboard cards: `table-layout: fixed`, `border-collapse: collapse`
- Column widths are table-specific, not universal tokens.
- Widths belong to the individual table/view that defines them.
- Reuse widths only when the same table pattern is intentionally repeated.
- Header cells:
- `font-size: 10px`, `font-weight: 500`, uppercase, `letter-spacing: 0.6px`
- bottom spacing: `padding-bottom: 12px`
- Body cells:
- primary text: `13px`
- secondary/metrics text: `12px`
- row vertical spacing via cell padding: typically `5px`
- Hot Tasks column widths:
- check `10%`, task `40%`, requested by `35%`, due by `15%`
- Client Highlight column widths:
- icon `5%`, company `22%`, contact `23%`, projects `13%`, open `13%`, outstanding `12%`, paid `12%`
- Sorting rule:
- Every visible data column header must be sortable.
- Use clickable header controls (`SortTh`) with ascending/descending indicator.
- Exclude only non-data utility/action columns (checkbox-only, icon-only status marker, action buttons).
## 12) Profile Page
- Container: full available content width, column, `gap: 24`
- Top row: `grid-template-columns: 60fr 40fr`, `gap: 24`
- At `<=1200px`: top row stacks to one column
- Main profile card uses widget shell
- Profile card width is determined by the profile page grid, not by the card itself.
- Internal card layout:
- row `gap: 20px`
- portrait max `140x140`, circle
- portrait aligns flush in the row without extra wrapper padding/side space
- detail grid `140px 1fr`, `row-gap: 8`, `column-gap: 12`, `margin-top: 14`
- profile name/title: `18px`, `500`, `line-height: 1.2`
- company subtitle: `13px`, secondary text
- contact/detail rows: `13px`, primary text
- social row `margin-top: 14`, `gap: 8`
- company line under title is always visible; fallback display is `—` when no company is assigned
- right-side meta labels (`Member Since`, `Role`) use widget-title sizing: `11px`, `500`, uppercase, `letter-spacing: 0.8px`
- right-side meta values use body sizing: `13px`
- self-only edit button: `position: absolute`, `top: 18px`, `right: 21px` (aligns to card padding), `border-radius: 8px` (matches card), `height: 30px`, `font-size: 12px`, `padding: 0 12px`
- default outline button hover/focus fills with accent gold and uses dark text
- Right calendar card shows only tasks/events assigned to the viewed profile user
- Profile page left column includes a `Tasks In Progress` card above `Recent Activity`
- Profile `Tasks In Progress` follows the dashboard table/card pattern:
- same widget shell and header treatment
- same show-all behavior (5 visible by default)
- profile-specific filter is tasks assigned to the viewed user with statuses `in_progress`, `on_hold`, or `client_review`
- columns are `Task` and `Status`
- Profile activity feed action text pattern: `Task started`, `Task submitted`, `Task approved`, `Task rejected` (sentence title case)
- Activity feed includes:
- actions performed by the viewed user
- `Task approved` and `Task rejected` entries for tasks assigned to that viewed user (even if actioned by someone else)
## 12.5) File Sharing
- Main split: `grid-template-columns: minmax(0, 1fr) minmax(0, 3fr)` for an effective `25 / 75` layout, `gap: 24`
- Left stacked cards (`Pinned`, `Navigation`): `gap: 24`
- Canonical folder structure:
- team and subcontractor profile folders live at `Team/<User Name>`
- company folders live at `Clients/<Company Name>`
- project folders live at `Clients/<Company Name>/Projects/<Project Name>`
- every project auto-creates `00 Project Files`
- task folders live at `Clients/<Company Name>/Projects/<Project Name>/<Task Name>`
- every task auto-creates `Request Info`, `Working Files`, and `Old Books`
- request submission files are copied into `Request Info/R00`, `R01`, and higher revision folders
- renaming a team user, subcontractor user, company, project, or task must rename the matching filesystem folder
- folder repair/backfill is additive only: create missing folders, leave existing folders untouched
- request-info backfill must skip files that already exist and must not overwrite added working files or user-managed files
- deleting a task in the portal moves its task folder into `Archive/Clients/<Company Name>/Projects/<Project Name>/<Task Name>` instead of deleting it
- deleting a project in the portal moves its project folder into `Archive/Clients/<Company Name>/Projects/<Project Name>` instead of deleting it
- orphan reconciliation may move folders into archive when they no longer map to portal records
- orphan team folders move to `Archive/Team/<Folder Name>` when no team or subcontractor profile matches that folder name
- orphan project folders move to `Archive/Clients/<Company Name>/Projects/<Project Name>` when no portal project matches that folder name under that company
- orphan reconciliation does not remove company roots or overwrite archived content; it merge-moves into archive
- Access/home rules:
- team members have full file access
- client users with exactly one tied company use that company folder as home: `/Clients/<Company Name>`
- client users tied to multiple companies use `/Clients` as home and only see company folders they are tied to
- `/Clients` acts as a virtual parent for multi-company client users and must not expose unrelated company folders
- subcontractor users use virtual home `/`
- subcontractor virtual home shows `Team` plus only the project folders they are assigned to
- subcontractor users skip all other root folders and must not see unrelated client or internal roots
- subcontractor `Team` maps to the real shared `Team` folder
- each subcontractor project folder is a virtual root that maps to the real client project path `/Clients/<Company>/Projects/<Project>`
- Right card header:
- title label is `File Browser`
- drag/drop note sits directly under the title and uses subtext sizing: `12px`
- current file path uses the same `11px` uppercase label treatment as the title row family
- toolbar does not show `+ Folder` or `Upload` buttons
- upload happens by dragging and dropping files or folders into the right card
- delete action uses the same geometry as the profile edit button (`top: 18px`, `right: 21px`, `8px` radius, `30px` height, `12px` text, `0 12px` padding) but uses danger styling with red hover/fill
- Right card table:
- uses dashboard table styling (`table-layout: fixed`, transparent header row, `10px` uppercase headers, `13px/12px` body text)
- card padding matches dashboard widget shell (`18px 21px`)
- clickable text inside the table highlights in accent; rows do not use block hover fill
- body cells are borderless like dashboard card tables
- body cell padding matches dashboard tables exactly: `5px`
- visible headers (`Name`, `Size`, `Modified`) use shared sortable header controls
- file/folder icon footprint is compact so row height stays on the same cadence as dashboard tables
- alternating rows use a very subtle theme-aware tint for scanability
- Navigation tree:
- `Home` aligns to the first arrow column
- connector line runs through the arrow center column
- pinned folders are user-specific and must not be shared across users on the same device/browser session
- hover is text-only accent color, no row fill
## 13) Radius + Geometry Rules
- Dashboard/profile widgets: `8px` radius
- Sidebar: `8px` radius
- Standard app buttons use the `Edit Profile` geometry:
- height: `30px`
- horizontal padding: `0 12px`
- border-radius: `8px`
- font-size: `11px`
- font-weight: `500`
- letter-spacing: `0.8px`
- text-transform: uppercase
- line-height: `1`
- label color follows theme text roles:
- dark mode: primary button labels use dark text on accent fill; outline labels use primary text on transparent surface
- light mode: outline labels use light-theme primary text; danger labels use danger text
- outline button border uses the same `var(--border)` token as card outlines unless a button role explicitly overrides it
- keep existing button role styling intact (`outline`, `primary`, `danger`); geometry changes, not role colors
- Inputs/dropdowns may use their own control radius unless a page-specific rule says otherwise
- Circular elements (avatar/day/icon badges): `50%`
## 14) Z-Index Stack
- Sidebar: `200`
- Header dropdowns/tooltips: `300`
- Calendar hover popover: `1002` within card context (`card can be 1001 active`)
- Modal overlay: `1200`
## 15) Motion
- Motion vars:
- fast `160ms`
- base `220ms`
- easing `cubic-bezier(0.22, 1, 0.36, 1)`
- Dropdown animation: `ui-fade-up` from `translateY(4px)` + opacity 0 -> 1
## 17) Hover Interaction Contract
- Sidebar, header icon buttons, dropdown items, and avatar menu items must show a visible hover surface before click.
- Single hover source-of-truth block controls these elements.
- Dark hover surface baseline: `#1f1f1f`.
- Light hover surface baseline: `rgba(0,0,0,0.08)`.
- Nav icon opacity must lift from muted to full on hover (`opacity: 1`).
- Clickable text links use text-only highlight on hover/focus (`color: var(--accent)`), not whole-row/background fill.
- Hover and active must be visually distinct:
- hover uses stronger temporary contrast (`bg` + thin border),
- active remains persistent selected-state background.
- File Sharing left navigation exception:
- `Pinned` + `Navigation` tree rows use text-only hover highlight (`color: var(--accent)`).
- Do not apply row background fill for hover in this section.
## 16) Non-Negotiable Implementation Rules
- Keep gradient backgrounds on `html`, not `body`
- Keep widget shell values (`18px 21px`, `8px`, blur 12, border token) consistent
- Maintain global `24px` spacing rhythm for page/frame/grid gaps
- Keep team dashboard card order:
1. Open Tasks
2. Active Projects
3. Net Profit
4. Revenue (wide)
- Keep row 2 order: Recent Activity (left), Tasks In Progress (center), Calendar (right fixed at `280px`)
## 18) Invoice Rules
- New work (`R00`) is billed at the new-service rate.
- Revision `R01` is free.
- Revisions `R02+` are billed incrementally: each uninvoiced revision entry contributes exactly `1x` revision charge.
- Previously invoiced revisions are excluded; later invoices only charge newly uninvoiced revisions (e.g. if `R02` was already invoiced, at `R04` only `R03` + `R04` are billed).