/* ===============================================================
   ChatterBase Hire -- Design System v1
   Dark premium. Fonts: Sora (display) + Inter (body), loaded in layout.
   =============================================================== */

:root {
    --bg: #07080D;
    --bg-2: #0C0E15;
    --bg-3: #12141D;
    --card: rgba(255,255,255,.035);
    --card-hover: rgba(255,255,255,.06);
    --line: rgba(255,255,255,.09);
    --line-strong: rgba(255,255,255,.16);
    --text: #F4F6FB;
    --text-2: #A7AFC0;
    --text-3: #6B7385;
    --acc-1: #7C5CFF;
    --acc-2: #FF4D8D;
    --grad: linear-gradient(135deg, #7C5CFF 0%, #FF4D8D 100%);
    --grad-soft: linear-gradient(135deg, rgba(124,92,255,.14), rgba(255,77,141,.10));
    --ok: #2CE5A7;
    --verified: #1D9BF0;   /* trust/verification blue (Facebook/X style) -- never green */
    --warn: #FFB454;
    --bad: #FF5C5C;
    --r-lg: 20px;
    --r-md: 14px;
    --r-sm: 10px;
    --shadow: 0 20px 60px rgba(0,0,0,.5);
    --font-display: 'Sora', 'Inter', sans-serif;
    --font-body: 'Inter', -apple-system, sans-serif;
}

* { margin: 0; padding: 0; box-sizing: border-box; }
html {
    scroll-behavior: smooth;
    /* The html element must carry the background. body alone leaves the canvas
       transparent, and iOS paints that WHITE in the safe-area insets and while
       overscrolling -- the white frame around the installed PWA.
       NOTE: no overflow-x here. Setting overflow on the ROOT makes html/body the
       scroll container in WebKit, which stops position:sticky from sticking -- it
       would silently break the navbar and the workspace tab bar on iOS. */
    background: var(--bg);
    -webkit-text-size-adjust: 100%; /* iOS must not re-scale text in landscape */
}
body {
    font-family: var(--font-body);
    /* NO background here on purpose. The colour lives on <html> (above), which is what
       fills the iOS safe-area. If body ALSO painted a background it would cover the
       ambient layers .cb-glow / .cb-stars, which sit at z-index -2 / -1 and are painted
       before any block background in the root stacking context -- that is exactly how
       the orbs and the starfield vanished once html gained a background. */
    background: transparent;
    color: var(--text);
    font-size: 15px;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    min-height: 100vh;
    min-height: 100dvh; /* real viewport height on mobile browsers with dynamic toolbars */
    /* clip (not hidden) contains any stray overflow WITHOUT creating a scroll
       container, so sticky positioning keeps working. This is a safety net only --
       the actual overflowing elements are fixed at their source (see the
       "HORIZONTAL OVERFLOW CONTAINMENT" block further down).
       Why clip and not hidden: overflow-x:hidden next to overflow-y:visible forces
       the y axis to compute to auto, which turns the propagating element into a
       scroll container -- that is what used to break position:sticky in WebKit.
       clip is the one non-visible value that legally pairs with visible, so the
       page still scrolls DOWN normally and the sticky navbar keeps sticking. */
    overflow-x: clip;
    overflow-wrap: break-word; /* long emails / URLs / handles can never blow out a card */
}
/* Pre-2022 engines (Safari < 16, Chrome < 90) drop `clip` as an invalid value, so the
   page could still slide sideways there. Fall back to hidden ONLY in that case, and
   put it on the ROOT rather than on body: overflow set on the root element is always
   propagated to the viewport and the root's own used value becomes visible, so neither
   html nor body turns into a scroll container and position:sticky is untouched.
   (On body the same fallback would risk the WebKit sticky bug noted above whenever an
   engine declines to propagate.) */
@supports not (overflow-x: clip) {
    html { overflow-x: hidden; }
}
a { color: inherit; text-decoration: none; }
img, svg, video { max-width: 100%; }
::selection { background: rgba(124,92,255,.35); }

/* -- Ambient background glow -- */
.cb-glow {
    position: fixed; inset: 0; z-index: -2; pointer-events: none; overflow: hidden;
    background:
        radial-gradient(600px 400px at 15% -5%, rgba(124,92,255,.12), transparent 60%),
        radial-gradient(700px 500px at 90% 10%, rgba(255,77,141,.07), transparent 60%),
        radial-gradient(800px 600px at 50% 110%, rgba(124,92,255,.06), transparent 60%);
}
/* animated floating orbs */
.cb-glow::before, .cb-glow::after {
    content: ''; position: absolute; border-radius: 50%; filter: blur(100px); will-change: transform;
}
.cb-glow::before { width: 520px; height: 520px; background: #7C5CFF; opacity: .22; top: -180px; left: -120px; animation: cbDrift1 26s ease-in-out infinite alternate; }
.cb-glow::after  { width: 460px; height: 460px; background: #FF4D8D; opacity: .14; top: 8%; right: -160px; animation: cbDrift2 32s ease-in-out infinite alternate; }
@keyframes cbDrift1 { to { transform: translate(140px, 120px) scale(1.15); } }
@keyframes cbDrift2 { to { transform: translate(-120px, 180px) scale(1.1); } }

/* faint starfield layer (add via <div class="cb-stars">...</div>) */
.cb-stars { position: fixed; inset: 0; z-index: -1; pointer-events: none; }
.cb-stars i { position: absolute; width: 2px; height: 2px; border-radius: 50%; background: #fff; opacity: .18; animation: cbTwinkle var(--d,5s) ease-in-out var(--del,0s) infinite; }
.cb-stars i.b { width: 3px; height: 3px; }
@keyframes cbTwinkle { 50% { opacity: .9; transform: scale(1.8); } }

/* hero glow -- a soft aura directly behind the headline */
.cb-hero-glow { position: relative; }
.cb-hero-glow::before {
    content: ''; position: absolute; top: 42%; left: 50%; width: 640px; height: 360px; max-width: 92vw;
    transform: translate(-50%, -50%); z-index: -1; pointer-events: none;
    background: radial-gradient(ellipse at center, rgba(124,92,255,.30), rgba(255,77,141,.10) 45%, transparent 70%);
    filter: blur(34px);
}
@media (prefers-reduced-motion: reduce) { .cb-glow::before, .cb-glow::after, .cb-stars i { animation: none; } }

/* -- Layout helpers -- */
/* Side padding respects the landscape notch/rounded corners. Written as LONGHANDS on
   purpose: the shorthand order is top/right/bottom/left, which makes it far too easy
   to feed the left inset into padding-right (and it was, once). */
.cb-wrap, .cb-wrap-narrow { margin: 0 auto; }
.cb-wrap { max-width: 1160px; }
.cb-wrap-narrow { max-width: 760px; }
.cb-wrap, .cb-wrap-narrow {
    padding-left: max(24px, env(safe-area-inset-left, 0px));
    padding-right: max(24px, env(safe-area-inset-right, 0px));
}
/* minmax(0, 1fr), never a bare 1fr. `1fr` is shorthand for minmax(auto, 1fr) and
   that `auto` minimum resolves to the track's MIN-CONTENT width, so a track refuses
   to get narrower than its widest child -- the grid then grows past its container
   and the page scrolls sideways. The worst offender is <select>: Blink reports the
   width of the longest <option> as its min-content size, so a single long creator or
   member name silently widened the whole "Log a sale" grid. minmax(0, 1fr) removes
   that floor; the children are told to shrink in the FORM CONTROLS section below. */
.cb-grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; }
.cb-grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; }
.cb-grid-4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; }
.cb-flex { display: flex; align-items: center; gap: 12px; }
.cb-between { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.cb-main { padding: 42px 0 90px; }
@media (max-width: 900px) {
    .cb-grid-3, .cb-grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
    .cb-grid-2, .cb-grid-3, .cb-grid-4 { grid-template-columns: minmax(0, 1fr); }
}

/* -- Navbar -- */
.cb-nav {
    position: sticky; top: 0; z-index: 100;
    backdrop-filter: blur(18px);
    background: rgba(7,8,13,.72);
    border-bottom: 1px solid var(--line);
    /* With apple-mobile-web-app-status-bar-style=black-translucent the installed app
       draws under the status bar, so the bar must pay for its own clearance. */
    padding-top: env(safe-area-inset-top, 0px);
}
.cb-nav-inner { max-width: 1160px; margin: 0 auto; padding: 0 24px; height: 68px; display: flex; align-items: center; gap: 28px; }
.cb-logo { font-family: var(--font-display); font-weight: 800; font-size: 19px; letter-spacing: -.4px; display: flex; align-items: center; gap: 10px; }
.cb-logo .mark {
    width: 30px; height: 30px; border-radius: 9px; background: var(--grad);
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 13px; font-weight: 800; color: #fff;
}
.cb-logo .suffix { background: var(--grad); -webkit-background-clip: text; background-clip: text; color: transparent; }
.cb-nav-links { display: flex; gap: 4px; flex: 1; }
.cb-nav-links a {
    padding: 8px 14px; border-radius: 10px; font-size: 14px; font-weight: 500; color: var(--text-2);
    transition: all .18s;
}
.cb-nav-links a:hover { color: var(--text); background: var(--card); }
.cb-nav-links a.active { color: var(--text); background: var(--card-hover); }
.cb-nav-actions { display: flex; align-items: center; gap: 10px; }
/* 900, not 780: between 781 and ~1024 the inline links + actions + a long user name
   (RU labels run ~25% longer) overflowed the bar and were silently clipped, taking
   the account menu with them -- while the burger was not rendered yet. */
@media (max-width: 900px) {
    .cb-nav-links { display: none; }
}
/* A long display name must never push the burger off the bar. */
.ov-usertrigger > .small { max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* -- Buttons -- */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 8px;
    padding: 11px 22px; border-radius: 12px; border: 1px solid transparent;
    font-family: var(--font-body); font-size: 14px; font-weight: 600; cursor: pointer;
    transition: all .18s; white-space: nowrap;
}
.btn-primary { background: var(--grad); color: #fff; box-shadow: 0 8px 28px rgba(124,92,255,.35); }
.btn-primary:hover { transform: translateY(-1px); box-shadow: 0 12px 34px rgba(124,92,255,.5); }
.btn-ghost { background: var(--card); border-color: var(--line); color: var(--text); }
.btn-ghost:hover { background: var(--card-hover); border-color: var(--line-strong); }
.btn-danger { background: rgba(255,92,92,.12); border-color: rgba(255,92,92,.3); color: var(--bad); }
.btn-sm { padding: 7px 14px; font-size: 13px; border-radius: 10px; }
.btn-lg { padding: 15px 32px; font-size: 15px; border-radius: 14px; }
.btn-block { width: 100%; }
.btn:disabled { opacity: .5; cursor: not-allowed; transform: none; }
/* A button must never be wider than what holds it. Long labels (and RU strings, which
   run ~25% longer than EN) previously pushed buttons past the viewport on phones. */
.btn { max-width: 100%; }
@media (max-width: 640px) {
    .btn { white-space: normal; text-align: center; }
    .cb-nav-actions .btn { white-space: nowrap; } /* the bar's own buttons still stay on one line */
}

/* -- Cards -- */
.card {
    background: var(--card); border: 1px solid var(--line); border-radius: var(--r-lg);
    padding: 26px; transition: border-color .2s, background .2s;
}
.card:hover { border-color: var(--line-strong); }
.card-flat:hover { border-color: var(--line); }
.card-pad-sm { padding: 18px; }
.card-featured { background: var(--grad-soft); border-color: rgba(124,92,255,.35); }

/* -- Typography -- */
.h-display {
    font-family: var(--font-display); font-weight: 800; letter-spacing: -1.5px;
    font-size: clamp(38px, 6vw, 64px); line-height: 1.06;
}
.h1 { font-family: var(--font-display); font-weight: 700; font-size: 28px; letter-spacing: -.6px; }
.h2 { font-family: var(--font-display); font-weight: 700; font-size: 21px; letter-spacing: -.4px; }
.h3 { font-family: var(--font-display); font-weight: 600; font-size: 16px; }
.grad-text { background: var(--grad); -webkit-background-clip: text; background-clip: text; color: transparent; }
.muted { color: var(--text-2); }
.muted-3 { color: var(--text-3); }
.small { font-size: 13px; }
.tiny { font-size: 12px; }
.section-label {
    font-size: 12px; font-weight: 700; letter-spacing: 2.5px; text-transform: uppercase;
    color: var(--acc-1); margin-bottom: 12px;
}

/* -- Forms -- */
.field { margin-bottom: 18px; }
.field label { display: block; font-size: 13px; font-weight: 600; color: var(--text-2); margin-bottom: 7px; }
.input, .select, .textarea {
    width: 100%; padding: 12px 15px; border-radius: var(--r-sm);
    background: var(--bg-3); border: 1px solid var(--line); color: var(--text);
    font-family: var(--font-body); font-size: 14px; transition: border-color .18s, box-shadow .18s;
    /* A control must never be the reason the page grows. Two separate mechanisms:
       min-width:0 removes the min-content floor a flex/grid child gets by default
       (a <select> reports its longest <option>, so without this it never shrinks),
       and max-width:100% caps the ones that are given width:auto inline. */
    min-width: 0; max-width: 100%;
    /* Explicit line-height so a text input, a select and a native date input all end
       up exactly the same height. Inherited 1.6 applied to <input> but not to the
       shadow tree of input[type=date], which is where the 2-3px mismatch came from. */
    line-height: 1.4;
}
.input, .select { min-height: 46px; }
.input:focus, .select:focus, .textarea:focus {
    outline: none; border-color: var(--acc-1);
    box-shadow: 0 0 0 3px rgba(61,125,255,.22);
    /* Accent-aware ring, so the user-selectable accents stay coherent. Older engines
       keep the azure fallback on the line above. */
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--acc-1) 30%, transparent);
}
.textarea { min-height: 110px; resize: vertical; line-height: 1.6; }
/* Every native control shrinks and stays inside its box, class or no class. */
input, select, textarea, button { max-width: 100%; }
select { min-width: 0; }

/* -- Visible keyboard focus (never for mouse/touch, hence :focus-visible) -- */
.btn:focus-visible,
a:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible,
input[type="checkbox"]:focus-visible,
input[type="radio"]:focus-visible {
    outline: 2px solid var(--acc-1);
    outline-offset: 2px;
}
.btn:focus-visible { box-shadow: 0 0 0 4px rgba(61,125,255,.20); }
.select { appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%236B7385' stroke-width='1.6' fill='none' stroke-linecap='round'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 14px center; padding-right: 38px;
    /* Now that a select is allowed to shrink below its longest option, a long creator
       or member name must fade out rather than be cut off mid-glyph. */
    text-overflow: ellipsis; }
.form-err {
    background: rgba(255,92,92,.1); border: 1px solid rgba(255,92,92,.3); color: #FF8A8A;
    padding: 11px 15px; border-radius: var(--r-sm); font-size: 13.5px; margin-bottom: 16px;
}
.form-ok {
    background: rgba(44,229,167,.08); border: 1px solid rgba(44,229,167,.28); color: var(--ok);
    padding: 11px 15px; border-radius: var(--r-sm); font-size: 13.5px; margin-bottom: 16px;
}

/* -- Chips & badges -- */
.chip {
    display: inline-flex; align-items: center; gap: 6px; padding: 5px 12px;
    border-radius: 999px; background: var(--card-hover); border: 1px solid var(--line);
    font-size: 12.5px; font-weight: 500; color: var(--text-2);
}
.badge {
    display: inline-flex; align-items: center; gap: 6px; padding: 4px 11px;
    border-radius: 999px; font-size: 12px; font-weight: 600;
}
.badge-ok    { background: rgba(44,229,167,.1);  border: 1px solid rgba(44,229,167,.3);  color: var(--ok); }
.badge-warn  { background: rgba(255,180,84,.1);  border: 1px solid rgba(255,180,84,.3);  color: var(--warn); }
.badge-bad   { background: rgba(255,92,92,.1);   border: 1px solid rgba(255,92,92,.3);   color: var(--bad); }
.badge-plain { background: var(--card-hover);    border: 1px solid var(--line);          color: var(--text-2); }
.badge-grad  { background: var(--grad); color: #fff; }
.badge-verified { background: rgba(29,155,240,.12); border: 1px solid rgba(29,155,240,.45); color: var(--verified); }

/* -- Avatars -- */
.avatar {
    width: 44px; height: 44px; border-radius: 13px; flex-shrink: 0;
    display: inline-flex; align-items: center; justify-content: center;
    font-family: var(--font-display); font-weight: 700; font-size: 16px; color: #fff;
    background: var(--grad);
}
.avatar-lg { width: 72px; height: 72px; border-radius: 20px; font-size: 26px; }
.avatar-sm { width: 32px; height: 32px; border-radius: 9px; font-size: 12px; }
/* A faint ring so an uploaded photo with light edges still reads as an avatar and
   not as a blank gap in the UI. */
.avatar.has-photo { box-shadow: inset 0 0 0 1px rgba(255,255,255,.18); }

/* -- Stats -- */
.stat { text-align: left; }
.stat .num { font-family: var(--font-display); font-weight: 800; font-size: 32px; letter-spacing: -1px; }
.stat .lbl { font-size: 13px; color: var(--text-3); margin-top: 2px; }

/* -- Timeline (employment history) -- */
.timeline { position: relative; padding-left: 26px; }
.timeline::before {
    content: ''; position: absolute; left: 7px; top: 6px; bottom: 6px;
    width: 2px; background: var(--line);
}
.timeline-item { position: relative; padding-bottom: 26px; }
.timeline-item:last-child { padding-bottom: 0; }
.timeline-item::before {
    content: ''; position: absolute; left: -25px; top: 6px;
    width: 12px; height: 12px; border-radius: 50%;
    background: var(--bg-3); border: 2px solid var(--text-3);
}
.timeline-item.current::before { background: var(--ok); border-color: var(--ok); box-shadow: 0 0 12px rgba(44,229,167,.6); }

/* -- Rows (list items) -- */
.row-item {
    display: flex; align-items: center; gap: 14px;
    padding: 16px 18px; border: 1px solid var(--line); border-radius: var(--r-md);
    background: var(--card); transition: all .18s; margin-bottom: 10px;
}
.row-item:hover { background: var(--card-hover); border-color: var(--line-strong); transform: translateY(-1px); }

/* -- Empty state -- */
.empty {
    text-align: center; padding: 60px 24px; color: var(--text-3);
    border: 1px dashed var(--line-strong); border-radius: var(--r-lg);
}
.empty .ico { font-size: 34px; margin-bottom: 12px; opacity: .6; }

/* -- Tables -- */
.cb-table { width: 100%; border-collapse: collapse; font-size: 14px;
    /* Tabular figures: every digit gets the same advance width, so money columns line
       up vertically instead of jittering row to row. */
    font-variant-numeric: tabular-nums; }
.cb-table th { text-align: left; padding: 10px 14px; color: var(--text-3); font-size: 12px; text-transform: uppercase; letter-spacing: 1px; border-bottom: 1px solid var(--line); }
.cb-table td { padding: 13px 14px; border-bottom: 1px solid var(--line); overflow-wrap: anywhere; }
/* Header band: a faint fill separates the labels from the rows even when the table is
   scrolled sideways inside its wrapper. */
.cb-table thead th { background: var(--card-hover); font-weight: 700; white-space: nowrap; }
/* Row feedback. .refund-row is an injected detail row with its own fill, so it is
   excluded rather than fighting the page-level style for it. */
.cb-table tbody tr:not(.refund-row):hover > td { background: var(--card-hover); }
.cb-table tbody tr:last-child > td { border-bottom: 0; }
.cb-table tfoot td { border-bottom: 0; padding-top: 15px; }
/* Numeric column helper: right-aligned money reads far faster in a column.
   Put class="num" on the <th> and the <td> of any amount column. */
.cb-table th.num, .cb-table td.num { text-align: right; white-space: nowrap; }

/* -- Table scroll wrapper --
   THE rule that keeps a wide table from taking the whole page with it. Wrap the
   table: <div class="table-scroll"><table class="cb-table"> ... The wrapper scrolls
   on its own axis; min-width:0 is what makes that actually happen when the wrapper
   sits inside a flex or grid parent, because such a child otherwise refuses to go
   below its content width and pushes the page instead. */
.table-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
    min-width: 0;
    max-width: 100%;
    scrollbar-width: thin;
    scrollbar-color: var(--line-strong) transparent;
}
.table-scroll::-webkit-scrollbar { height: 9px; }
.table-scroll::-webkit-scrollbar-track { background: transparent; }
.table-scroll::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 9px; }
.table-scroll::-webkit-scrollbar-thumb:hover { background: var(--text-3); }
/* A card is frequently the thing that holds the table; it must be shrinkable too. */
.card, .row-item, .empty { min-width: 0; overflow-wrap: anywhere; }

