HR-ATS-Portal/frontend/src/styles/styles.css

1696 lines
98 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/* ============================================================
TalentFlow ATS — Utopia Brands Design System
------------------------------------------------------------
Palette source: Utopia Brands Brand Guideline
Primary #004d43 deep green · #1a3134 ink teal
#ceff71 lime · #eafff4 mint white
Secondary #25e9a5 mint · #8e92ff periwinkle
Neutral #ffffff · #000000
Typography
Display / main headings ....... Inter Tight (semibold, tight tracking)
UI, body & sub-headings ....... Neue Montreal (Inter fallback)
Wordmark only ................. Belleza
Theme model
Light — white/mint surfaces, deep green as the action colour.
Dark — brand ink-teal surfaces, lime as the action colour.
Because the action colour inverts between themes, ALWAYS pair
`background: var(--primary)` with `color: var(--primary-fg)`.
The same applies to --success/--warning/--danger/--info.
============================================================ */
/* ---------- Brand constants (identical in both themes) ---------- */
:root {
--brand-green: #004d43;
--brand-ink: #1a3134;
--brand-lime: #ceff71;
--brand-mint: #25e9a5;
--brand-peri: #8e92ff;
--brand-tint: #eafff4;
}
/* ============================ LIGHT ============================ */
:root {
color-scheme: light;
--bg: #f1f7f4;
--bg-elev: #ffffff;
--bg-sunken: #e8f2ec;
--sidebar-bg: #1a3134;
--sidebar-fg: #9fb8b4;
--sidebar-fg-active: #ffffff;
--sidebar-active-bg: rgba(206,255,113,.14);
--sidebar-rail: #ceff71;
--border: #dbe8e2;
--border-strong: #c2d6ce;
--text: #10231f;
--text-2: #4a625c;
--text-3: #54726c;
/* Action colour — deep brand green on light surfaces */
--primary: #004d43;
--primary-600: #00382f;
--primary-fg: #ffffff;
--primary-soft: #eafff4;
--primary-border: #b4e3d2;
/* Signature accent — lime. Light on white, so it is a SURFACE
colour here, never a text colour. Use --accent-ink for text. */
--accent: #ceff71;
--accent-fg: #1a3134;
--accent-ink: #4f6619;
--accent-soft: #f4ffdf;
--success: #00734f; --success-fg: #ffffff; --success-soft: #d9f7ec;
--warning: #8a5a00; --warning-fg: #ffffff; --warning-soft: #fff2d9;
--danger: #b3243a; --danger-fg: #ffffff; --danger-soft: #ffe6ea;
--info: #0d6580; --info-fg: #ffffff; --info-soft: #e4f4f9;
--purple: #4b4fd6; --purple-fg: #ffffff; --purple-soft: #ecedff;
--teal: #00734f; --teal-soft: #d9f7ec;
--shadow-sm: 0 1px 2px rgba(10,35,31,.05);
--shadow: 0 1px 3px rgba(10,35,31,.07), 0 1px 2px rgba(10,35,31,.04);
--shadow-md: 0 4px 12px rgba(10,35,31,.08), 0 2px 4px rgba(10,35,31,.05);
--shadow-lg: 0 12px 32px rgba(10,35,31,.12), 0 4px 8px rgba(10,35,31,.06);
--radius-sm: 7px;
--radius: 11px;
--radius-lg: 16px;
--radius-xl: 22px;
--sidebar-w: 262px;
--sidebar-w-collapsed: 74px;
--topbar-h: 64px;
--font: 'Neue Montreal', 'PP Neue Montreal', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
--font-display: 'Inter Tight', 'Neue Montreal', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
--font-brand: 'Belleza', 'Inter Tight', 'Inter', sans-serif;
--mono: 'SF Mono', ui-monospace, 'Cascadia Code', Menlo, monospace;
/* Type scale — 9 steps that the 20-size census collapses onto.
Theme-invariant; declared once here, never redefined in dark. */
--fs-2xs: 11px; /* eyebrow labels, micro-meta */
--fs-xs: 12px; /* badges, chips, cell-sub */
--fs-sm: 13px; /* secondary body, form labels, small buttons */
--fs-base: 14px; /* body, tables, buttons, nav */
--fs-md: 15px; /* card titles */
--fs-lg: 18px; /* section headings, empty states */
--fs-xl: 22px; /* modal titles */
--fs-2xl: 25px; /* profile hero name, mobile page title */
--fs-3xl: 30px; /* page title (Inter Tight) */
--lh-display: 1.15; /* display headings */
--lh-heading: 1.25; /* h2h6, card titles */
--lh-body: 1.5; /* running copy */
--lh-label: 1.35; /* eyebrows, form labels, table headers */
/* Spacing scale. --gap is the app's signature 18px stack rhythm
(grid gap, mt/mb-18, card-head padding) — a sanctioned step, kept. */
--space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px;
--space-5: 20px; --space-6: 24px; --space-7: 32px; --space-8: 40px;
--gap: 18px;
/* Categorical chart series — brand hues darkened to hold >=3:1
against white so lines and small marks stay legible. */
--c1: #004d43; --c2: #0f9d76; --c3: #5b60e8; --c4: #6f8f14;
--c5: #0e7490; --c6: #8a5a00; --c7: #a8327d; --c8: #3f6d64;
/* Avatar + pipeline-stage ramps. Both invert with the theme, so the
JS emits `var(--av-n)` / `var(--stage-n)` rather than fixed hex. */
--avatar-fg: #ffffff;
--av-1: #004d43; --av-2: #1a3134; --av-3: #0f5f4a; --av-4: #2f4858;
--av-5: #4b4fd6; --av-6: #155e63; --av-7: #5b3f8f; --av-8: #8a2f4a;
--stage-1: #0e7490; --stage-2: #5b60e8; --stage-3: #8a5a00; --stage-4: #004d43;
--stage-5: #0f9d76; --stage-6: #6f8f14; --stage-7: #b3243a;
--stage-8: #0b6e4f; --stage-9: #b45309;
--ring: 0 0 0 3px rgba(0,77,67,.20);
/* select chevron: whole url() is tokenised so the stroke can follow the theme */
--chev-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2354726c' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
}
/* ============================= DARK ============================= */
[data-theme="dark"] {
color-scheme: dark;
--bg: #0e1d1f;
--bg-elev: #16292c;
--bg-sunken: #1a3134;
--sidebar-bg: #0a1618;
--sidebar-fg: #8fa9a4;
--sidebar-fg-active: #ffffff;
--sidebar-active-bg: rgba(206,255,113,.12);
--sidebar-rail: #ceff71;
--border: #24403f;
--border-strong: #33534f;
--text: #e6f2ec;
--text-2: #a3bdb6;
--text-3: #8fada6;
/* Action colour inverts to lime — brand's dark-surface highlight */
--primary: #ceff71;
--primary-600: #dcff96;
--primary-fg: #0d2523;
--primary-soft: rgba(206,255,113,.08);
--primary-border: rgba(206,255,113,.32);
--accent: #ceff71;
--accent-fg: #12292b;
--accent-ink: #ceff71;
--accent-soft: rgba(206,255,113,.10);
--success: #25e9a5; --success-fg: #06251b; --success-soft: rgba(37,233,165,.12);
--warning: #f5c451; --warning-fg: #2a1e04; --warning-soft: rgba(245,196,81,.12);
--danger: #ff7a8a; --danger-fg: #2d0a10; --danger-soft: rgba(255,122,138,.12);
--info: #5fd3e8; --info-fg: #05242b; --info-soft: rgba(95,211,232,.12);
--purple: #8e92ff; --purple-fg: #12133a; --purple-soft: rgba(142,146,255,.12);
--teal: #25e9a5; --teal-soft: rgba(37,233,165,.12);
--shadow-sm: 0 1px 2px rgba(0,0,0,.45);
--shadow: 0 1px 3px rgba(0,0,0,.55);
--shadow-md: 0 4px 14px rgba(0,0,0,.6);
--shadow-lg: 0 14px 40px rgba(0,0,0,.65);
/* Same series, brightened for dark surfaces — lime and mint lead. */
--c1: #ceff71; --c2: #25e9a5; --c3: #8e92ff; --c4: #a8e063;
--c5: #5fd3e8; --c6: #f5c451; --c7: #ff9ec4; --c8: #7fb3aa;
--avatar-fg: #0d2523;
--av-1: #ceff71; --av-2: #25e9a5; --av-3: #8e92ff; --av-4: #a8e063;
--av-5: #5fd3e8; --av-6: #f5c451; --av-7: #ff9ec4; --av-8: #7fb3aa;
--stage-1: #5fd3e8; --stage-2: #8e92ff; --stage-3: #f5c451; --stage-4: #ceff71;
--stage-5: #25e9a5; --stage-6: #a8e063; --stage-7: #ff7a8a;
--stage-8: #5ee0b5; --stage-9: #ffb020;
--ring: 0 0 0 3px rgba(206,255,113,.28);
--chev-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238fada6' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html {
height: 100%;
/* iOS inflates text when a phone is rotated to landscape unless this is
pinned; Windows/Android high-contrast modes need the adjust too. */
-webkit-text-size-adjust: 100%;
text-size-adjust: 100%;
}
body {
min-height: 100%;
font-family: var(--font);
background: var(--bg);
color: var(--text);
font-size: var(--fs-base);
line-height: var(--lh-body);
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
/* Grey flash on tap (iOS/Android WebKit + Chromium); we provide our own
:active feedback further down instead. */
-webkit-tap-highlight-color: transparent;
/* Stop the whole page rubber-banding behind fixed chrome on iOS. */
overscroll-behavior-y: none;
}
svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
button {
font-family: inherit; cursor: pointer; border: none; background: none; color: inherit;
touch-action: manipulation; /* removes the legacy 300ms tap delay */
}
input, select, textarea { font-family: inherit; font-size: var(--fs-base); color: var(--text); }
a { color: inherit; text-decoration: none; -webkit-tap-highlight-color: transparent; }
img, svg, video, canvas { max-width: 100%; }
::-webkit-scrollbar { width: 14px; height: 14px; }
::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 20px; border: 3px solid transparent; background-clip: padding-box; }
::-webkit-scrollbar-thumb:hover { background: var(--text-3); background-clip: padding-box; }
::selection { background: var(--brand-lime); color: var(--brand-ink); }
/* Firefox-only scrollbar colors. Chrome 121+ also passes
@supports (scrollbar-color: auto), and any non-auto scrollbar-color/width
makes Chromium IGNORE the ::-webkit-scrollbar rules above — the old
`scrollbar-width: thin` here is what forced the skinny native bars.
Gate on -moz-appearance so only Firefox takes this path. */
@supports (-moz-appearance: none) {
* { scrollbar-color: var(--border-strong) transparent; }
}
/* ============================================================
INPUT MODALITY
Hover styling belongs to devices that can hover. On touch, :hover
sticks after a tap and leaves rows/buttons stuck in a hover state,
so every hover rule is gated and touch gets :active feedback instead.
============================================================ */
@media (hover: none) {
.btn:active, .icon-btn:active, .nav-item:active, .act-btn:active,
.page-btn:active, .dropdown-link:active, .prompt-chip:active,
.search-item:active, .k-card:active, .platform-card:active,
.role-item:active, .inbox-item:active, .tab:active, .pill-tab:active {
opacity: .68;
transition: opacity .05s;
}
}
/* Prevent iOS Safari from zooming the page when a control gains focus.
Safari zooms whenever the focused field is under 16px, so on any coarse
pointer the controls step up to 16px rather than shrinking the viewport. */
@media (pointer: coarse) {
input, select, textarea,
.form-field input, .form-field select, .form-field textarea,
.toolbar-search input, .topbar-search input, .chat-input-bar textarea, .select {
font-size: 16px;
}
}
/* ============================================================
BRAND TYPOGRAPHY
Display face is Inter Tight — a headline grotesque that shares
Inter's skeleton, so titles read as the same voice as the UI,
only set semibold with negative tracking. Belleza (the brand
guideline's decorative face) is confined to the wordmark: at
text sizes and weight 400 it read thin and informal against a
dense data UI. Everything structural (labels, tables, controls)
stays in the UI face for legibility.
============================================================ */
.page-title,
.modal-head h2,
.ph-name,
.ai-hero h2,
.empty-state h3 {
font-family: var(--font-display);
font-weight: 600;
letter-spacing: -0.015em;
}
.page-title { font-size: var(--fs-3xl); line-height: var(--lh-display); letter-spacing: -0.02em; }
.page-title-sm { font-size: var(--fs-xl); letter-spacing: -0.015em; } /* embedded sub-page titles (h2) */
.modal-head h2 { font-size: var(--fs-xl); }
.ph-name { font-size: var(--fs-2xl); }
.brand-name { font-family: var(--font-brand); font-size: var(--fs-lg); font-weight: 400; letter-spacing: .2px; }
/* Metrics read as data — hero numbers use the display face (Inter
Tight keeps Inter's figures), everything else stays in the UI face;
all tabular-lining so digits don't jitter as values update. */
.kpi-value, .stat-mini-val, .ats-ring .ats-num, .cell-mono, .mono,
table.data td, .k-count, .nav-badge {
font-variant-numeric: tabular-nums;
}
/* Base heading scale. Any heading a class doesn't reach lands on a sane
step instead of the UA default (which rendered bare h3/h4 LARGER and
bolder than the styled card titles beside them). Component rules
(.page-title, .modal-head h2, .card-head h3, …) win by specificity. */
h1, h2, h3, h4, h5, h6 { line-height: var(--lh-heading); }
h1 { font-family: var(--font-display); font-weight: 600; font-size: var(--fs-3xl); line-height: var(--lh-display); letter-spacing: -0.02em; }
h2 { font-size: var(--fs-xl); font-weight: 600; }
h3 { font-size: var(--fs-md); font-weight: 600; }
h4 { font-size: var(--fs-base); font-weight: 600; }
h5, h6 { font-size: var(--fs-sm); font-weight: 600; }
/* Eyebrow labels — one concept, one rule. Previously eleven near-identical
declarations at five sizes and five letter-spacings. Selectors keep only
their unique bits (padding, borders, sticky) at their own definitions. */
.nav-section-label, .search-group-label, .form-section-title,
table.data thead th, .rbac-matrix th, .cal-dow, .info-item .il,
.hf-tile .hf-k, .hf-block-title, .hf-sign .hf-sign-role,
.hf-rate-head > div, .hf-rate-foot > div:first-child {
font-size: var(--fs-2xs); font-weight: 700; text-transform: uppercase;
letter-spacing: .6px; line-height: var(--lh-label); color: var(--text-3);
}
/* ============================================================
FOCUS & MOTION (accessibility)
============================================================ */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
outline: 2px solid var(--primary);
outline-offset: 2px;
border-radius: var(--radius-sm);
}
:focus:not(:focus-visible) { outline: none; }
.sidebar :where(a, button):focus-visible { outline-color: var(--brand-lime); }
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: .01ms !important;
animation-iteration-count: 1 !important;
transition-duration: .01ms !important;
scroll-behavior: auto !important;
}
}
/* dvh tracks the visible area as mobile browser chrome collapses; the vh
line above it is the fallback for engines without dvh support. */
#app { display: flex; min-height: 100vh; min-height: 100dvh; }
/* ================= SIDEBAR ================= */
.sidebar {
width: var(--sidebar-w);
background: var(--sidebar-bg);
color: var(--sidebar-fg);
display: flex;
flex-direction: column;
position: sticky;
top: 0;
height: 100vh;
height: 100dvh;
flex-shrink: 0;
transition: width .22s cubic-bezier(.4,0,.2,1);
z-index: 60;
}
.sidebar-brand {
display: flex; align-items: center; gap: 12px;
padding: 18px 20px;
height: var(--topbar-h);
border-bottom: 1px solid rgba(255,255,255,.06);
position: relative;
}
.brand-logo {
width: 38px; height: 38px; border-radius: 10px; flex-shrink: 0;
background: var(--brand-green);
display: grid; place-items: center;
color: var(--brand-lime);
box-shadow: 0 4px 12px rgba(0,0,0,.28);
}
/* The global `svg` rule strokes icons; the emblem is a filled shape. */
.brand-mark { width: 22px; height: auto; fill: currentColor; stroke: none; }
.brand-text { display: flex; flex-direction: column; line-height: 1.1; overflow: hidden; }
.brand-name { color: #fff; }
.brand-sub { color: var(--sidebar-fg); font-size: 11px; letter-spacing: .3px; }
.sidebar-collapse-btn {
margin-left: auto; color: var(--sidebar-fg); width: 26px; height: 26px;
border-radius: 6px; display: grid; place-items: center; transition: .15s;
}
.sidebar-collapse-btn:hover { background: rgba(255,255,255,.08); color: #fff; }
.sidebar-collapse-btn svg { width: 18px; height: 18px; }
.sidebar-nav { flex: 1; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; padding: 14px 12px; }
.sidebar-nav::-webkit-scrollbar { width: 6px; }
.sidebar-nav::-webkit-scrollbar-thumb { background: rgba(255,255,255,.1); }
.nav-section-label {
letter-spacing: .8px; /* brand moment — wider than the base eyebrow */
padding: 20px 12px 6px; /* clear air between nav groups */
}
.sidebar-nav > div:first-child .nav-section-label { padding-top: 4px; }
.nav-item {
display: flex; align-items: center; gap: 12px;
padding: 9px 12px; border-radius: 9px; margin-bottom: 2px;
color: var(--sidebar-fg); font-weight: 500; font-size: var(--fs-base);
transition: background .14s, color .14s; position: relative; white-space: nowrap;
}
.nav-item svg { width: 19px; height: 19px; flex-shrink: 0; stroke-width: 1.9; }
.nav-item:hover { background: rgba(255,255,255,.05); color: #fff; }
.nav-item.active { background: var(--sidebar-active-bg); color: #fff; font-weight: 600; }
.nav-item.active::before {
content: ''; position: absolute; left: -12px; top: 50%; transform: translateY(-50%);
width: 3px; height: 20px; background: var(--sidebar-rail); border-radius: 0 3px 3px 0;
}
.nav-badge {
margin-left: auto; background: rgba(255,255,255,.12); color: #fff;
font-size: var(--fs-xs); font-weight: 600; padding: 1px 8px; border-radius: 20px; min-width: 22px; text-align: center;
}
.nav-badge-alert { background: var(--danger); color: var(--danger-fg); }
.nav-badge-ai { background: var(--brand-lime); color: var(--brand-ink); font-weight: 700; letter-spacing: .3px; }
/* The sidebar is a dark surface in BOTH themes, so anything inside it must
use sidebar tokens. Left on the global text/surface tokens these dropped
to ~2:1 in light mode (the section labels and the Upgrade button). */
.sidebar .nav-section-label { color: var(--sidebar-fg); }
.sidebar .btn-ghost { color: var(--sidebar-fg); }
.sidebar .btn-ghost:hover { background: rgba(255,255,255,.10); color: #fff; }
.sidebar .btn-secondary {
background: rgba(255,255,255,.06); color: #fff; border-color: rgba(255,255,255,.14);
}
.sidebar-footer { padding: 14px; border-top: 1px solid rgba(255,255,255,.06); }
.usage-card { background: rgba(255,255,255,.04); border: 1px solid rgba(255,255,255,.07); border-radius: 12px; padding: 14px; }
.usage-top { display: flex; justify-content: space-between; font-size: 12px; color: var(--sidebar-fg); margin-bottom: 8px; }
.usage-top span:last-child { color: #fff; font-weight: 600; }
.usage-bar { height: 6px; background: rgba(255,255,255,.1); border-radius: 20px; overflow: hidden; margin-bottom: 12px; }
.usage-fill { height: 100%; background: linear-gradient(90deg, var(--brand-mint), var(--brand-lime)); border-radius: 20px; }
/* Collapsed sidebar */
.sidebar.collapsed { width: var(--sidebar-w-collapsed); }
.sidebar.collapsed .brand-text,
.sidebar.collapsed .nav-item span:not(.nav-badge),
.sidebar.collapsed .nav-section-label,
.sidebar.collapsed .sidebar-footer,
.sidebar.collapsed .nav-badge { display: none; }
.sidebar.collapsed .sidebar-collapse-btn { transform: rotate(180deg); position: absolute; right: 8px; }
.sidebar.collapsed .nav-item { justify-content: center; padding: 10px; }
.sidebar.collapsed .sidebar-brand { justify-content: center; padding: 18px 0; }
/* ================= MAIN WRAP ================= */
.main-wrap { flex: 1; display: flex; flex-direction: column; min-width: 0; }
/* ================= TOPBAR ================= */
.topbar {
height: var(--topbar-h); background: var(--bg-elev); border-bottom: 1px solid var(--border);
display: flex; align-items: center; gap: 16px; padding: 0 22px;
position: sticky; top: 0; z-index: 50;
}
/* Double class: .icon-btn { display: grid } is declared later with equal
specificity and used to win, leaving the hamburger visible on desktop —
where clicking it stranded the scrim over the page with scroll locked. */
.icon-btn.menu-toggle { display: none; }
.topbar-search { position: relative; flex: 1; max-width: 480px; display: flex; align-items: center; }
.topbar-search > svg { position: absolute; left: 14px; width: 18px; height: 18px; color: var(--text-3); pointer-events: none; }
.topbar-search input {
width: 100%; padding: 9px 14px 9px 42px; border-radius: 10px;
background: var(--bg-sunken); border: 1px solid transparent; outline: none; transition: .15s;
}
.topbar-search input:focus { background: var(--bg-elev); border-color: var(--primary); box-shadow: var(--ring); }
.search-kbd {
position: absolute; right: 12px; font-family: var(--mono); font-size: 11px;
color: var(--text-3); background: var(--bg-elev); border: 1px solid var(--border);
padding: 2px 6px; border-radius: 5px; pointer-events: none;
}
.search-results {
position: absolute; top: calc(100% + 8px); left: 0; right: 0;
background: var(--bg-elev); border: 1px solid var(--border); border-radius: 12px;
box-shadow: var(--shadow-lg); max-height: 420px; overflow-y: auto; display: none; z-index: 80; padding: 6px;
}
.search-results.open { display: block; }
.search-group-label { padding: 8px 10px 4px; }
.search-item { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 8px; cursor: pointer; }
.search-item:hover { background: var(--bg-sunken); }
.search-item .si-title { font-weight: 600; font-size: 13px; }
.search-item .si-sub { font-size: 12px; color: var(--text-3); }
.search-empty { padding: 24px; text-align: center; color: var(--text-3); font-size: 13px; }
.topbar-actions { display: flex; align-items: center; gap: 6px; margin-left: auto; }
.topbar-divider { width: 1px; height: 30px; background: var(--border); margin: 0 6px; }
.icon-btn { position: relative; width: 40px; height: 40px; border-radius: 10px; display: grid; place-items: center; color: var(--text-2); transition: .15s; }
.icon-btn:hover { background: var(--bg-sunken); color: var(--text); }
.icon-btn svg { width: 20px; height: 20px; }
.icon-sun { display: none; }
[data-theme="dark"] .icon-sun { display: block; }
[data-theme="dark"] .icon-moon { display: none; }
.dot { position: absolute; top: 9px; right: 10px; width: 8px; height: 8px; border-radius: 50%; border: 2px solid var(--bg-elev); }
.dot-red { background: var(--danger); }
.dot-blue { background: var(--info); }
.avatar { width: 36px; height: 36px; border-radius: 50%; display: grid; place-items: center; font-weight: 600; font-size: 13px; color: var(--avatar-fg); flex-shrink: 0; }
.avatar-grad { background: linear-gradient(135deg, var(--brand-green), var(--brand-mint)); color: #fff; }
.avatar-lg { width: 44px; height: 44px; font-size: 15px; }
.profile-btn { display: flex; align-items: center; gap: 10px; padding: 5px 8px 5px 5px; border-radius: 30px; transition: .15s; }
.profile-btn:hover { background: var(--bg-sunken); }
.profile-meta { display: flex; flex-direction: column; line-height: 1.2; text-align: left; }
.profile-name { font-weight: 600; font-size: 13px; }
.profile-role { font-size: 11.5px; color: var(--text-3); }
.chev { width: 16px; height: 16px; color: var(--text-3); }
/* ================= DROPDOWN ================= */
.dropdown { position: relative; }
.dropdown-menu {
position: absolute; top: calc(100% + 10px); right: 0; min-width: 230px;
background: var(--bg-elev); border: 1px solid var(--border); border-radius: 14px;
box-shadow: var(--shadow-lg); padding: 8px; opacity: 0; visibility: hidden;
transform: translateY(-6px); transition: .16s; z-index: 90;
}
.dropdown.open .dropdown-menu { opacity: 1; visibility: visible; transform: translateY(0); }
.dropdown-menu-wide { min-width: 340px; padding: 0; }
.dropdown-head { display: flex; justify-content: space-between; align-items: center; padding: 14px 16px; font-weight: 700; font-size: 14px; border-bottom: 1px solid var(--border); }
.dropdown-foot { padding: 10px 16px; border-top: 1px solid var(--border); text-align: center; }
.dropdown-foot a { color: var(--primary); font-weight: 600; font-size: 13px; }
.dropdown-profile { display: flex; gap: 12px; align-items: center; padding: 14px; }
.dp-name { font-weight: 600; }
.dp-email { font-size: 12px; color: var(--text-3); }
.dropdown-divider { height: 1px; background: var(--border); margin: 6px 0; }
.dropdown-link { display: flex; align-items: center; gap: 10px; padding: 9px 12px; border-radius: 8px; font-size: var(--fs-base); font-weight: 500; width: 100%; text-align: left; color: var(--text); }
.dropdown-link svg { width: 17px; height: 17px; color: var(--text-3); }
.dropdown-link:hover { background: var(--bg-sunken); }
.dropdown-link.danger { color: var(--danger); }
.dropdown-link.danger svg { color: var(--danger); }
.link-btn { color: var(--primary); font-size: 12px; font-weight: 600; }
/* Rendered as a <button> when clickable (keyboard-reachable); the global
button reset keeps the visuals, these two keep the layout. */
.notif-row { display: flex; gap: 12px; padding: 12px 16px; border-bottom: 1px solid var(--border); cursor: pointer; transition: .12s; width: 100%; text-align: left; }
.notif-row:hover { background: var(--bg-sunken); }
.notif-row.unread { background: var(--primary-soft); }
[data-theme="dark"] .notif-row.unread { background: var(--primary-soft); }
.notif-icn { width: 34px; height: 34px; border-radius: 9px; display: grid; place-items: center; flex-shrink: 0; }
.notif-icn svg { width: 16px; height: 16px; }
.notif-body { flex: 1; min-width: 0; }
.notif-title { font-size: var(--fs-sm); font-weight: 600; }
.notif-text { font-size: var(--fs-sm); color: var(--text-2); }
.notif-time { font-size: 11px; color: var(--text-3); margin-top: 3px; }
.dd-scroll { max-height: 360px; overflow-y: auto; overscroll-behavior: contain; }
/* ================= CONTENT / PAGE ================= */
/* No overscroll-behavior here: #app is min-height, so .content never overflows
and the DOCUMENT is the real scroller. `contain` on this (non-scrolling)
scroll container blocked wheel chaining — the wheel was dead everywhere
except dragging the scrollbar thumb. */
.content { flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 26px 30px 60px; }
.page { animation: fadeUp .3s ease; }
@keyframes fadeUp { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
.page-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-5); margin-bottom: var(--space-6); flex-wrap: wrap; }
.page-head-main { min-width: 0; }
.page-sub { color: var(--text-2); font-size: var(--fs-base); line-height: var(--lh-body); margin-top: 3px; max-width: 65ch; }
.page-head-actions { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.breadcrumb { display: flex; gap: 8px; align-items: center; font-size: var(--fs-sm); color: var(--text-3); margin-bottom: 10px; }
.breadcrumb svg { width: 14px; height: 14px; }
/* ================= BUTTONS ================= */
.btn {
display: inline-flex; align-items: center; justify-content: center; gap: 8px;
padding: 9px 16px; border-radius: var(--radius); font-weight: 600; font-size: var(--fs-base);
transition: .15s; white-space: nowrap; border: 1px solid transparent;
}
.btn svg { width: 17px; height: 17px; }
.btn-primary { background: var(--primary); color: var(--primary-fg); box-shadow: var(--shadow-sm); }
.btn-primary:hover { background: var(--primary-600); }
.btn-secondary { background: var(--bg-elev); color: var(--text); border-color: var(--border-strong); box-shadow: var(--shadow-sm); }
.btn-secondary:hover { background: var(--bg-sunken); }
.btn-ghost { background: transparent; color: var(--text-2); }
.btn-ghost:hover { background: var(--bg-sunken); color: var(--text); }
.btn-danger { background: var(--danger); color: var(--danger-fg); }
.btn-danger:hover { filter: brightness(.94); }
.btn-block { width: 100%; margin-top: 12px; }
.btn-sm { padding: 6px 12px; font-size: var(--fs-sm); }
.btn-icon { padding: 8px; width: 34px; height: 34px; }
.btn:disabled { opacity: .5; cursor: not-allowed; }
/* ================= CARDS ================= */
.card { background: var(--bg-elev); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-sm); }
.card-pad { padding: var(--space-5); }
.card-head { display: flex; align-items: center; justify-content: space-between; padding: var(--gap) var(--space-5); border-bottom: 1px solid var(--border); gap: var(--space-3); }
.card-head h3 { font-size: var(--fs-md); font-weight: 600; letter-spacing: -.2px; }
.card-head .ch-sub { font-size: var(--fs-sm); color: var(--text-3); font-weight: 400; }
.card-body { padding: var(--space-5); }
.grid { display: grid; gap: var(--gap); }
.g-kpi { grid-template-columns: repeat(4, 1fr); }
.g-3 { grid-template-columns: repeat(3, 1fr); }
.g-2 { grid-template-columns: repeat(2, 1fr); }
.g-2-1 { grid-template-columns: 2fr 1fr; }
.g-1-2 { grid-template-columns: 1fr 2fr; }
.mt-18 { margin-top: var(--gap); }
.mb-18 { margin-bottom: var(--gap); }
/* KPI card */
.kpi {
background: var(--bg-elev); border: 1px solid var(--border); border-radius: var(--radius-lg);
padding: 18px 20px; box-shadow: var(--shadow-sm); position: relative; overflow: hidden; transition: .18s;
}
.kpi:hover { box-shadow: var(--shadow-md); transform: translateY(-2px); }
.kpi-top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.kpi-label { font-size: var(--fs-sm); color: var(--text-2); font-weight: 500; }
.kpi-icn { width: 40px; height: 40px; border-radius: 11px; display: grid; place-items: center; }
.kpi-icn svg { width: 20px; height: 20px; }
.kpi-value { font-family: var(--font-display); font-size: 28px; font-weight: 600; letter-spacing: -0.02em; line-height: 1; }
.kpi-foot { display: flex; align-items: center; gap: 6px; margin-top: 10px; font-size: var(--fs-sm); }
.trend { display: inline-flex; align-items: center; gap: 3px; font-weight: 600; padding: 2px 7px; border-radius: var(--radius-sm); font-size: var(--fs-xs); }
.trend svg { width: 13px; height: 13px; }
.trend-up { color: var(--success); background: var(--success-soft); }
.trend-down { color: var(--danger); background: var(--danger-soft); }
.trend-flat { color: var(--text-2); background: var(--bg-sunken); }
.kpi-foot-text { color: var(--text-3); }
.i-indigo { background: var(--primary-soft); color: var(--primary); }
.i-green { background: var(--success-soft); color: var(--success); }
.i-amber { background: var(--warning-soft); color: var(--warning); }
.i-red { background: var(--danger-soft); color: var(--danger); }
.i-blue { background: var(--info-soft); color: var(--info); }
.i-purple { background: var(--purple-soft); color: var(--purple); }
.i-teal { background: var(--teal-soft); color: var(--teal); }
/* ================= BADGES ================= */
.badge { display: inline-flex; align-items: center; gap: 5px; padding: 3px 10px; border-radius: 20px; font-size: var(--fs-xs); font-weight: 600; white-space: nowrap; }
.badge::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.badge-plain::before { display: none; }
.b-green { color: var(--success); background: var(--success-soft); }
.b-amber { color: var(--warning); background: var(--warning-soft); }
.b-red { color: var(--danger); background: var(--danger-soft); }
.b-blue { color: var(--info); background: var(--info-soft); }
.b-purple { color: var(--purple); background: var(--purple-soft); }
.b-teal { color: var(--teal); background: var(--teal-soft); }
.b-gray { color: var(--text-2); background: var(--bg-sunken); }
.b-indigo { color: var(--primary); background: var(--primary-soft); }
/* ================= TABLES ================= */
/* Horizontal scroll is the right answer for wide data tables on phones;
make the gesture smooth and keep it from chaining to the page. */
.table-wrap { overflow-x: auto; overscroll-behavior-x: contain; -webkit-overflow-scrolling: touch; }
table.data { width: 100%; border-collapse: collapse; font-size: var(--fs-base); }
table.data thead th {
text-align: left; padding: var(--space-3) var(--space-4);
border-bottom: 1px solid var(--border); white-space: nowrap; background: var(--bg-elev); position: sticky; top: 0;
}
table.data thead th.sortable { cursor: pointer; user-select: none; }
table.data thead th.sortable:hover { color: var(--text); }
.sort-ind { display: inline-block; margin-left: 4px; opacity: .4; font-size: 10px; }
th.sorted-asc .sort-ind, th.sorted-desc .sort-ind { opacity: 1; color: var(--primary); }
table.data tbody td { padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--border); vertical-align: middle; }
table.data tbody tr { transition: background .12s; }
table.data tbody tr:hover { background: var(--bg-sunken); }
table.data tbody tr:last-child td { border-bottom: none; }
.cell-primary { font-weight: 600; color: var(--text); }
.cell-sub { font-size: var(--fs-xs); color: var(--text-3); line-height: 1.4; }
.cell-mono { font-family: var(--mono); font-size: var(--fs-sm); color: var(--text-2); }
.user-cell { display: flex; align-items: center; gap: 11px; min-width: 0; }
/* Long emails/roles under a name clip with an ellipsis on every viewport —
this was previously only applied inside the 640px media query. */
.user-cell .cell-sub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 240px; }
.user-cell .avatar { width: 34px; height: 34px; font-size: 12px; }
.row-actions { display: flex; gap: 4px; justify-content: flex-end; }
.act-btn { width: 30px; height: 30px; border-radius: 8px; display: grid; place-items: center; color: var(--text-3); transition: .12s; }
.act-btn:hover { background: var(--bg-sunken); color: var(--primary); }
.act-btn.danger:hover { color: var(--danger); background: var(--danger-soft); }
.act-btn svg { width: 16px; height: 16px; }
/* Toolbar */
.toolbar { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: var(--space-4); }
.toolbar-search { position: relative; flex: 1; min-width: 200px; max-width: 340px; }
.toolbar-search svg { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); width: 16px; height: 16px; color: var(--text-3); }
.toolbar-search input { width: 100%; padding: 8px 12px 8px 36px; border-radius: 9px; background: var(--bg-elev); border: 1px solid var(--border-strong); outline: none; }
.toolbar-search input:focus { border-color: var(--primary); box-shadow: var(--ring); }
.toolbar .spacer { flex: 1; }
.select {
padding: 8px 32px 8px 12px; border-radius: 9px; background: var(--bg-elev) var(--chev-url) no-repeat right 10px center;
background-size: 15px; border: 1px solid var(--border-strong); outline: none; cursor: pointer; appearance: none; font-weight: 500;
}
.select:focus { border-color: var(--primary); box-shadow: var(--ring); }
/* Pagination */
.pagination { display: flex; align-items: center; justify-content: space-between; padding: 14px 20px; border-top: 1px solid var(--border); flex-wrap: wrap; gap: 12px; }
.page-info { font-size: 13px; color: var(--text-2); }
.page-controls { display: flex; gap: 4px; align-items: center; flex-wrap: wrap; min-width: 0; }
.page-nav { display: flex; align-items: center; gap: 4px; min-width: 0; flex: 1 1 auto; justify-content: flex-end; }
.page-nums { display: flex; gap: 4px; align-items: center; min-width: 0; }
.page-size { display: flex; align-items: center; gap: 8px; margin-right: 8px; flex-shrink: 0; }
.page-size-label { font-size: 13px; color: var(--text-2); white-space: nowrap; }
.page-size-select { height: 34px; padding: 0 28px 0 10px; font-size: 13px; }
.page-size-input {
width: 72px; height: 34px; padding: 0 8px; font-size: 13px; font-weight: 600;
text-align: center; border-radius: 8px; border: 1px solid var(--border-strong);
background: var(--bg-elev); color: inherit; outline: none;
}
.page-size-input:focus { border-color: var(--primary); box-shadow: var(--ring); }
.page-size-total { font-size: 13px; color: var(--text-2); margin-right: 8px; white-space: nowrap; }
.page-btn { min-width: 34px; height: 34px; padding: 0 8px; border-radius: 8px; display: grid; place-items: center; font-size: 13px; font-weight: 600; color: var(--text-2); border: 1px solid transparent; }
.page-btn:hover:not(:disabled) { background: var(--bg-sunken); }
.page-btn.active { background: var(--primary); color: var(--primary-fg); }
.page-btn:disabled { opacity: .4; cursor: not-allowed; }
.page-btn svg { width: 16px; height: 16px; }
/* Progress */
.pbar { height: 7px; background: var(--bg-sunken); border-radius: 20px; overflow: hidden; }
.pbar-fill { height: 100%; border-radius: 20px; background: var(--primary); transition: width .5s ease; }
.pbar-fill.green { background: var(--success); }
.pbar-fill.amber { background: var(--warning); }
.pbar-fill.red { background: var(--danger); }
/* Score chip */
.score { display: inline-flex; align-items: center; gap: 6px; font-weight: 700; font-size: 13px; }
.score-ring { --pct: 0; position: relative; width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center;
background: conic-gradient(var(--sc-color) calc(var(--pct)*1%), var(--bg-sunken) 0); }
.score-ring::after { content: ''; position: absolute; inset: 4px; border-radius: 50%; background: var(--bg-elev); }
.score-ring span { position: relative; z-index: 1; font-size: 10px; font-weight: 700; }
/* ================= CHARTS ================= */
.chart-wrap { position: relative; width: 100%; }
/* Without an explicit width a canvas keeps its 300px intrinsic size, so
every chart rendered at 300px regardless of its card. width:100% lets
setup() measure the real container and size the backing store to it. */
canvas { width: 100%; max-width: 100%; display: block; }
.chart-legend { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 14px; justify-content: center; }
.legend-item { display: flex; align-items: center; gap: 7px; font-size: 12.5px; color: var(--text-2); }
.legend-dot { width: 10px; height: 10px; border-radius: 3px; flex-shrink: 0; }
.chart-tooltip {
position: fixed; background: var(--text); color: var(--bg-elev); padding: 7px 11px; border-radius: 8px;
font-size: 12px; font-weight: 600; pointer-events: none; opacity: 0; transition: opacity .12s; z-index: 200;
box-shadow: var(--shadow-lg); white-space: nowrap;
}
[data-theme="dark"] .chart-tooltip { background: var(--brand-lime); color: var(--brand-ink); }
/* ================= MODAL ================= */
.modal-root { position: fixed; inset: 0; z-index: 300; display: none; }
.modal-root.open { display: block; }
.modal-backdrop { position: absolute; inset: 0; background: rgba(10,22,24,.55); backdrop-filter: blur(3px); animation: fadeIn .2s; }
[data-theme="dark"] .modal-backdrop { background: rgba(0,0,0,.65); }
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
.modal {
position: relative; margin: 5vh auto; max-width: 640px; width: calc(100% - 40px);
background: var(--bg-elev); border-radius: var(--radius-xl); box-shadow: var(--shadow-lg);
animation: modalIn .25s cubic-bezier(.34,1.3,.64,1); max-height: 90vh; display: flex; flex-direction: column;
}
.modal-lg { max-width: 860px; }
.modal-xl { max-width: 1040px; }
@keyframes modalIn { from { opacity: 0; transform: translateY(24px) scale(.97); } to { opacity: 1; transform: none; } }
.modal-head { display: flex; align-items: flex-start; justify-content: space-between; padding: 22px 24px; border-bottom: 1px solid var(--border); }
.modal-head p { font-size: 13px; color: var(--text-3); margin-top: 3px; }
.modal-close { width: 34px; height: 34px; border-radius: 9px; display: grid; place-items: center; color: var(--text-3); }
.modal-close:hover { background: var(--bg-sunken); color: var(--text); }
.modal-body { padding: var(--space-6); overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
.modal-foot { display: flex; justify-content: flex-end; gap: 10px; padding: 18px 24px; border-top: 1px solid var(--border); background: var(--bg-sunken); border-radius: 0 0 var(--radius-xl) var(--radius-xl); }
/* ================= FORMS ================= */
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4); }
.form-field { display: flex; flex-direction: column; gap: 6px; }
.form-field.col-span-2 { grid-column: 1 / -1; }
.form-field label { font-size: var(--fs-sm); font-weight: 600; color: var(--text-2); line-height: var(--lh-label); }
.form-field label .req { color: var(--danger); }
.form-field input, .form-field select, .form-field textarea {
padding: 9px 12px; border-radius: 9px; background: var(--bg-elev); border: 1px solid var(--border-strong); outline: none; transition: .15s; width: 100%;
}
.form-field select { appearance: none; background: var(--bg-elev) var(--chev-url) no-repeat right 12px center; background-size: 15px; cursor: pointer; }
.form-field textarea { resize: vertical; min-height: 84px; }
.form-field input:focus, .form-field select:focus, .form-field textarea:focus { border-color: var(--primary); box-shadow: var(--ring); }
.form-field input.err, .form-field select.err, .form-field textarea.err { border-color: var(--danger); }
.field-error { font-size: var(--fs-xs); color: var(--danger); display: none; }
.field-error.show { display: block; }
.form-section-title { margin: var(--space-5) 0 var(--space-1); grid-column: 1/-1; }
/* AI field assist (ui/AiFieldAssist.jsx) */
.field-label-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.ai-assist { position: relative; display: inline-flex; }
.ai-assist-btn { display: inline-grid; place-items: center; width: 22px; height: 22px; border-radius: 6px; color: var(--primary); background: transparent; transition: .15s; }
.ai-assist-btn svg { width: 14px; height: 14px; }
.ai-assist-btn:hover, .ai-assist-btn.active { background: var(--primary-soft); }
.ai-assist-btn:disabled { opacity: .4; cursor: not-allowed; }
.ai-assist-panel {
position: absolute; top: calc(100% + 6px); right: 0; z-index: 95; min-width: 250px; max-width: 340px;
background: var(--bg-elev); border: 1px solid var(--border); border-radius: 12px;
box-shadow: var(--shadow-lg); padding: 8px;
}
.ai-assist-panel .dropdown-link:disabled { opacity: .45; cursor: not-allowed; }
.ai-assist-status { display: flex; align-items: center; gap: 10px; padding: 10px 12px; font-size: 13px; color: var(--text-2); }
.ai-assist-spinner { width: 14px; height: 14px; border-radius: 50%; flex-shrink: 0; border: 2px solid var(--border-strong); border-top-color: var(--primary); animation: aiAssistSpin .7s linear infinite; }
@keyframes aiAssistSpin { to { transform: rotate(360deg); } }
.ai-assist-preview { font-size: 13px; color: var(--text-2); background: var(--bg-sunken); border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px; margin: 4px 4px 8px; max-height: 220px; overflow-y: auto; }
.ai-assist-preview.multiline { white-space: pre-wrap; }
.ai-assist-error { font-size: 12.5px; color: var(--danger); padding: 10px 12px 6px; }
.ai-assist-hint { font-size: 11.5px; color: var(--text-3); padding: 2px 12px 8px; }
.ai-assist-actions { display: flex; justify-content: flex-end; gap: 6px; padding: 0 4px 4px; }
/* Switch */
.switch { position: relative; display: inline-flex; align-items: center; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch-track { width: 42px; height: 24px; border-radius: 20px; background: var(--border-strong); position: relative; transition: .2s; cursor: pointer; }
.switch-track::after { content: ''; position: absolute; top: 3px; left: 3px; width: 18px; height: 18px; border-radius: 50%; background: #fff; transition: .2s; box-shadow: var(--shadow-sm); }
.switch input:checked + .switch-track { background: var(--primary); }
.switch input:checked + .switch-track::after { background: var(--primary-fg); }
.switch input:checked + .switch-track::after { transform: translateX(18px); }
.setting-row { display: flex; align-items: center; justify-content: space-between; padding: 16px 0; border-bottom: 1px solid var(--border); gap: 20px; }
.setting-row:last-child { border-bottom: none; }
.setting-info h4 { font-size: 14px; font-weight: 600; }
.setting-info p { font-size: 13px; color: var(--text-3); margin-top: 2px; }
/* ================= TABS ================= */
.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--border); margin-bottom: var(--space-5); overflow-x: auto; }
.tab { display: inline-flex; align-items: center; gap: 8px; padding: 11px 16px; font-weight: 600; font-size: var(--fs-base); color: var(--text-2); border-bottom: 2px solid transparent; white-space: nowrap; transition: .15s; margin-bottom: -1px; }
.tab:hover { color: var(--text); }
.tab.active { color: var(--primary); border-bottom-color: var(--primary); }
.tab-pane { display: none; animation: fadeUp .25s; }
.tab-pane.active { display: block; }
.pill-tabs { display: inline-flex; gap: 4px; background: var(--bg-sunken); padding: 4px; border-radius: 11px; }
.pill-tab { padding: 7px 14px; border-radius: 8px; font-weight: 600; font-size: var(--fs-sm); color: var(--text-2); transition: .15s; display: inline-flex; align-items: center; gap: 6px; border: none; background: transparent; cursor: pointer; }
.pill-tab svg { width: 14px; height: 14px; }
.pill-tab.active { background: var(--bg-elev); color: var(--text); box-shadow: var(--shadow-sm); }
/* ================= KANBAN ================= */
.kanban { display: flex; gap: 16px; overflow-x: auto; overscroll-behavior-x: contain; -webkit-overflow-scrolling: touch; padding-bottom: 12px; align-items: flex-start; scroll-snap-type: x proximity; }
.kanban-col { flex: 0 0 288px; background: var(--bg-sunken); border-radius: var(--radius-lg); display: flex; flex-direction: column; max-height: calc(100vh - 220px); max-height: calc(100dvh - 220px); }
.kanban-col-head { display: flex; align-items: center; gap: 8px; padding: 14px 16px; position: sticky; top: 0; }
.kanban-col-head .k-dot { width: 9px; height: 9px; border-radius: 50%; }
.kanban-col-head h4 { font-size: 13.5px; font-weight: 700; }
.k-count { margin-left: auto; background: var(--bg-elev); color: var(--text-2); font-size: var(--fs-xs); font-weight: 700; padding: 1px 9px; border-radius: 20px; }
.kanban-cards { padding: 0 12px 12px; display: flex; flex-direction: column; gap: 10px; overflow-y: auto; min-height: 60px; }
.kanban-cards.drag-over { background: var(--primary-soft); border-radius: 10px; outline: 2px dashed var(--primary); outline-offset: -4px; }
.k-card { background: var(--bg-elev); border: 1px solid var(--border); border-radius: 11px; padding: 13px; cursor: grab; box-shadow: var(--shadow-sm); transition: .15s; }
.k-card:hover { box-shadow: var(--shadow-md); border-color: var(--border-strong); }
.k-card.dragging { opacity: .5; transform: rotate(2deg); cursor: grabbing; }
.k-card-top { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.k-card-top .avatar { width: 32px; height: 32px; font-size: 11px; }
.kc-name { font-weight: 600; font-size: var(--fs-base); }
.kc-role { font-size: 12px; color: var(--text-3); }
.k-card-meta { display: flex; align-items: center; justify-content: space-between; margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border); }
.k-tags { display: flex; gap: 5px; flex-wrap: wrap; margin-top: 8px; }
.tag { font-size: var(--fs-xs); font-weight: 600; padding: 2px 8px; border-radius: var(--radius-sm); background: var(--bg-sunken); color: var(--text-2); }
/* ================= MISC ================= */
.list-tight > * + * { border-top: 1px solid var(--border); }
.list-row { display: flex; align-items: center; gap: 12px; padding: 13px 0; }
.list-row:first-child { padding-top: 0; }
.list-row .avatar { width: 38px; height: 38px; font-size: 13px; }
.lr-main { flex: 1; min-width: 0; }
.lr-title { font-weight: 600; font-size: var(--fs-base); }
.lr-sub { font-size: var(--fs-sm); color: var(--text-3); }
.lr-right { text-align: right; flex-shrink: 0; }
.timeline { position: relative; padding-left: 28px; }
.timeline::before { content: ''; position: absolute; left: 9px; top: 4px; bottom: 4px; width: 2px; background: var(--border); }
.tl-item { position: relative; padding-bottom: 22px; }
.tl-item:last-child { padding-bottom: 0; }
.tl-dot { position: absolute; left: -28px; top: 2px; width: 20px; height: 20px; border-radius: 50%; background: var(--bg-elev); border: 2px solid var(--primary); display: grid; place-items: center; }
.tl-dot svg { width: 11px; height: 11px; color: var(--primary); }
.tl-title { font-weight: 600; font-size: var(--fs-base); }
.tl-meta { font-size: 12px; color: var(--text-3); margin-top: 2px; }
.tl-desc { font-size: 13px; color: var(--text-2); margin-top: 5px; }
.empty-state { text-align: center; padding: 60px 20px; color: var(--text-3); }
.empty-state svg { width: 48px; height: 48px; margin-bottom: 14px; opacity: .5; }
.empty-state h3 { font-size: var(--fs-lg); color: var(--text-2); margin-bottom: 6px; }
.empty-state p { max-width: 46ch; margin: 0 auto; line-height: var(--lh-body); }
.empty-state-body { margin-top: 4px; }
.empty-state-body p { margin: 0 0 10px; }
.avatar-stack { display: flex; }
.avatar-stack .avatar { width: 30px; height: 30px; font-size: 11px; border: 2px solid var(--bg-elev); margin-left: -8px; }
.avatar-stack .avatar:first-child { margin-left: 0; }
.more-count { width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center; background: var(--bg-sunken); color: var(--text-2); font-size: 11px; font-weight: 700; border: 2px solid var(--bg-elev); margin-left: -8px; }
.stat-mini { display: flex; flex-direction: column; gap: 4px; }
.stat-mini-val { font-family: var(--font-display); font-size: 22px; font-weight: 600; letter-spacing: -0.015em; }
.stat-mini-lbl { font-size: var(--fs-sm); color: var(--text-3); }
.divider { height: 1px; background: var(--border); margin: 16px 0; }
.flex { display: flex; }
.flex-col { flex-direction: column; }
.items-center { align-items: center; }
.justify-between { justify-content: space-between; }
.flex-wrap { flex-wrap: wrap; }
.flex-1 { flex: 1 1 0%; min-width: 0; }
.min-w-0 { min-width: 0; }
.w-full { width: 100%; }
.gap-4 { gap: var(--space-1); }
.gap-8 { gap: 8px; } .gap-12 { gap: 12px; } .gap-16 { gap: 16px; }
.mt-8 { margin-top: var(--space-2); } .mb-8 { margin-bottom: var(--space-2); }
.mt-12 { margin-top: var(--space-3); } .mb-12 { margin-bottom: var(--space-3); }
.mt-16 { margin-top: var(--space-4); } .mb-16 { margin-bottom: var(--space-4); }
.mt-24 { margin-top: var(--space-6); } .mb-24 { margin-bottom: var(--space-6); }
.text-muted { color: var(--text-3); }
.fw-600 { font-weight: 600; }
.text-sm { font-size: var(--fs-sm); }
.mono { font-family: var(--mono); }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.clamp-2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
/* Inline clamp for table cells (emails, long titles); pair with title="". */
.cell-clip { display: inline-block; max-width: 26ch; vertical-align: bottom;
overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row-click { cursor: pointer; }
/* Classes referenced from JSX that previously had no definition. */
.dt { display: flow-root; }
.route-loading { display: grid; place-items: center; min-height: 40vh; }
.tab-count { font-size: var(--fs-xs); font-weight: 600; padding: 1px 8px;
border-radius: 20px; background: var(--bg-sunken); color: var(--text-2); }
.tab.active .tab-count { background: var(--primary-soft); color: var(--primary); }
/* Skeleton loading (primitives.jsx SkeletonRows). The sweep uses --border,
which tracks the theme, so no per-theme rules are needed. */
.skeleton {
position: relative; overflow: hidden;
background: var(--bg-sunken); border-radius: var(--radius-sm);
}
.skeleton::after {
content: ''; position: absolute; inset: 0; transform: translateX(-100%);
background: linear-gradient(90deg, transparent, var(--border), transparent);
animation: skeletonSweep 1.4s infinite;
}
@keyframes skeletonSweep { to { transform: translateX(100%); } }
.skeleton-row { display: flex; align-items: center; gap: 12px; padding: 13px 0; }
.skeleton-row + .skeleton-row { border-top: 1px solid var(--border); }
.skeleton-avatar { width: 34px; height: 34px; border-radius: 50%; flex-shrink: 0; }
.skeleton-line { display: block; height: 11px; }
.skeleton-line + .skeleton-line { margin-top: 7px; }
/* Keyboard users jump straight past the 20+ sidebar links. */
.skip-link { position: absolute; left: -9999px; z-index: 1000; }
.skip-link:focus {
left: 12px; top: 12px; position: fixed; background: var(--bg-elev);
color: var(--text); padding: 10px 16px; border-radius: var(--radius-sm);
box-shadow: var(--shadow-lg); outline: 2px solid var(--primary);
}
/* Calendar */
.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1px; background: var(--border); border: 1px solid var(--border); border-radius: 12px; overflow: hidden; }
.cal-dow { background: var(--bg-elev); padding: 10px; text-align: center; }
.cal-cell { background: var(--bg-elev); min-height: 108px; padding: 8px; position: relative; transition: .12s; }
.cal-cell:hover { background: var(--bg-sunken); }
.cal-cell.other { background: var(--bg-sunken); }
.cal-date { font-size: 12.5px; font-weight: 600; color: var(--text-2); }
.cal-cell.today .cal-date { background: var(--primary); color: var(--primary-fg); width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center; }
.cal-cell.other .cal-date { color: var(--text-3); }
.cal-event { font-size: 11px; font-weight: 600; padding: 3px 6px; border-radius: 5px; margin-top: 4px; cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Toast */
.toast-root { position: fixed; bottom: 24px; right: 24px; z-index: 500; display: flex; flex-direction: column; gap: 10px; }
.toast { display: flex; align-items: center; gap: 12px; background: var(--bg-elev); border: 1px solid var(--border); border-radius: 12px; padding: 13px 16px; box-shadow: var(--shadow-lg); min-width: 300px; max-width: 400px; animation: toastIn .3s cubic-bezier(.34,1.3,.64,1); }
@keyframes toastIn { from { opacity: 0; transform: translateX(40px); } to { opacity: 1; transform: none; } }
.toast.out { animation: toastOut .3s forwards; }
@keyframes toastOut { to { opacity: 0; transform: translateX(40px); } }
.toast-icn { width: 34px; height: 34px; border-radius: 9px; display: grid; place-items: center; flex-shrink: 0; }
.toast-icn svg { width: 18px; height: 18px; }
.toast-body { flex: 1; }
.toast-title { font-weight: 600; font-size: var(--fs-base); }
.toast-msg { font-size: var(--fs-sm); color: var(--text-3); }
.toast-close { color: var(--text-3); width: 24px; height: 24px; display: grid; place-items: center; border-radius: 6px; }
.toast-close:hover { background: var(--bg-sunken); }
/* Scrim */
.scrim { position: fixed; inset: 0; background: rgba(10,22,24,.55); z-index: 55; display: none; }
.scrim.open { display: block; }
/* Tooltip */
[data-tip] { position: relative; }
[data-tip]::after { content: attr(data-tip); position: absolute; bottom: calc(100% + 8px); left: 50%; transform: translateX(-50%); background: var(--text); color: var(--bg-elev); padding: 5px 9px; border-radius: 7px; font-size: 11.5px; font-weight: 600; white-space: nowrap; opacity: 0; pointer-events: none; transition: .15s; z-index: 100; }
[data-tip]:hover::after { opacity: 1; }
/* Hover tooltips have no dismiss gesture on touch and stick after a tap. */
@media (hover: none) { [data-tip]::after { content: none; } }
[data-theme="dark"] [data-tip]::after { background: var(--brand-lime); color: var(--brand-ink); }
/* Segmented insight bars */
.mini-bars { display: flex; align-items: flex-end; gap: 3px; height: 40px; }
.mini-bar { flex: 1; background: var(--primary-soft); border-radius: 3px 3px 0 0; min-height: 4px; transition: .3s; }
.mini-bar.hl { background: var(--primary); }
/* Profile header */
.profile-hero { display: flex; gap: 18px; align-items: center; margin-bottom: 4px; }
.profile-hero .avatar { width: 68px; height: 68px; font-size: 24px; }
.ph-role { color: var(--text-2); font-size: 14px; }
.ph-tags { display: flex; gap: 8px; margin-top: 8px; flex-wrap: wrap; }
.info-grid { display: grid; grid-template-columns: repeat(2,1fr); gap: 14px 24px; }
.info-item .iv { font-size: var(--fs-base); font-weight: 500; margin-top: 3px; }
/* ================= ENTERPRISE PHASE 2 ================= */
/* Split inbox layout */
.split { display: grid; grid-template-columns: 380px 1fr; gap: 0; min-height: 560px; }
.split-list { border-right: 1px solid var(--border); overflow-y: auto; overscroll-behavior: contain; max-height: calc(100vh - 260px); max-height: calc(100dvh - 260px); }
.split-detail { overflow-y: auto; overscroll-behavior: contain; max-height: calc(100vh - 260px); max-height: calc(100dvh - 260px); }
.inbox-item { display: flex; gap: 12px; padding: 14px 18px; border-bottom: 1px solid var(--border); cursor: pointer; transition: .12s; position: relative; }
.inbox-item:hover { background: var(--bg-sunken); }
.inbox-item.active { background: var(--primary-soft); }
[data-theme="dark"] .inbox-item.active { background: var(--primary-soft); }
.inbox-item.unread::before { content: ''; position: absolute; left: 6px; top: 50%; transform: translateY(-50%); width: 6px; height: 6px; border-radius: 50%; background: var(--primary); }
.inbox-item.unread .ii-name { font-weight: 700; }
.ii-main { flex: 1; min-width: 0; }
/* The name text is wrapped in a .truncate span in the JSX — email-style
sender names have no break points and used to paint over the timestamp. */
.ii-name { font-weight: 600; font-size: var(--fs-base); display: flex; align-items: center; gap: 6px; min-width: 0; }
.ii-pos { font-size: 12.5px; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ii-meta { display: flex; align-items: center; gap: 8px; margin-top: 5px; }
.ii-time { font-size: 11px; color: var(--text-3); white-space: nowrap; }
/* Inbox sidebar only: fit the list instead of scrolling sideways.
Username (.ii-name) and subject (.ii-pos) are left alone. */
.inbox-split { grid-template-columns: minmax(0, 420px) 1fr; }
.inbox-queue { overflow-x: hidden; min-width: 0; }
.inbox-queue .inbox-item { min-width: 0; }
/* Name + time on row 1, subject on row 2, chips span the full width under
the timestamp so a board address stays on one line. */
.inbox-queue .ii-main {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
column-gap: 12px;
align-items: start;
}
.inbox-queue .ii-name { grid-column: 1; grid-row: 1; }
.inbox-queue .ii-pos { grid-column: 1; grid-row: 2; }
.inbox-queue .ii-aside { grid-column: 2; grid-row: 1 / span 2; text-align: right; }
.inbox-queue .ii-meta {
grid-column: 1 / -1;
grid-row: 3;
flex-wrap: wrap;
min-width: 0;
overflow: visible;
row-gap: 6px;
}
/* One-line To-address pill: grow with the address, never wrap (wrapping
stretched the chip taller). Badges sit on the next row. */
.inbox-queue .source-chip {
flex: 0 0 auto;
width: max-content;
max-width: 100%;
overflow: visible;
white-space: nowrap;
line-height: 1.25;
}
.inbox-queue .source-chip-label {
white-space: nowrap;
overflow-wrap: normal;
word-break: normal;
}
.inbox-queue .toolbar-search { min-width: 0; }
.inbox-queue .pagination {
flex-direction: column;
align-items: stretch;
gap: 8px;
padding: 10px 12px;
overflow: visible;
}
.inbox-queue .page-info { width: 100%; }
.inbox-queue .page-controls { flex-wrap: wrap; }
.inbox-queue .page-nav {
justify-content: flex-start;
flex: 1 1 100%;
width: 100%;
}
.inbox-bulk-bar {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 12px;
border-bottom: 1px solid var(--border);
flex-wrap: nowrap;
min-width: 0;
}
.inbox-bulk-count {
flex: 1 1 auto;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 12px;
color: var(--text-3);
}
.inbox-bulk-actions {
display: flex;
align-items: center;
gap: 4px;
flex-shrink: 0;
}
.inbox-bulk-actions .btn-sm {
padding: 5px 8px;
font-size: 12px;
white-space: nowrap;
}
/* `--chip` is the source's own brand colour, set inline. It tints the
background and fills the dot, while the label stays on theme text so
11px copy keeps its contrast in both modes. */
.source-chip {
display: inline-flex; align-items: center; gap: 5px;
font-size: var(--fs-xs); font-weight: 600; line-height: 1.35;
padding: 3px 8px; border-radius: 20px;
--chip: var(--text-3);
color: var(--text-2);
background: var(--bg-sunken); /* fallback: color-mix needs Safari 16.2+ / Chrome 111+ */
background: color-mix(in srgb, var(--chip) 14%, transparent);
}
.source-chip svg { width: 12px; height: 12px; color: var(--chip); }
.source-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; background: var(--chip); }
.source-chip-label { min-width: 0; }
.integration-status { display: inline-flex; align-items: center; gap: 8px; padding: 6px 12px; border-radius: 20px; font-size: var(--fs-sm); font-weight: 600; background: var(--success-soft); color: var(--success); }
.integration-status.pending { background: var(--warning-soft); color: var(--warning); }
.integration-status .pulse { width: 8px; height: 8px; border-radius: 50%; background: currentColor; position: relative; }
.integration-status .pulse::after { content: ''; position: absolute; inset: 0; border-radius: 50%; background: currentColor; animation: pulse 1.8s infinite; }
@keyframes pulse { 0% { transform: scale(1); opacity: .7; } 100% { transform: scale(3); opacity: 0; } }
.email-preview { background: var(--bg-sunken); border: 1px solid var(--border); border-radius: 12px; padding: 18px; white-space: pre-wrap; font-size: 13.5px; line-height: 1.7; color: var(--text-2); }
.attach-card { display: flex; align-items: center; gap: 12px; padding: 14px; border: 1px solid var(--border); border-radius: 12px; background: var(--bg-elev); }
.attach-icn { width: 42px; height: 42px; border-radius: 10px; background: var(--danger-soft); color: var(--danger); display: grid; place-items: center; }
.resume-thumb { border: 1px solid var(--border); border-radius: 10px; background: var(--bg-sunken); padding: 20px; font-family: var(--mono); font-size: 11px; color: var(--text-2); line-height: 1.8; max-height: 300px; overflow: hidden; position: relative; }
.resume-thumb::after { content: ''; position: absolute; bottom: 0; left: 0; right: 0; height: 60px; background: linear-gradient(transparent, var(--bg-sunken)); }
/* Untruncated variant. The base is a thumbnail: 300px tall, clipped, with a fade
over the last 60px. Raising max-height alone still leaves that fade washing out
the closing lines, which is the opposite of showing the whole text. */
.resume-thumb.is-full { max-height: none; overflow: visible; white-space: pre-wrap; word-break: break-word; }
.resume-thumb.is-full::after { content: none; }
.resume-thumb .rt-subject { display: block; color: var(--text); font-weight: 600; margin-bottom: 12px; padding-bottom: 12px; border-bottom: 1px solid var(--border); }
/* Email viewer: a header strip joined to the body below it, Outlook-style. The
body is either an iframe (HTML mail, see ui/EmailBody.jsx) or a <pre> for
plain text — both square off their top corners to meet the header. */
.email-head { border: 1px solid var(--border); border-bottom: none; border-radius: 10px 10px 0 0; background: var(--bg-elev); padding: 10px 14px; font-weight: 600; color: var(--text); font-size: 13px; overflow-wrap: break-word; }
.email-frame { display: block; width: 100%; border: 1px solid var(--border); border-radius: 0 0 10px 10px; background: var(--bg-sunken); }
.email-plain { border-radius: 0 0 10px 10px; }
/* Upload dropzone */
/* Job detail cover image — banner above the info grid. */
.job-cover { display: block; width: 100%; max-height: 200px; object-fit: cover; border-radius: var(--radius); border: 1px solid var(--border); background: var(--bg-sunken); margin-bottom: 18px; }
.dropzone { border: 2px dashed var(--border-strong); border-radius: var(--radius-lg); padding: 48px 24px; text-align: center; transition: .18s; background: var(--bg-sunken); cursor: pointer; }
.dropzone.drag { border-color: var(--primary); background: var(--primary-soft); transform: scale(1.005); }
.dropzone .dz-icn { width: 64px; height: 64px; border-radius: 18px; background: var(--primary-soft); color: var(--primary); display: grid; place-items: center; margin: 0 auto 16px; }
.dropzone .dz-icn svg { width: 30px; height: 30px; }
.dropzone h3 { font-size: 17px; margin-bottom: 6px; }
.upload-row { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border: 1px solid var(--border); border-radius: 11px; margin-top: 10px; background: var(--bg-elev); }
.upload-progress { height: 5px; background: var(--bg-sunken); border-radius: 20px; overflow: hidden; flex: 1; }
.upload-progress-fill { height: 100%; background: var(--primary); border-radius: 20px; transition: width .2s; }
/* ATS match ring big */
.ats-ring { --pct: 0; --c: var(--primary); position: relative; width: 120px; height: 120px; border-radius: 50%; display: grid; place-items: center; margin: 0 auto;
background: conic-gradient(var(--c) calc(var(--pct)*1%), var(--bg-sunken) 0); }
.ats-ring::after { content: ''; position: absolute; inset: 12px; border-radius: 50%; background: var(--bg-elev); }
.ats-ring .ats-val { position: relative; z-index: 1; text-align: center; }
.ats-ring .ats-num { font-family: var(--font-display); font-size: 30px; font-weight: 700; letter-spacing: -0.02em; line-height: 1; }
.ats-ring .ats-lbl { font-size: 11px; color: var(--text-3); font-weight: 600; }
.skill-pill { display: inline-flex; align-items: center; gap: 5px; font-size: var(--fs-xs); font-weight: 600; padding: 4px 10px; border-radius: var(--radius-sm); }
.skill-pill svg { width: 12px; height: 12px; }
.skill-matched { background: var(--success-soft); color: var(--success); }
.skill-missing { background: var(--danger-soft); color: var(--danger); }
/* Per-job scored-candidate cards (JobCandidates.jsx). Every zone has a fixed
height so the grid rows align regardless of how much text a CV produced. */
.cand-card { display: flex; flex-direction: column; cursor: pointer; transition: .15s; }
.cand-card:hover { border-color: var(--border-strong); box-shadow: var(--shadow-sm); transform: translateY(-1px); }
.cand-card > .card-body { display: flex; flex-direction: column; flex: 1; padding: 18px; }
.cand-head { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.cand-id { flex: 1; min-width: 0; }
.cand-name { font-weight: 700; font-size: 14.5px; letter-spacing: -.1px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cand-role { font-size: 12.5px; color: var(--text-3); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cand-skills { display: flex; flex-wrap: wrap; gap: 6px; align-content: flex-start; height: 54px; overflow: hidden; margin-bottom: 12px; }
.cand-chip { display: inline-flex; align-items: center; gap: 4px; height: 24px; padding: 0 10px; border-radius: var(--radius-sm); font-size: var(--fs-xs); font-weight: 600; background: var(--bg-sunken); color: var(--text-2); white-space: nowrap; }
.cand-chip svg { width: 11px; height: 11px; }
.cand-chip.miss { background: var(--danger-soft); color: var(--danger); }
.cand-chip.more { background: transparent; color: var(--text-3); padding: 0 4px; }
.cand-crit { font-size: 13px; line-height: 1.55; color: var(--text-2); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; height: 60px; margin-bottom: 14px; }
.cand-foot { margin-top: auto; display: flex; align-items: center; gap: 10px; padding-top: 12px; border-top: 1px solid var(--border); }
.cand-meta { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; color: var(--text-3); white-space: nowrap; flex-shrink: 0; }
.cand-meta svg { width: 13px; height: 13px; }
.cand-company { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; color: var(--text-3); }
/* Platform publish card */
.platform-card { display: flex; align-items: center; gap: 14px; padding: 16px; border: 1px solid var(--border); border-radius: 14px; transition: .15s; cursor: pointer; background: var(--bg-elev); }
.platform-card:hover { border-color: var(--border-strong); box-shadow: var(--shadow-sm); }
.platform-card.selected { border-color: var(--primary); box-shadow: var(--ring); background: var(--primary-soft); }
[data-theme="dark"] .platform-card.selected { background: var(--primary-soft); }
.platform-logo { width: 44px; height: 44px; border-radius: 11px; display: grid; place-items: center; color: #fff; flex-shrink: 0; }
.platform-check { width: 22px; height: 22px; border-radius: 6px; border: 2px solid var(--border-strong); display: grid; place-items: center; margin-left: auto; flex-shrink: 0; transition: .15s; }
.platform-card.selected .platform-check { background: var(--primary); border-color: var(--primary); color: var(--primary-fg); }
.platform-check svg { width: 14px; height: 14px; opacity: 0; }
.platform-card.selected .platform-check svg { opacity: 1; }
/* Stepper */
.stepper { display: flex; align-items: center; margin-bottom: 24px; }
.step { display: flex; align-items: center; gap: 10px; }
.step-num { width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center; font-weight: 700; font-size: 13px; background: var(--bg-sunken); color: var(--text-3); border: 2px solid var(--border); }
.step.active .step-num { background: var(--primary); color: var(--primary-fg); border-color: var(--primary); }
.step.done .step-num { background: var(--success); color: var(--success-fg); border-color: var(--success); }
.step-label { font-size: 13px; font-weight: 600; color: var(--text-3); }
.step.active .step-label, .step.done .step-label { color: var(--text); }
.step-line { flex: 1; height: 2px; background: var(--border); margin: 0 14px; min-width: 20px; }
.step.done + .step-line, .step-line.done { background: var(--success); }
/* Heatmap */
.heatmap { display: grid; grid-template-columns: 40px repeat(5, 1fr); gap: 5px; }
.hm-label { font-size: 11px; color: var(--text-3); display: flex; align-items: center; }
.hm-cell { aspect-ratio: 1.4; border-radius: 5px; background: var(--bg-sunken); transition: .15s; cursor: pointer; }
.hm-cell:hover { outline: 2px solid var(--primary); }
.hm-legend { display: flex; align-items: center; gap: 4px; justify-content: flex-end; margin-top: 10px; font-size: 11px; color: var(--text-3); }
.hm-legend .hm-box { width: 13px; height: 13px; border-radius: 3px; }
/* Leaderboard */
.leader-row { display: flex; align-items: center; gap: 14px; padding: 12px 0; border-bottom: 1px solid var(--border); }
.leader-row:last-child { border-bottom: none; }
.leader-rank { width: 28px; height: 28px; border-radius: 8px; display: grid; place-items: center; font-weight: 800; font-size: 13px; background: var(--bg-sunken); color: var(--text-2); flex-shrink: 0; }
.leader-rank.gold { background: var(--accent); color: var(--accent-fg); }
.leader-rank.silver { background: var(--success-soft); color: var(--success); }
.leader-rank.bronze { background: var(--warning-soft); color: var(--warning); }
/* RBAC matrix (Microsoft admin center style) */
.rbac-layout { display: grid; grid-template-columns: 280px 1fr; gap: 18px; }
.role-list { display: flex; flex-direction: column; gap: 6px; }
.role-item { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border-radius: 11px; cursor: pointer; border: 1px solid transparent; transition: .12s; }
.role-item:hover { background: var(--bg-sunken); }
.role-item.active { background: var(--primary-soft); border-color: var(--primary); }
[data-theme="dark"] .role-item.active { background: var(--primary-soft); }
/* Role chips use the avatar ramp, which inverts with the theme. */
.role-badge { width: 38px; height: 38px; border-radius: 10px; display: grid; place-items: center; color: var(--avatar-fg); flex-shrink: 0; }
.rbac-matrix { width: 100%; border-collapse: collapse; font-size: 13px; }
.rbac-matrix th { padding: 12px 8px; border-bottom: 1px solid var(--border); text-align: center; }
.rbac-matrix th:first-child { text-align: left; padding-left: 16px; }
.rbac-matrix td { padding: 10px 8px; border-bottom: 1px solid var(--border); text-align: center; }
.rbac-matrix td:first-child { text-align: left; padding-left: 16px; font-weight: 600; }
.perm-check { width: 22px; height: 22px; border-radius: 6px; border: 2px solid var(--border-strong); display: inline-grid; place-items: center; cursor: pointer; transition: .12s; }
.perm-check.on { background: var(--primary); border-color: var(--primary); color: var(--primary-fg); }
.perm-check.on svg { width: 13px; height: 13px; }
.perm-check:not(.on) svg { display: none; }
/* AI Assistant chat */
.chat-wrap { display: flex; flex-direction: column; height: calc(100vh - 190px); height: calc(100dvh - 190px); }
.chat-scroll { flex: 1; overflow-y: auto; padding: 8px 4px 20px; }
.chat-msg { display: flex; gap: 12px; margin-bottom: 22px; max-width: 820px; }
.chat-msg .chat-av { width: 32px; height: 32px; border-radius: 9px; display: grid; place-items: center; flex-shrink: 0; color: #fff; }
.chat-av.ai { background: linear-gradient(135deg, var(--brand-green), var(--brand-mint)); }
.chat-av.user { background: var(--bg-sunken); color: var(--text-2); }
.chat-bubble { padding-top: 3px; }
.chat-role { font-weight: 700; font-size: 13px; margin-bottom: 4px; }
.chat-text { font-size: 14px; line-height: 1.65; color: var(--text); }
.chat-text p { margin-bottom: 10px; }
.chat-text ul { padding-left: 20px; margin-bottom: 10px; }
.chat-text li { margin-bottom: 4px; }
.chat-typing span { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: var(--text-3); margin-right: 3px; animation: typing 1.2s infinite; }
.chat-typing span:nth-child(2) { animation-delay: .2s; }
.chat-typing span:nth-child(3) { animation-delay: .4s; }
@keyframes typing { 0%,60%,100% { opacity: .3; transform: translateY(0); } 30% { opacity: 1; transform: translateY(-3px); } }
.chat-input-bar { border: 1px solid var(--border-strong); border-radius: 16px; padding: 10px 12px; display: flex; gap: 10px; align-items: flex-end; background: var(--bg-elev); box-shadow: var(--shadow-sm); }
.chat-input-bar:focus-within { border-color: var(--primary); box-shadow: var(--ring); }
.chat-input-bar textarea { flex: 1; border: none; outline: none; resize: none; background: transparent; font-size: 14px; max-height: 140px; line-height: 1.5; padding: 6px 4px; }
.chat-send { width: 38px; height: 38px; border-radius: 10px; background: var(--primary); color: var(--primary-fg); display: grid; place-items: center; flex-shrink: 0; transition: .15s; }
.chat-send:hover { background: var(--primary-600); }
.chat-send:disabled { opacity: .4; }
.prompt-chip { display: inline-flex; align-items: center; gap: 8px; padding: 9px 14px; border: 1px solid var(--border-strong); border-radius: 11px; font-size: 13px; font-weight: 500; cursor: pointer; transition: .15s; background: var(--bg-elev); text-align: left; }
.prompt-chip:hover { border-color: var(--primary); background: var(--primary-soft); color: var(--primary); }
.prompt-chip svg { width: 15px; height: 15px; color: var(--primary); }
.ai-hero { text-align: center; padding: 30px 0 24px; }
.ai-hero .ai-logo { width: 64px; height: 64px; border-radius: 20px; background: linear-gradient(135deg, var(--brand-green), var(--brand-mint)); display: grid; place-items: center; margin: 0 auto 16px; box-shadow: 0 10px 30px rgba(0,77,67,.35); }
.ai-hero .ai-logo svg { width: 32px; height: 32px; color: var(--brand-lime); }
/* ============================================================
BRAND HERO
Full-bleed brand-green panel used for page-level banners. It keeps
the same deep green in BOTH themes — it is a brand surface, not a
theme surface — so everything inside is scoped to light-on-green.
============================================================ */
.brand-hero {
background: linear-gradient(120deg, var(--brand-green), #0a6a58);
border: none;
color: #fff;
position: relative;
overflow: hidden;
}
/* Emblem-derived curve, echoing the logo's flowing edge. */
.brand-hero::after {
content: '';
position: absolute; right: -40px; top: -60px;
width: 260px; height: 260px; border-radius: 50%;
background: radial-gradient(circle at 30% 30%, rgba(206,255,113,.20), transparent 68%);
pointer-events: none;
}
.brand-hero .card-body { position: relative; z-index: 1; }
.brand-hero h2, .brand-hero h3 { color: #fff; }
.brand-hero p { color: rgba(255,255,255,.86); }
.brand-hero .ai-logo { background: rgba(206,255,113,.16); box-shadow: none; }
.brand-hero .avatar { color: #fff; }
.brand-hero .ai-logo svg { color: var(--brand-lime); }
.brand-hero .topbar-search > svg { color: var(--text-3); }
.brand-hero .topbar-search input {
background: #fff; color: #10231f; border-color: transparent;
}
.brand-hero .topbar-search input::placeholder { color: #54726c; }
.btn-on-brand { background: var(--brand-lime); color: var(--brand-ink); font-weight: 600; }
.btn-on-brand:hover { background: #dcff96; }
/* AI FAB + dock */
.ai-fab { position: fixed; bottom: 26px; right: 26px; width: 56px; height: 56px; border-radius: 50%; background: var(--brand-green); color: var(--brand-lime); display: grid; place-items: center; box-shadow: 0 10px 30px rgba(0,77,67,.45); z-index: 200; transition: .2s; }
.ai-fab:hover { transform: scale(1.08) rotate(8deg); }
/* Redundant (and overlapping the send button) on the assistant page itself. */
[data-view="aiassistant"] .ai-fab { display: none; }
.ai-fab svg { width: 26px; height: 26px; }
.ai-dock { position: fixed; top: 0; right: 0; bottom: 0; width: 440px; max-width: 92vw; background: var(--bg-elev); border-left: 1px solid var(--border); box-shadow: var(--shadow-lg); z-index: 310; transform: translateX(100%); transition: transform .28s cubic-bezier(.4,0,.2,1); }
.ai-dock.open { transform: translateX(0); }
.ai-dock-inner { height: 100%; display: flex; flex-direction: column; }
/* Bulk action bar */
.bulk-bar { display: flex; align-items: center; gap: 12px; padding: 12px 18px; background: var(--primary); color: var(--primary-fg); border-radius: 12px; margin-bottom: 14px; animation: fadeUp .2s; }
.bulk-bar .btn { background: rgba(255,255,255,.15); background: color-mix(in srgb, var(--primary-fg) 14%, transparent); color: var(--primary-fg); border: none; }
.bulk-bar .btn:hover { background: rgba(255,255,255,.25); background: color-mix(in srgb, var(--primary-fg) 24%, transparent); }
.checkbox { width: 18px; height: 18px; border-radius: 5px; border: 2px solid var(--border-strong); display: inline-grid; place-items: center; cursor: pointer; flex-shrink: 0; transition: .12s; background: var(--bg-elev); }
.checkbox.on { background: var(--primary); border-color: var(--primary); color: var(--primary-fg); }
.checkbox svg { width: 12px; height: 12px; opacity: 0; }
.checkbox.on svg { opacity: 1; }
/* Filter panel */
.filter-panel { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
.filter-panel .form-field label { font-size: var(--fs-xs); }
.star-btn { color: var(--text-3); transition: .12s; }
.star-btn.on { color: var(--warning); }
.star-btn.on svg { fill: currentColor; }
/* Segmented control */
.seg { display: inline-flex; background: var(--bg-sunken); padding: 3px; border-radius: 10px; }
.seg button { padding: 6px 14px; border-radius: 8px; font-size: var(--fs-sm); font-weight: 600; color: var(--text-2); }
.seg button.active { background: var(--bg-elev); color: var(--text); box-shadow: var(--shadow-sm); }
.rating-stars { display: inline-flex; gap: 3px; }
.rating-stars .rs { color: var(--border-strong); cursor: pointer; transition: .1s; }
.rating-stars .rs svg { width: 22px; height: 22px; }
.rating-stars .rs.on { color: var(--warning); }
.rating-stars .rs.on svg { fill: currentColor; }
.recc-banner { display: flex; align-items: center; gap: 14px; padding: 16px 18px; border-radius: 14px; margin-bottom: 18px; }
.recc-strong { background: var(--success-soft); color: var(--success); }
.recc-potential { background: var(--warning-soft); color: var(--warning); }
.recc-weak { background: var(--danger-soft); color: var(--danger); }
.recc-banner .recc-icn { width: 44px; height: 44px; border-radius: 12px; background: rgba(255,255,255,.5); display: grid; place-items: center; }
[data-theme="dark"] .recc-banner .recc-icn { background: rgba(0,0,0,.2); }
/* ============================================================
SAFE AREAS (iOS notch / Dynamic Island / home indicator,
and Android gesture bars). index.html sets viewport-fit=cover,
so the layout reaches the physical edges and these insets pull
the actual content back into the safe region.
============================================================ */
.sidebar { padding-left: env(safe-area-inset-left); }
.topbar {
padding-left: max(22px, env(safe-area-inset-left));
padding-right: max(22px, env(safe-area-inset-right));
}
.content {
padding-left: max(30px, env(safe-area-inset-left));
padding-right: max(30px, env(safe-area-inset-right));
padding-bottom: max(60px, env(safe-area-inset-bottom));
}
.ai-fab {
right: max(26px, env(safe-area-inset-right));
bottom: max(26px, env(safe-area-inset-bottom));
}
.toast-root {
right: max(24px, env(safe-area-inset-right));
bottom: max(24px, env(safe-area-inset-bottom));
}
.ai-dock { padding-bottom: env(safe-area-inset-bottom); }
.modal-foot { padding-bottom: max(18px, env(safe-area-inset-bottom)); }
/* ============================================================
TOUCH TARGETS
Apple HIG asks for 44pt, Material for 48dp. Rather than inflate
the visuals everywhere, controls keep their drawn size and gain
an invisible centred hit area via ::after on coarse pointers.
============================================================ */
@media (pointer: coarse) {
.act-btn, .page-btn, .icon-btn, .modal-close, .toast-close,
.sidebar-collapse-btn, .checkbox, .perm-check, .rating-stars .rs,
.star-btn, .link-btn {
position: relative;
}
/* ::before, not ::after — .act-btn carries data-tip, whose tooltip is
rendered through [data-tip]::after and would be clobbered. */
.act-btn::before, .page-btn::before, .icon-btn::before, .modal-close::before,
.toast-close::before, .sidebar-collapse-btn::before, .checkbox::before,
.perm-check::before, .rating-stars .rs::before, .star-btn::before {
content: '';
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
width: 44px; height: 44px;
/* purely a hit area — never paints, never blocks the icon */
pointer-events: auto;
}
.btn { min-height: 44px; padding-top: 11px; padding-bottom: 11px; }
.btn-sm { min-height: 40px; }
.nav-item { padding-top: 12px; padding-bottom: 12px; }
.dropdown-link { padding-top: 12px; padding-bottom: 12px; }
.tab { padding-top: 14px; padding-bottom: 14px; }
.list-row, .search-item, .notif-row { min-height: 48px; }
.form-field input, .form-field select, .form-field textarea,
.toolbar-search input, .select { min-height: 44px; }
.switch-track { width: 50px; height: 30px; }
.switch-track::after { width: 24px; height: 24px; }
.switch input:checked + .switch-track::after { transform: translateX(20px); }
}
/* ============================================================
RESPONSIVE
1200 laptop · 980 tablet-landscape · 900 tablet-portrait (sidebar
goes off-canvas) · 640 phone · 400 small phone · plus a
landscape-phone height rule. Late bolt-on sections (Dashboard v2,
hiring forms) keep their 1400/1200/860 steps next to their base
rules and share ONE consolidated 640/400 block at the end of file.
============================================================ */
/* Cap the measure on every desktop, not only ultrawide — between 900 and
1600px the content used to run full-bleed. No-op below ~1500px viewports;
agrees with .cand-page's own 1440px cap. */
.content > .page { max-width: 1440px; margin-inline: auto; }
/* ≤1200 — laptop. .g-3 steps 3→2 here and 2→1 at 900; it used to jump
straight to one column, wasting the whole 9001200 band. */
@media (max-width: 1200px) {
.g-kpi { grid-template-columns: repeat(2, 1fr); }
.g-3 { grid-template-columns: repeat(2, 1fr); }
.g-2-1, .g-1-2, .g-2 { grid-template-columns: 1fr; }
.filter-panel { grid-template-columns: repeat(3, 1fr); }
}
/* ≤980 — tablet landscape */
@media (max-width: 980px) {
.split { grid-template-columns: 1fr; }
.split-list { border-right: none; border-bottom: 1px solid var(--border); max-height: 380px; }
.rbac-layout { grid-template-columns: 1fr; }
.filter-panel { grid-template-columns: repeat(2, 1fr); }
.rbac-matrix { min-width: 620px; } /* scrolls inside .table-wrap */
}
/* ≤900 — tablet portrait: the sidebar goes off-canvas */
@media (max-width: 900px) {
.g-3 { grid-template-columns: 1fr; }
.sidebar {
/* above the scrim (55) but below the AI dock (310) and modals (300),
so an open drawer never sits on top of a dialog. */
position: fixed; left: 0; z-index: 100;
transform: translateX(-100%); transition: transform .25s;
box-shadow: none;
}
.sidebar.mobile-open { transform: translateX(0); box-shadow: var(--shadow-lg); }
/* The FAB floated over the scrim and stayed tappable behind the drawer. */
.nav-open .ai-fab { display: none; }
.icon-btn.menu-toggle { display: grid; }
.search-kbd { display: none; }
.content { padding: 20px max(16px, env(safe-area-inset-left)) 50px max(16px, env(safe-area-inset-right)); }
.profile-meta { display: none; }
.topbar { padding-left: max(16px, env(safe-area-inset-left)); padding-right: max(16px, env(safe-area-inset-right)); }
.chat-wrap { height: calc(100vh - 170px); height: calc(100dvh - 170px); }
}
/* ≤640 — phone (core shell + components; late-section 640 rules live in the
consolidated block at the end of the file, after their base rules) */
@media (max-width: 640px) {
.g-kpi { grid-template-columns: 1fr; }
.topbar { padding-left: max(12px, env(safe-area-inset-left)); padding-right: max(12px, env(safe-area-inset-right)); gap: 6px; }
.form-grid, .info-grid, .filter-panel { grid-template-columns: 1fr; }
.page-title { font-size: var(--fs-2xl); }
.page-head { gap: 12px; margin-bottom: 18px; }
.page-head-actions { width: 100%; }
.page-head-actions .btn { flex: 1 1 auto; justify-content: center; }
/* The action cluster was eating 232px of a 375px bar, leaving search
~59px — too narrow to read or tap. Drop the secondary affordances
(messages, divider, profile chevron) so search stays usable. */
.topbar-search { max-width: none; min-width: 0; }
#messagesDropdown, .topbar-divider, .profile-btn .chev { display: none; }
.topbar-actions { gap: 2px; }
.icon-btn { width: 40px; height: 40px; }
.profile-btn { padding: 4px; }
/* Dropdowns were 340px wide and ran off the left edge of a 320px screen.
Anchor them to the viewport instead of the trigger. */
.dropdown-menu, .dropdown-menu-wide {
position: fixed;
top: calc(var(--topbar-h) + 6px);
left: 8px; right: 8px;
width: auto; min-width: 0; max-width: none;
max-height: calc(100vh - var(--topbar-h) - 24px);
max-height: calc(100dvh - var(--topbar-h) - 24px);
overflow-y: auto; overscroll-behavior: contain;
}
.dd-scroll { max-height: none; }
/* Toast overhung the left edge at 300px min-width. */
.toast-root { left: max(12px, env(safe-area-inset-left)); right: max(12px, env(safe-area-inset-right)); }
.toast { min-width: 0; max-width: none; width: 100%; }
/* Modals read better as near-full-height sheets on a phone. */
.modal { margin: 0; width: 100%; max-width: none; border-radius: var(--radius-xl) var(--radius-xl) 0 0;
position: fixed; left: 0; right: 0; bottom: 0; max-height: 94vh; max-height: 94dvh; }
.modal-head { padding: 18px 18px 14px; }
.modal-body { padding: 18px; }
.modal-foot { padding: 14px 18px max(14px, env(safe-area-inset-bottom)); flex-direction: column-reverse; }
.modal-foot .btn { width: 100%; }
/* Kanban: a 288px column left 32px of the next one visible, so the board
didn't read as scrollable. Show a slice of the neighbour and snap. */
.kanban { gap: 12px; scroll-padding-left: 16px; }
.kanban-col { flex: 0 0 min(78vw, 300px); scroll-snap-align: start; max-height: none; }
.kanban-cards { max-height: 60vh; }
.ai-dock { width: 100%; max-width: 100%; }
.split-list { max-height: 320px; }
.card-head { padding: 14px 16px; }
.card-body, .card-pad { padding: 16px; }
.kpi { padding: 16px; }
.tabs { gap: 0; }
.cal-cell { min-height: 76px; }
.chat-msg { gap: 10px; }
.brand-hero .card-body { padding: 22px 18px; }
.stepper { overflow-x: auto; padding-bottom: 6px; }
.step-label { display: none; } /* numbers alone keep the stepper legible */
.step-line { margin: 0 8px; }
/* Data tables: let the row scroll sideways at a legible column width
rather than squeezing names onto three lines. The wrapper already
handles the horizontal gesture. */
table.data { min-width: 720px; }
table.data thead th { padding: 10px 12px; }
table.data tbody td { padding: 11px 12px; }
.user-cell .cell-primary { white-space: nowrap; }
.user-cell .cell-sub {
white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 190px;
}
/* Sticky identity column keeps context while scrolling the rest. */
table.data thead th:nth-child(2),
table.data tbody td:nth-child(2) {
position: sticky; left: 0; z-index: 2;
background: var(--bg-elev);
box-shadow: 1px 0 0 var(--border);
}
table.data tbody tr:hover td:nth-child(2) { background: var(--bg-sunken); }
}
/* Small phones (iPhone SE / older Android at 320400px). */
@media (max-width: 400px) {
.content { padding-left: max(12px, env(safe-area-inset-left)); padding-right: max(12px, env(safe-area-inset-right)); }
.page-title { font-size: 22px; }
.kpi-value { font-size: 25px; }
.sidebar { width: min(88vw, var(--sidebar-w)); }
.toolbar-search { max-width: none; }
.pagination { justify-content: center; }
.page-info { width: 100%; text-align: center; }
}
/* Landscape phones: only ~375px of height, most of it chrome. */
@media (max-height: 500px) and (orientation: landscape) {
:root { --topbar-h: 52px; }
.content { padding-top: 14px; padding-bottom: 28px; }
.page-head { margin-bottom: 14px; }
.chat-wrap { height: calc(100vh - 120px); height: calc(100dvh - 120px); }
.kanban-col { max-height: calc(100vh - 150px); max-height: calc(100dvh - 150px); }
.split-list, .split-detail { max-height: calc(100vh - 150px); max-height: calc(100dvh - 150px); }
.modal { max-height: 96vh; max-height: 96dvh; }
.sidebar-footer { display: none; } /* reclaim height in the drawer */
}
/* Foldables / very short windows on desktop. */
@media (max-height: 420px) {
.ai-fab { width: 46px; height: 46px; }
.ai-fab svg { width: 22px; height: 22px; }
}
/* ============================================================
DASHBOARD v2 — scoped to the restyled dashboard. Brand tokens only.
KpiCard / .g-kpi on Interviews, JobBoard, RecruiterHub stay untouched.
============================================================ */
.kpi-tile { padding: 16px 18px; }
.kpi-tile:hover { transform: none; }
.kpi-tile .kpi-label { display: block; margin-bottom: 8px; }
.kpi-tile .kpi-value { font-size: 24px; margin-bottom: 8px; }
.kpi-tile .trend { margin-bottom: 4px; }
.kpi-spark { height: 36px; margin-top: 8px; }
.kpi-spark canvas { width: 100%; display: block; }
.g-kpi-7 { grid-template-columns: repeat(7, 1fr); }
.pipe-split { display: grid; grid-template-columns: 1fr 150px; gap: 16px; align-items: center; }
.pipe-row { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.pipe-row:last-child { margin-bottom: 0; }
.pipe-label {
flex: 0 0 92px; font-size: 12.5px; color: var(--text-2); font-weight: 500;
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pipe-track { flex: 1; height: 8px; background: var(--bg-sunken); border-radius: 99px; overflow: hidden; }
.pipe-fill { height: 100%; border-radius: 99px; }
.pipe-pct { flex: 0 0 40px; text-align: right; font-size: 12.5px; font-weight: 600; color: var(--text-2); }
.task-foot {
display: flex; align-items: center; gap: 10px; margin-top: 14px; padding-top: 12px;
border-top: 1px solid var(--border); font-size: 12.5px; color: var(--text-2);
}
.task-foot .pbar { flex: 1; }
.sched-time { flex: 0 0 64px; font-size: 12.5px; font-weight: 700; color: var(--primary); }
@media (max-width: 1400px) {
.g-kpi-7 { grid-template-columns: repeat(4, 1fr); }
}
@media (max-width: 1200px) {
.g-kpi-7 { grid-template-columns: repeat(2, 1fr); }
.pipe-split { grid-template-columns: 1fr; }
}
/* ============================================================
Hiring forms — the candidate profile Forms tab (CandidateForms.jsx).
Digitized paper annexures: requisition, interview analysis, cultural
fit, offer. Namespaced .hf-* ; consumes only global tokens so both
themes come for free. */
/* Score summary: stat tiles, hero = combined overall */
.hf-summary { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-bottom: 18px; }
.hf-tile { background: var(--bg-sunken); border: 1px solid var(--border); border-radius: 12px; padding: 12px 14px; min-width: 0; }
.hf-tile .hf-k { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hf-tile .hf-v { font-size: 20px; font-weight: 700; margin-top: 4px; font-variant-numeric: tabular-nums; }
.hf-tile .hf-v small { font-size: 12px; font-weight: 600; color: var(--text-3); margin-left: 2px; }
.hf-tile .hf-sub { font-size: 11.5px; color: var(--text-3); margin-top: 4px; }
.hf-tile.hero { background: var(--primary-soft); border-color: var(--border-strong); }
.hf-meter { height: 4px; border-radius: 2px; background: var(--border); margin-top: 8px; overflow: hidden; }
.hf-meter i { display: block; height: 100%; border-radius: 2px; background: var(--primary); }
/* Bordered section card, titled like the paper form's section headers */
.hf-block { border: 1px solid var(--border); border-radius: 12px; padding: 14px 16px; margin-top: 14px; }
.hf-block-title { margin-bottom: 12px; display: flex; align-items: center; gap: 10px; }
.hf-block-title label { display: flex; align-items: center; gap: 8px; cursor: pointer; text-transform: none; letter-spacing: 0; font-size: 13px; font-weight: 600; color: var(--text-2); }
.hf-note { font-size: 12.5px; color: var(--text-3); margin: 2px 0 10px; }
/* Rating table: the paper grid — scale header, radio-dot cells, average foot */
.hf-rate { border: 1px solid var(--border); border-radius: 10px; overflow: hidden; }
.hf-rate-head, .hf-rate-row, .hf-rate-foot { display: grid; grid-template-columns: minmax(0, 1fr) repeat(4, 96px); align-items: center; }
.hf-rate-head { background: var(--bg-sunken); }
.hf-rate-head > div { padding: 8px 10px; text-align: center; }
.hf-rate-head > div:first-child { text-align: left; }
.hf-rate-row { border-top: 1px solid var(--border); }
.hf-rate-row > div:first-child { padding: 9px 10px; font-size: 13px; }
.hf-rate-cell { display: flex; justify-content: center; }
.hf-dot { width: 22px; height: 22px; border-radius: 50%; border: 2px solid var(--border-strong); background: var(--bg-elev); cursor: pointer; transition: border-color .12s, background .12s, box-shadow .12s; padding: 0; }
.hf-dot:hover { border-color: var(--primary); }
.hf-dot.on { background: var(--primary); border-color: var(--primary); box-shadow: inset 0 0 0 3.5px var(--bg-elev); }
.hf-rate-foot { border-top: 1px solid var(--border); background: var(--bg-sunken); }
.hf-rate-foot > div:first-child { padding: 8px 10px; }
.hf-rate-foot .hf-avg { grid-column: 2 / -1; text-align: center; font-size: 13.5px; font-weight: 700; font-variant-numeric: tabular-nums; padding: 8px 0; }
/* Completion dot on the form switcher */
.hf-done { width: 6px; height: 6px; border-radius: 50%; background: var(--success); display: inline-block; margin-left: 7px; vertical-align: middle; }
/* Approvals: four signature slots */
.hf-sign-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
.hf-sign { display: flex; flex-direction: column; gap: 6px; }
@media (max-width: 860px) {
/* Rating columns keep their full 96px width here — the word headers still
fit. The shrink + numeric headers happen together at 640px. */
.hf-summary { grid-template-columns: repeat(2, 1fr); }
.hf-sign-grid { grid-template-columns: repeat(2, 1fr); }
}
/* Modal tab strips: wrap instead of clipping behind a horizontal scrollbar —
ten tabs do not fit the 860px profile modal. */
.tabs-wrap { flex-wrap: wrap; overflow-x: visible; }
/* Full-page candidate profile (/candidate/:userId).
The page centers itself with a generous cap so ultrawide monitors don't get
a mile-wide form, and everything below the cap is fluid — no fixed widths. */
.cand-page { max-width: 1440px; margin: 0 auto; }
.cand-page-bar { display: flex; align-items: center; gap: 14px; margin-bottom: 16px; flex-wrap: wrap; }
.cand-page-crumb { font-size: 13.5px; color: var(--text-3); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cand-page-crumb span { margin: 0 2px; }
.cand-page-crumb strong { color: var(--text); font-weight: 600; }
.cand-page-actions { margin-left: auto; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.cand-page-actions .star-btn { margin-right: 0 !important; }
/* The four-form switcher must wrap rather than overflow on narrow screens. */
.cand-page .seg { flex-wrap: wrap; }
/* Rating-table scale header: full words down to 640px, bare numbers below. */
.hf-scale-short { display: none; }
/* Empty-state CTA on the hiring forms: full-size, and full-width on phones. */
.hf-cta { padding: 11px 26px; font-size: 14.5px; }
/* ============================================================
≤640 / ≤400 — consolidated phone rules for the late bolt-on sections
(Dashboard v2 grid, candidate page, hiring forms). Kept in ONE block
at the end of the file so they always follow their base rules; the
core shell's 640 rules live in the RESPONSIVE section above.
============================================================ */
@media (max-width: 640px) {
.g-kpi-7 { grid-template-columns: 1fr; }
.cand-page-actions { width: 100%; }
.cand-page-actions .btn { flex: 1 1 auto; justify-content: center; }
.hf-sign-grid { grid-template-columns: 1fr; }
.hf-summary { grid-template-columns: repeat(2, 1fr); }
.hf-scale-full { display: none; }
.hf-scale-short { display: inline; font-size: var(--fs-xs); }
.hf-rate-head, .hf-rate-row, .hf-rate-foot { grid-template-columns: minmax(0, 1fr) repeat(4, 44px); }
.hf-cta { width: 100%; max-width: 420px; justify-content: center; }
}
@media (max-width: 400px) {
.hf-summary { grid-template-columns: 1fr; }
}