Site comments (8/3) - BIM card: LOD removed, IFF # added next to the coordination status, and required once that status is "Signed off (IFF)" — an unnumbered sign-off isn't traceable. A LOD already stored on a package is preserved and shown as legacy, not blanked. - The blue "from SOP types" subtext under a field is now a SOP chip on the label with the detail in a tooltip. The chip stays visible rather than hover-only: field tablets have no hover, and "this came from the SOP" is the part that matters. The hint elements stay in the DOM (hidden) so the code writing to them keeps working; an observer mirrors their text into the tooltip. - Specification Section is no longer typed per package. Each WP type carries a spec section on the SOP; the field is read-only in the Creator and follows the type, with the SOP's spec folder linked underneath. This reads both spec comments as one intent — stop typing it, derive it. - Assignees and Distribution are multi-selects over the SOP project team, showing each person's job function, with the CM pre-added to Distribution (removable per package) and a free-text option for people with no account. The stored display strings are unchanged so print/export/dashboard keep working; account ids ride alongside for the notification work in wave 3. Localization + time - Per-user locale/timezone (Language & time in the user menu), an app-wide default in the admin console, then the browser. Timezones are validated against the server's zoneinfo and the picker is fed from it. Calendar dates are formatted from their parts so a due date never reads a day early in another zone. - Every displayed timestamp now goes through the shared helpers. Top-bar chrome - Project switcher beside the logo and a centered global search, injected into either generation of top bar; skipped in an iframe so the embedded Creator doesn't get a second one. Ctrl/Cmd-K focuses search. - GET /api/search covers work packages, projects and SOPs, scoped to the caller's projects, hiding archived packages, with LIKE wildcards escaped. Fixed along the way: showForm() cleared every card's inline display, which undid applyKind() — so the Package Type and BIM cards reappeared on an install-only project. Split out applyKindVisibility() and re-apply it there. Verified: 100 API checks on a fresh database (44 permissions + 22 password reset + 34 search/localization), 24 driven UI checks against the real Creator page in headless Chrome (SOP chips, both people pickers, spec auto-fill, critical tags, BIM suppression), and the chrome harness on both bar styles. Screenshots reviewed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
554 lines
12 KiB
CSS
554 lines
12 KiB
CSS
:root {
|
|
--primary: #0f62fe;
|
|
--primary-light: #edf5ff;
|
|
--success: #198038;
|
|
--warning: #8e6a00;
|
|
--warning-bg: #fdf6dd;
|
|
--danger: #da1e28;
|
|
--text: #161616;
|
|
--text-light: #525252;
|
|
--text-dim: #8d8d8d;
|
|
--border: #e0e0e0;
|
|
--border-strong: #8d8d8d;
|
|
--bg: #f4f4f4;
|
|
--bg-card: #ffffff;
|
|
--appbar: #161616;
|
|
--shadow: none;
|
|
--shadow-lg: 0 4px 16px rgba(0,0,0,0.16);
|
|
}
|
|
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
body {
|
|
font-family: 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
|
|
color: var(--text);
|
|
background: var(--bg);
|
|
line-height: 1.5;
|
|
}
|
|
|
|
.app-container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-height: 100vh;
|
|
}
|
|
|
|
/* HEADER — dark UI Shell bar */
|
|
.header {
|
|
background: var(--appbar);
|
|
color: #fff;
|
|
padding: 0 16px;
|
|
height: 48px;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
|
|
.header-left {
|
|
flex: 1;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 14px;
|
|
min-width: 0;
|
|
}
|
|
|
|
/* Prime logo (white-background wordmark) sits in a white chip on the dark bar */
|
|
.logo {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: #fff;
|
|
padding: 4px 8px;
|
|
border-radius: 4px;
|
|
text-decoration: none;
|
|
transition: opacity 0.2s;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.logo:hover { opacity: 0.92; }
|
|
.logo img { height: 24px; width: auto; display: block; }
|
|
|
|
.logo-icon {
|
|
width: 36px;
|
|
height: 36px;
|
|
background: var(--primary-light);
|
|
border-radius: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 18px;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.header-title {
|
|
font-size: 15px;
|
|
font-weight: 600;
|
|
margin-bottom: 0;
|
|
color: #fff;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.header-subtitle {
|
|
font-size: 12px;
|
|
color: #c6c6c6;
|
|
min-height: 16px;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.header-right {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
.header-button {
|
|
padding: 7px 14px;
|
|
background: transparent;
|
|
color: #fff;
|
|
border: 1px solid #6f6f6f;
|
|
border-radius: 0;
|
|
cursor: pointer;
|
|
font-size: 14px;
|
|
font-weight: 400;
|
|
transition: background 0.15s, border-color 0.15s;
|
|
}
|
|
|
|
.header-button:hover {
|
|
background: #353535;
|
|
border-color: #6f6f6f;
|
|
}
|
|
|
|
.step-counter {
|
|
background: transparent;
|
|
border: 1px solid #6f6f6f;
|
|
color: #c6c6c6;
|
|
padding: 4px 10px;
|
|
border-radius: 20px;
|
|
font-size: 12px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
/* MAIN NAVIGATION — underline tabs */
|
|
.main-nav {
|
|
display: flex;
|
|
gap: 0;
|
|
padding: 0 16px;
|
|
background: var(--bg-card);
|
|
border-bottom: 1px solid var(--border);
|
|
}
|
|
|
|
.nav-tab {
|
|
padding: 13px 18px;
|
|
background: none;
|
|
border: none;
|
|
border-bottom: 3px solid transparent;
|
|
border-radius: 0;
|
|
cursor: pointer;
|
|
font-size: 15px;
|
|
font-weight: 400;
|
|
color: var(--text-light);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
transition: background 0.15s, color 0.15s;
|
|
}
|
|
|
|
.nav-tab:hover {
|
|
background: var(--bg);
|
|
color: var(--text);
|
|
}
|
|
|
|
.nav-tab.active {
|
|
background: none;
|
|
color: var(--text);
|
|
border-bottom-color: var(--primary);
|
|
font-weight: 600;
|
|
}
|
|
|
|
.tab-icon { font-size: 16px; }
|
|
|
|
/* CONTENT AREA */
|
|
.content-area {
|
|
flex: 1;
|
|
padding: 2rem;
|
|
max-width: 1000px;
|
|
margin: 0 auto;
|
|
width: 100%;
|
|
}
|
|
|
|
.tool {
|
|
display: none;
|
|
}
|
|
|
|
.tool.active {
|
|
display: block;
|
|
}
|
|
|
|
/* STEP NAV */
|
|
.step-nav {
|
|
margin-bottom: 2rem;
|
|
overflow-x: auto;
|
|
}
|
|
|
|
.steps-container {
|
|
display: flex;
|
|
gap: 0.5rem;
|
|
min-width: min-content;
|
|
padding: 0.5rem;
|
|
}
|
|
|
|
.step-item {
|
|
padding: 0.6rem 0.9rem;
|
|
border-radius: 0;
|
|
background: var(--bg-card);
|
|
border: 1px solid var(--border);
|
|
color: var(--text-light);
|
|
cursor: pointer;
|
|
font-size: 12px;
|
|
font-weight: 500;
|
|
white-space: nowrap;
|
|
transition: background 0.15s, color 0.15s, border-color 0.15s;
|
|
}
|
|
|
|
.step-item:hover { background: var(--bg); border-color: var(--border-strong); color: var(--text); }
|
|
.step-item.active { background: var(--primary); color: white; border-color: var(--primary); font-weight: 600; }
|
|
|
|
/* STEP CONTENT */
|
|
.step-content {
|
|
background: var(--bg-card);
|
|
padding: 2rem;
|
|
border: 1px solid var(--border);
|
|
border-radius: 0;
|
|
margin-bottom: 2rem;
|
|
}
|
|
|
|
.step { display: none; }
|
|
|
|
.step h2 {
|
|
font-size: 22px;
|
|
font-weight: 400;
|
|
letter-spacing: -0.01em;
|
|
margin-bottom: 0.75rem;
|
|
color: var(--text);
|
|
}
|
|
|
|
.notice {
|
|
font-size: 13px;
|
|
color: var(--text-light);
|
|
background: var(--primary-light);
|
|
padding: 0.75rem 1rem;
|
|
border-radius: 0;
|
|
margin-bottom: 1.5rem;
|
|
border-left: 4px solid var(--primary);
|
|
}
|
|
|
|
/* FIELDS */
|
|
.field-grid {
|
|
display: grid;
|
|
gap: 1.5rem;
|
|
}
|
|
|
|
.field-grid.col1 { grid-template-columns: 1fr; }
|
|
|
|
.field {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.field label {
|
|
font-size: 13px;
|
|
font-weight: 600;
|
|
margin-bottom: 0.5rem;
|
|
color: var(--text);
|
|
}
|
|
|
|
.field input,
|
|
.field select,
|
|
.field textarea {
|
|
padding: 0.75rem;
|
|
border: 1px solid var(--border);
|
|
border-radius: 0;
|
|
font-size: 14px;
|
|
font-family: inherit;
|
|
color: var(--text);
|
|
background: var(--bg);
|
|
transition: border-color 0.2s;
|
|
}
|
|
|
|
.field input:focus,
|
|
.field select:focus,
|
|
.field textarea:focus {
|
|
outline: none;
|
|
border-color: var(--primary);
|
|
box-shadow: 0 0 0 3px var(--primary-light);
|
|
}
|
|
|
|
.field small {
|
|
font-size: 12px;
|
|
color: var(--text-dim);
|
|
margin-top: 0.25rem;
|
|
}
|
|
|
|
/* ROLES */
|
|
.required-roles {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 1rem;
|
|
}
|
|
|
|
.role-required {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 1rem;
|
|
background: var(--bg);
|
|
border-radius: 0;
|
|
border: 1px solid var(--border);
|
|
}
|
|
|
|
.role-checkbox {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.role-checkbox input[type="checkbox"] {
|
|
width: 18px;
|
|
height: 18px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.role-checkbox label {
|
|
margin: 0;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
}
|
|
|
|
/* WP TYPES */
|
|
#wp-types-table { overflow-x: auto; }
|
|
|
|
.wp-type-row {
|
|
display: grid;
|
|
grid-template-columns: 1.1fr 80px 1.3fr 1.6fr 1.2fr;
|
|
gap: 0.85rem;
|
|
align-items: center;
|
|
padding: 0.75rem 1rem;
|
|
background: var(--bg);
|
|
border-radius: 0;
|
|
margin-bottom: 0.5rem;
|
|
border: 1px solid var(--border);
|
|
}
|
|
|
|
.wp-types-header {
|
|
display: grid;
|
|
grid-template-columns: 1.1fr 80px 1.3fr 1.6fr 1.2fr;
|
|
gap: 0.85rem;
|
|
padding: 0.5rem 1rem;
|
|
font-size: 11px;
|
|
font-weight: 600;
|
|
letter-spacing: 0.04em;
|
|
text-transform: uppercase;
|
|
color: var(--text-light);
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
|
|
/* BUTTONS */
|
|
.add-btn {
|
|
padding: 0.7rem 1.25rem;
|
|
background: var(--primary);
|
|
color: white;
|
|
border: none;
|
|
border-radius: 0;
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
transition: background 0.2s;
|
|
}
|
|
|
|
.add-btn:hover { background: var(--cds-hover-primary, #0353e9); }
|
|
|
|
.nav-btn {
|
|
padding: 0.7rem 1.4rem;
|
|
background: var(--bg-card);
|
|
border: 1px solid var(--border-strong);
|
|
border-radius: 0;
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
color: var(--text);
|
|
cursor: pointer;
|
|
transition: all 0.15s;
|
|
}
|
|
|
|
.nav-btn:hover { border-color: var(--primary); color: var(--primary); background: var(--bg); }
|
|
|
|
.nav-btn.primary {
|
|
background: var(--success);
|
|
color: white;
|
|
border-color: var(--success);
|
|
}
|
|
|
|
.nav-btn.primary:hover { background: #0e6027; border-color: #0e6027; color: white; }
|
|
|
|
.nav-btn:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
|
|
/* NAVIGATION */
|
|
.step-navigation {
|
|
display: flex;
|
|
gap: 1rem;
|
|
justify-content: space-between;
|
|
padding: 1.5rem;
|
|
background: var(--bg-card);
|
|
border-radius: 0;
|
|
box-shadow: var(--shadow);
|
|
}
|
|
|
|
/* COMMENTS */
|
|
.comments-section {
|
|
margin-top: 2rem;
|
|
padding-top: 1.5rem;
|
|
border-top: 2px solid var(--border);
|
|
}
|
|
|
|
.comments-toggle {
|
|
padding: 0.5rem 1rem;
|
|
background: var(--primary-light);
|
|
color: var(--primary);
|
|
border: 1px solid var(--primary);
|
|
border-radius: 0;
|
|
font-size: 13px;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.comments-toggle:hover { background: var(--primary); color: white; }
|
|
|
|
/* CONSTRUCTION SEQUENCE (drag & drop) */
|
|
#sequence-list { display: flex; flex-direction: column; gap: 8px; }
|
|
.seq-step {
|
|
display: flex; align-items: center; gap: 12px; padding: 11px 14px;
|
|
background: var(--bg-card); border: 1px solid var(--border); border-radius: 0;
|
|
box-shadow: var(--shadow); transition: border-color .12s, box-shadow .12s, opacity .12s;
|
|
}
|
|
.seq-step:hover { border-color: var(--primary); }
|
|
.seq-step.dragging { opacity: .35; border-style: dashed; }
|
|
.seq-step.drag-over { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-light); }
|
|
.seq-handle { cursor: grab; color: var(--text-dim); font-size: 16px; line-height: 1; user-select: none; flex-shrink: 0; }
|
|
.seq-handle:active { cursor: grabbing; }
|
|
.seq-num {
|
|
width: 24px; height: 24px; flex-shrink: 0; border-radius: 50%; background: var(--primary-light); color: var(--primary);
|
|
font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center;
|
|
}
|
|
.seq-step input.seq-label {
|
|
border: 1px solid transparent; background: transparent; font-size: 14px; padding: 5px 8px; color: var(--text); flex: 1; border-radius: 4px;
|
|
}
|
|
.seq-step input.seq-label:focus { background: var(--bg); border-color: var(--primary); outline: none; }
|
|
.seq-del {
|
|
background: var(--danger); color: white; border: none; border-radius: 4px;
|
|
width: 28px; height: 28px; cursor: pointer; font-weight: 600; flex-shrink: 0;
|
|
}
|
|
.seq-arrow { text-align: center; color: var(--text-dim); font-size: 13px; line-height: .4; margin: -2px 0; }
|
|
.seq-step.gate { border-color: var(--warning); background: var(--warning-bg); border-style: dashed; }
|
|
.seq-step.gate .seq-label { color: var(--warning); font-weight: 500; }
|
|
.seq-gate-badge {
|
|
flex-shrink: 0; padding: 3px 9px; border-radius: 20px; background: var(--warning); color: #fff;
|
|
font-size: 9px; font-weight: 600; letter-spacing: .08em; white-space: nowrap;
|
|
}
|
|
|
|
/* STEP COMMENTS DROPDOWN */
|
|
.comments-dropdown {
|
|
position: fixed;
|
|
top: 80px;
|
|
right: 2rem;
|
|
width: 360px;
|
|
max-width: calc(100vw - 2rem);
|
|
background: var(--bg-card);
|
|
border: 1px solid var(--border);
|
|
border-radius: 0;
|
|
box-shadow: var(--shadow-lg);
|
|
padding: 1.25rem;
|
|
z-index: 1200;
|
|
}
|
|
|
|
.comments-dropdown-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.comments-dropdown-close {
|
|
background: none;
|
|
border: none;
|
|
font-size: 16px;
|
|
cursor: pointer;
|
|
color: var(--text-light);
|
|
line-height: 1;
|
|
}
|
|
|
|
.comments-dropdown-close:hover { color: var(--text); }
|
|
|
|
/* MODAL */
|
|
.modal {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background: rgba(0,0,0,0.5);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
z-index: 1000;
|
|
}
|
|
|
|
.modal-content {
|
|
background: var(--bg-card);
|
|
border-radius: 0;
|
|
padding: 2rem;
|
|
max-width: 600px;
|
|
max-height: 80vh;
|
|
overflow-y: auto;
|
|
box-shadow: var(--shadow-lg);
|
|
}
|
|
|
|
.modal-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 1.5rem;
|
|
border-bottom: 1px solid var(--border);
|
|
padding-bottom: 1rem;
|
|
}
|
|
|
|
.modal-header h3 { font-size: 18px; margin: 0; }
|
|
|
|
.modal-close {
|
|
background: none;
|
|
border: none;
|
|
font-size: 20px;
|
|
cursor: pointer;
|
|
color: var(--text-dim);
|
|
}
|
|
|
|
.modal-close:hover { color: var(--text); }
|
|
|
|
/* UTILITY */
|
|
.sub-heading {
|
|
font-size: 14px;
|
|
font-weight: 700;
|
|
color: var(--text);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.05em;
|
|
}
|
|
|
|
/* RESPONSIVE */
|
|
@media (max-width: 768px) {
|
|
.header { height: auto; flex-direction: column; align-items: stretch; text-align: center; gap: 0.75rem; padding: 12px 16px; }
|
|
.main-nav { flex-wrap: wrap; }
|
|
.content-area { padding: 1rem; }
|
|
.step-content { padding: 1rem; }
|
|
.wp-type-row { grid-template-columns: 1fr; }
|
|
.wp-types-header { display: none; }
|
|
.step-navigation { flex-direction: column; }
|
|
}
|