/* -- Footer -- */
.cb-footer { border-top: 1px solid var(--line); padding: 40px 0 max(40px, calc(24px + env(safe-area-inset-bottom, 0px))); margin-top: 80px; color: var(--text-3); font-size: 13.5px; }

/* -- Phone layout: tighter gutters and a nav that always fits -- */
@media (max-width: 640px) {
    .cb-wrap, .cb-wrap-narrow { padding-left: max(16px, env(safe-area-inset-left, 0px)); padding-right: max(16px, env(safe-area-inset-right, 0px)); }
    .cb-nav-inner { height: 60px; gap: 12px; }
    .cb-main { padding: 26px 0 64px; }
    .cb-footer { margin-top: 48px; padding-top: 28px; }
}
/* The nav bar keeps its own notch clearance at every width (a landscape phone is
   844px wide, so a max-width query would miss it entirely). */
.cb-nav-inner {
    padding-left: max(24px, env(safe-area-inset-left, 0px));
    padding-right: max(24px, env(safe-area-inset-right, 0px));
}
@media (max-width: 640px) {
    .cb-nav-inner { padding-left: max(16px, env(safe-area-inset-left, 0px)); padding-right: max(16px, env(safe-area-inset-right, 0px)); }
}

/* -- Touch devices, ANY width --
   These were previously scoped to max-width:640px, so a phone held in landscape
   (844px wide) lost every one of them: iOS resumed auto-zooming on focus and every
   control dropped back under the 44px touch minimum. Keying on the POINTER instead
   of the width covers portrait, landscape and tablets, and never affects a mouse. */
@media (pointer: coarse) {
    /* !important is deliberate: several pages set a smaller font-size inline on
       individual controls, and an inline style would otherwise win and re-enable
       the zoom. This rule is the single place that guarantees the 16px floor. */
    .input, .select, textarea,
    input[type="text"], input[type="email"], input[type="password"],
    input[type="number"], input[type="date"], input[type="search"], input[type="tel"], input[type="url"] {
        font-size: 16px !important; /* under 16px iOS Safari zooms the page in on focus */
    }
    /* The 16px floor makes every control taller; pin them all to one height so a date
       field never sits 2px off from the select beside it. */
    .input, .select { min-height: 48px; }
    .btn, .btn-sm { min-height: 44px; }
    .btn-sm { padding-top: 9px; padding-bottom: 9px; }
    /* Inline text links used as controls (footer, mailto, chips) get a real hit box. */
    .cb-footlinks a, .ov-menu a { min-height: 44px; display: flex; align-items: center; }
    .cb-footlinks a { display: inline-flex; }
}

/* -- Utility -- */
.mt-1 { margin-top: 8px; } .mt-2 { margin-top: 16px; } .mt-3 { margin-top: 24px; } .mt-4 { margin-top: 40px; } .mt-6 { margin-top: 64px; }
.mb-1 { margin-bottom: 8px; } .mb-2 { margin-bottom: 16px; } .mb-3 { margin-bottom: 24px; } .mb-4 { margin-bottom: 40px; }
.gap-sm { gap: 8px; } .wrap { flex-wrap: wrap; }
.divider { height: 1px; background: var(--line); margin: 22px 0; }
.hide-mobile { }
@media (max-width: 640px) { .hide-mobile { display: none !important; } }

/* ===============================================================
   MOBILE / RESPONSIVE PASS
   Trailing override layer -- rules here intentionally win over the
   base declarations above (later-in-file + range-scoped media).
   Breakpoints touched: 1024 . 900 . 768 . 641 . 640 . 480 . 430
   =============================================================== */

/* -- 1024: gentle desktop -> tablet easing -- */
@media (max-width: 1024px) {
    .cb-nav-inner { gap: 20px; }
}

/* -- 641-900 tablet grids: 2-up for grid-3/4 --
   The floor used to be minmax(260px, 1fr): two 260px tracks plus the gap need 536px,
   which no longer fits once the page gutters are taken off a 641px viewport, so the
   grid pushed the page sideways. minmax(0, 1fr) keeps the 2-up shape and lets the
   tracks shrink to whatever the viewport actually has. */
@media (min-width: 641px) and (max-width: 900px) {
    .cb-grid-3,
    .cb-grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* -- <=768: tables scroll horizontally instead of squashing --
   nowrap is deliberately NOT applied to every cell: free-text columns (names,
   emails, reasons, notes) would each be forced onto one line and inflate the table
   to thousands of pixels, burying the Actions column far off to the right. Only
   short, atomic values that must not break mid-token stay on one line. */
@media (max-width: 768px) {
    .cb-table {
        display: block;
        width: 100%;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }
    /* When a table already sits in a .table-scroll wrapper, do NOT make the table a
       scroller too -- nested scrollers meant you had to drag the inner one to reach the
       Actions column while the outer one swallowed the gesture. The wrapper scrolls. */
    .table-scroll .cb-table { display: table; overflow-x: visible; }
    /* Same situation, different spelling: a few pages (sales.php) turn the CARD into
       the scroller with an inline style instead of using .table-scroll. Recognise it
       so those pages do not get the nested-scroller behaviour either. The proper fix
       is to give the card the .table-scroll class; this keeps it working until then. */
    .card[style*="overflow-x:auto"] .cb-table,
    .card[style*="overflow-x: auto"] .cb-table { display: table; overflow-x: visible; }
    .cb-table th { white-space: nowrap; }
    .cb-table td { white-space: normal; overflow-wrap: break-word; }
    /* Keep dates, money, badges and the action cluster from breaking apart. */
    .cb-table td.nowrap,
    .cb-table td .badge,
    .cb-table td .btn { white-space: nowrap; }
    .cb-table .adm-actions { white-space: nowrap; }
    /* A cell still needs a sane floor so text does not collapse to one word per line. */
    .cb-table td { min-width: 92px; }
}

/* -- Light theme: the navbar/tab chrome must follow the theme --
   .cb-nav hardcoded a dark rgba background, so in light mode the bar stayed dark
   while its text switched to dark ink -- logo and links became unreadable. */
:root[data-theme="light"] .cb-nav { background: rgba(246,244,250,.82); border-bottom-color: var(--line); }
:root[data-theme="light"] .cb-nav-links { background: rgba(246,244,250,.97); }

/* -- Footer link row: inline text flow, CSS separators -- */
.cb-footlinks { line-height: 2.2; }
.cb-footlinks a { display: inline-block; padding: 2px 0; }
.cb-footlinks a:not(:last-child)::after { content: "."; margin: 0 9px; color: var(--text-3); }
@media (max-width: 640px) {
    .cb-footer .cb-between { flex-direction: column; align-items: center; text-align: center; gap: 14px; }
    .cb-footlinks { text-align: center; }
    .cb-footmeta { text-align: center; }
}
@media (min-width: 641px) { .cb-footmeta { text-align: right; } }

/* -- <=640 phone: the bulk of the mobile pass -- */
@media (max-width: 640px) {
    /* spacing: lighter top, shorter tail */
    .cb-main { padding: 24px 0 64px; }

    /* typography scale-down */
    .h1 { font-size: 22px; }
    .h2 { font-size: 18px; }
    .stat .num { font-size: 24px; }

    /* navbar: fixed 60px height, logo breathing room */
    .cb-nav-inner { height: 60px; gap: 16px; padding-left: 20px; padding-right: 20px; }
    .cb-logo { font-size: 17px; }

    /* tap-target-friendly buttons (44px min) */
    .btn { min-height: 44px; }
    .btn-lg { width: 100%; }               /* full-width friendly */
    .btn-sm { padding: 9px 13px; }         /* compact so wrapping tab-bars stay 1-2 rows */

    /* inputs >=16px stop iOS auto-zoom on focus */
    .input, .select, .textarea { font-size: 16px; }

    /* list rows wrap; avatar pinned top-left, right metadata drops below */
    .row-item { flex-wrap: wrap; align-items: flex-start; }
    .row-item > .avatar,
    .row-item > .avatar-sm,
    .row-item > .avatar-lg { flex-shrink: 0; }

    /* footer stacks + centers */
    .cb-footer { padding: 28px 0; margin-top: 48px; text-align: center; }
    .cb-footer .cb-between,
    .cb-footer .cb-flex { flex-direction: column; align-items: center; gap: 10px; }
}

/* -- <=480: tighter side gutters -- */
@media (max-width: 480px) {
    .cb-wrap,
    .cb-wrap-narrow { padding-left: 16px; padding-right: 16px; }
    .cb-nav-inner { padding-left: 16px; padding-right: 16px; }
    .empty { padding: 44px 18px; }
}

/* -- <=430 small phones (360-430): reclaim card padding -- */
@media (max-width: 430px) {
    .card { padding: 20px; }
    .card-pad-sm { padding: 16px; }
    .avatar-lg { width: 60px; height: 60px; border-radius: 16px; font-size: 22px; }
    .h-display { letter-spacing: -1px; }
}

/* -- OnlyVega motto: Verify . Earn . Grow . Analyze -- */
.vega-motto { display: flex; align-items: center; justify-content: center; gap: 10px; flex-wrap: wrap;
    font-family: var(--font-display); font-size: 13px; font-weight: 600; letter-spacing: 3px;
    text-transform: uppercase; color: var(--text-2); }
.vega-motto b { background: var(--grad); -webkit-background-clip: text; background-clip: text; color: transparent; font-weight: 800; }
.vega-motto i { color: var(--acc-1); font-style: normal; opacity: .7; }
.vega-motto.compact { font-size: 11px; letter-spacing: 2px; gap: 7px; }
@media (max-width: 480px) { .vega-motto { font-size: 11px; letter-spacing: 1.5px; gap: 6px; } }

/* =========== DAY MODE (light) -- toggle via <html data-theme="light"> =========== */
:root[data-theme="light"] {
    --bg: #F6F4FA;
    --bg-2: #FFFFFF;
    --bg-3: #EFEBF6;
    --card: rgba(20,10,30,.03);
    --card-hover: rgba(20,10,30,.05);
    --line: rgba(30,16,44,.12);
    --line-strong: rgba(30,16,44,.22);
    --text: #17111F;
    --text-2: #4E4560;
    --text-3: #857B96;
    --shadow: 0 20px 60px rgba(30,16,44,.12);
}
/* Colour only -- the light-mode sky is painted on the ROOT element (ov-ui.css), so
   body must stay transparent or it would hide the ambient glow/star layers. */
:root[data-theme="light"] body { color: var(--text); }
:root[data-theme="light"] ::selection { background: rgba(124,92,255,.22); }
/* keep the ambient glow subtle on light */
:root[data-theme="light"] .cb-glow { opacity: .5; }
:root[data-theme="light"] .cb-stars { display: none; }

/* == Notification bell (layout.php) == */
.ov-bell-badge {
    position: absolute; top: 1px; right: 1px;
    min-width: 15px; height: 15px; padding: 0 4px;
    border-radius: 8px; background: var(--bad); color: #fff;
    font-size: 9.5px; font-weight: 700; line-height: 15px; text-align: center;
}
.notif-row { display: flex; gap: 12px; align-items: flex-start; padding: 13px 16px; border-top: 1px solid var(--line); }
.notif-row:first-child { border-top: none; }
.notif-row.is-unread { background: rgba(61,125,255,.05); }
.notif-ico { flex-shrink: 0; width: 30px; height: 30px; border-radius: 8px; display: flex; align-items: center; justify-content: center; background: var(--surface-2, rgba(255,255,255,.04)); color: var(--text-2); }
.notif-ico.sev-good { color: var(--ok); }
.notif-ico.sev-warn { color: var(--warn); }
.notif-ico.sev-critical { color: var(--bad); }

/* Bell dropdown: fixed width, wrapped text, never a horizontal scrollbar. */
.ov-bell-menu { width: min(360px, calc(100vw - 20px)); overflow-x: hidden; }
.ov-bell-menu a, .ov-bell-menu a span { white-space: normal; overflow-wrap: break-word; }
.ov-bell-menu .tiny { white-space: normal; }

/* ===============================================================
   HORIZONTAL OVERFLOW CONTAINMENT
   The page scrolls DOWN only. Anything too wide scrolls INSIDE its
   own box. body{overflow-x:clip} at the top of this file is only the
   last line of defence; the rules below remove the causes, because a
   clipped page hides content instead of letting you reach it.

   The one mechanism behind almost every case: a flex item and a grid
   item both get min-width:auto by default, which resolves to their
   MIN-CONTENT width. Such a child will not shrink, so the parent
   grows, and the growth travels up until the page itself is wider
   than the window. Handing the child min-width:0 is what lets the
   designated scroll container do its job.
   =============================================================== */

/* 1) Flex children of the shared layout utilities may shrink. Buttons are excluded on
      purpose: they carry white-space:nowrap, so shrinking them clips the label rather
      than wrapping it -- they wrap to the next line instead (.wrap / flex-wrap). */
.cb-flex > *:not(.btn),
.cb-between > *:not(.btn),
.row-item > *:not(.btn),
.ov-bulkbar > *:not(.btn) { min-width: 0; }

/* 2) The page shell itself is shrinkable, in case a wrap lands inside a flex parent. */
.cb-main, .cb-wrap, .cb-wrap-narrow, .field, form { min-width: 0; }

/* 3) Big display numbers are the other classic culprit: "$1,234,567.89" set at 32px has
      no break opportunity, so its min-content width alone can outgrow a 4-up stat grid.
      Scale it with the viewport and, as a final resort, allow the number to break. */
.stat .num { font-size: clamp(24px, 2.6vw, 32px); overflow-wrap: anywhere; }

/* 4) Long unbroken strings (URLs, emails, handles, hashes, IDs). overflow-wrap:anywhere
      rather than break-word: only `anywhere` also lowers the element's min-content
      width, which is what stops it forcing a parent wider in the first place. */
.chip, .badge, .timeline-item, .notif-row, .ov-menu a, .form-err, .form-ok { overflow-wrap: anywhere; }
pre, code, kbd, samp { overflow-wrap: anywhere; }
pre { overflow-x: auto; max-width: 100%; }
iframe, embed, object, canvas { max-width: 100%; }

/* 5) Decorative absolutely-positioned layers are measured too. The hero aura was sized
      in vw while being centred on its (narrower, gutter-inset) parent, so it stuck out
      past both edges; a percentage keeps it inside whatever holds it. */
.cb-hero-glow::before { max-width: 92%; }

/* 6) Wide tables: give the wrapper the scroll, keep the table intact inside it. Any
      block that has been made a scroller must also be allowed to shrink, otherwise it
      is sized by the table and never scrolls -- the page does. */
.table-scroll,
[style*="overflow-x:auto"],
[style*="overflow-x: auto"] { min-width: 0; max-width: 100%; }

/* ==========================================================================
   FLOATING MESSENGER  (layout.php button + hire/dm.php?panel=1 in an iframe)
   z-index 300/301 sits above the sticky nav (100) and .ov-menu (200) and below
   .ov-overlay (10001), so it collides with nothing. /hire has no fixed bottom
   nav, so the bottom-right corner is free on every page.
   ========================================================================== */
.ov-dmfab {
    position: fixed; z-index: 301;
    right: max(20px, env(safe-area-inset-right, 0px));
    bottom: max(20px, env(safe-area-inset-bottom, 0px));
    width: 56px; height: 56px; border-radius: 50%; border: none; cursor: pointer;
    background: var(--acc-1); color: #fff; font-size: 20px;
    box-shadow: 0 10px 30px rgba(0, 0, 0, .4);
    display: flex; align-items: center; justify-content: center;
    transition: transform .16s ease, box-shadow .16s ease;
}
.ov-dmfab:hover  { transform: translateY(-2px); box-shadow: 0 14px 36px rgba(0, 0, 0, .5); }
.ov-dmfab:active { transform: translateY(0); }
.ov-dmfab:focus-visible { outline: 2px solid var(--acc-1); outline-offset: 3px; }
.ov-dmfab.is-open i::before { content: "\f00d"; }   /* fa-xmark while the panel is open */
/* The shared nav badge needs repositioning on a button this size. */
.ov-dmfab .ov-bell-badge {
    top: 4px; right: 4px; min-width: 18px; height: 18px;
    border-radius: 9px; font-size: 11px; line-height: 18px;
}

.ov-dmpanel {
    position: fixed; z-index: 300;
    right: max(20px, env(safe-area-inset-right, 0px));
    bottom: calc(max(20px, env(safe-area-inset-bottom, 0px)) + 68px);
    width: 380px; height: min(560px, calc(100vh - 140px));
    background: var(--bg-2); border: 1px solid var(--line);
    border-radius: var(--r-md); box-shadow: var(--shadow); overflow: hidden;
}
.ov-dmpanel[hidden] { display: none; }
.ov-dmpanel-frame { width: 100%; height: 100%; border: 0; display: block; }

/* Phone: dock it to the bottom edge full width, like a native sheet. */
@media (max-width: 520px) {
    .ov-dmpanel {
        right: 0; left: 0; bottom: 0; width: auto;
        height: min(78vh, 640px);
        border-radius: var(--r-md) var(--r-md) 0 0; border-bottom: none;
    }
}

/* ==========================================================================
   Unified inbox (messages.php) -- conversation rows.
   Unread rows must be unmistakable: accent edge, lifted background, bold
   name and preview, solid count pill. Read rows stay quiet. Everything is
   driven by --acc-1 so every accent theme (and light mode) just works.
   ========================================================================== */
.ov-inbox { overflow: hidden; }
.ov-msg-row {
    display: flex; align-items: center; gap: 12px;
    padding: 13px 16px; position: relative;
    border-bottom: 1px solid var(--line);
    text-decoration: none; color: inherit;
    transition: background .15s ease;
}
.ov-msg-row:last-child { border-bottom: none; }
.ov-msg-row:hover { background: var(--card-hover); }
.ov-msg-ava { flex-shrink: 0; display: flex; }
.ov-msg-main { flex: 1; min-width: 0; }
.ov-msg-top { display: flex; align-items: center; gap: 8px; min-width: 0; }
.ov-msg-name {
    font-weight: 500; font-size: 14.5px; color: var(--text);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ov-msg-sub {
    display: flex; align-items: center; gap: 7px; min-width: 0;
    margin-top: 2px; font-size: 12.5px; color: var(--text-3);
}
.ov-msg-snippet { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.ov-msg-badge { font-size: 10px; padding: 1px 7px; flex-shrink: 0; }
.ov-msg-pill {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 20px; height: 20px; padding: 0 6px; flex-shrink: 0;
    border-radius: 999px; background: var(--acc-1); color: #fff;
    font-size: 11px; font-weight: 700; line-height: 1;
    box-shadow: 0 2px 8px color-mix(in srgb, var(--acc-1) 45%, transparent);
}
.ov-msg-meta {
    display: flex; flex-direction: column; align-items: flex-end; gap: 2px;
    flex-shrink: 0; text-align: right;
}
.ov-msg-time { font-size: 11.5px; color: var(--text-3); white-space: nowrap; }
.ov-msg-count { font-size: 11px; color: var(--text-3); white-space: nowrap; }

/* The unread state. */
.ov-msg-row.is-unread { background: color-mix(in srgb, var(--acc-1) 7%, transparent); }
.ov-msg-row.is-unread:hover { background: color-mix(in srgb, var(--acc-1) 11%, transparent); }
.ov-msg-row.is-unread::before {
    content: ""; position: absolute; left: 0; top: 8px; bottom: 8px; width: 3px;
    border-radius: 0 3px 3px 0; background: var(--acc-1);
}
.ov-msg-row.is-unread .ov-msg-name { font-weight: 700; }
.ov-msg-row.is-unread .ov-msg-sub { color: var(--text-2); font-weight: 600; }
.ov-msg-row.is-unread .ov-msg-time { color: var(--acc-1); font-weight: 600; }

/* Narrow phones: keep the row on one line, drop the message count. */
@media (max-width: 480px) {
    .ov-msg-row { padding: 12px 12px; gap: 10px; }
    .ov-msg-count { display: none; }
    .ov-msg-name { font-size: 14px; }
}
