/*
Theme Name: CVJOBBOX Custom
Author: WorkBuddy
Description: Standalone, privacy-first job board theme for any WordPress site. Portable by design: every URL comes from home_url(), the visible site name and the notification mailbox come from WordPress settings, and no domain, host, path or email address is hard-coded - install it on any domain and any host without editing a line. A deliberately small feature set: no public resume database, no candidate search, no marketplace features. No parent theme, no page builder, no commercial job plugin required. Ships a noo_job job catalogue, isolated candidate + employer roles with real capabilities, employer membership levels with monthly contact/resume quotas, candidate regions with quota weights and minimum levels, one-off contact / resume passes, a central administrator policy screen, private resume uploads with gated downloads, a right-side floating account drawer, a URL-based job search with facet counts, closing dates, saved-search e-mail alerts and a Customizer-controlled colour system. Every feature is one independently switchable module. Tested on WordPress 7.1 with PHP 8.4 (mbstring optional).
Version: 2.3.0
Requires PHP: 7.4
Requires at least: 5.8
Tested up to: 7.1
Text Domain: cvjobbox
License: GPLv2 or later

INSTALL
1. Install as a STANDALONE theme package: Appearance > Themes > Add New > Upload Theme > cvjobbox-custom-theme.zip. The theme is never bundled inside a plugin.
2. Go to Settings > Permalinks and click Save (rebuilds /jobs/ job-type/ job-location/ URLs).
3. Appearance > Customize > CVJOBBOX Colours to pick one of four skins or set custom brand colours.
4. Jobs use post type noo_job with job_category / job_type / job_location. This is a brand-new independent site: publish jobs in wp-admin > Jobs, in the front-end Post a job form, or use the separate CVJOBBOX Job Import plugin to bring in job CONTENT from a WXR export (old authors, users, settings and media are never imported; legacy source-site URLs are rewritten to this domain).
4a. Category, city, job type and country are pickers everywhere, and both pickers read the same vocabulary: the terms this board already uses, plus "add a new one". A new value typed by an employer is held on the job and only becomes a term when an administrator publishes it; an administrator creates it on save. The CVJOBBOX Job Editor plugin mirrors the front-end form in wp-admin > Jobs > Add New.
5. New accounts use job_seeker / employer / pending_employer. Any user without an employer role is treated as a candidate.
6. wp-admin > CVJOBBOX > Review & access log: verify employer signups, approve public-contact requests, view all contacts and the access log.
7. Candidate contacts stay private until the candidate authorises a specific application, or an admin approves publication. All views are logged.
8. wp-admin > CVJOBBOX > Resume & mailbox: set the receiving mailbox, allowed formats, size cap, whether the file is attached to the email, and whether the mailbox button is shown on the site.
9. Resumes are stored in wp-content/cvjobbox-private/resumes/ with random names plus .htaccess and web.config deny rules. There is NO public URL - downloads go through admin-post.php, which re-checks permission and logs every attempt.
10. Nginx does not read .htaccess. Add: location ^~ /wp-content/cvjobbox-private/ { deny all; return 403; }
11. The notification email (and any attached resume copy) lives in the administrator's mailbox, outside the site permission system. Use a restricted company mailbox and check that wp_mail() works on this host.
12. wp-admin > CVJOBBOX > Privacy & access: one screen owns every permission switch (privacy rules, membership quota gate, single passes, country limits, sign-in throttling), the emergency bulk controls and account suspension. Defaults are the strictest setting.
13. English-only interface by design. No Chinese or bilingual mode is included.

MEMBERSHIP (v1.5.0)
14. Two independent server-side gates: PRIVACY first (candidate per-application authorisation, or admin-approved publication), then ACCESS metering (monthly level quota or a single-use pass, plus the candidate's region). A paid level never buys a candidate's consent.
15. wp-admin > CVJOBBOX > Membership & upgrades: configure the four level types, their monthly contact / resume allowances (all numbers are administrator-controlled), country scope, an admin-only price reference and validity. No price is published on the public site. Upgrade requests are approved offline.
16. wp-admin > CVJOBBOX > Single passes: approve "1 contact" / "1 resume read" requests, issue passes manually and see balances. A pass is one candidate, one action, and never expires.
17. wp-admin > CVJOBBOX > Countries & regions: three signup choices (China / Overseas / Others, with a typed country), editable quota weight (1-5) and minimum membership level (0-3). Candidates choose a country at signup or in their account; employers get a home country.
18. wp-admin > CVJOBBOX > Access ledger: every charged unlock, which candidate, which action and whether it came from a quota or a pass. Re-opening the same candidate for the same action is never charged twice.
19. Employer HR personal contacts are never public and never visible to other employers. Only an admin-verified COMPANY contact may be shown to job seekers, and only while that switch is on.

MODULES (v1.5.0)
20. 20 units. One feature = one folder in modules/<id>/: manifest.php (metadata + dependencies + contracts), module.php (implementation), parts/ (optional HTML fragments).
21. wp-admin > CVJOBBOX > Modules lists every unit, its version, dependencies and contracts; optional units can be switched off individually, and "Safe mode" turns all optional units off at once.
22. core/contracts.php is the only map of "which unit provides which ability". Cross-unit code calls jobsapk_contract( 'namespace.ability', ... ), never another unit's function directly.
23. core/fallbacks.php defines fail-closed shims: if a unit is off or broken, permission checks answer false, data answers empty and resume downloads are refused. Turning a unit off can only remove capability, never widen it.
24. foundation / roles / policy / privacy are locked security units: always on, but each can still be replaced by overwriting its folder while keeping the same id. regions -> membership -> credits -> access is a dependency chain that resolves automatically.
25. Integration points between units: jobsapk/frontend_config (each unit adds its own JS config), jobsapk/footer_overlays (each unit injects its own overlay), jobsapk/admin_review_url, jobsapk/flush_rewrite_types, jobsapk/contract/<name>.

CONTENT & LAYOUT (v1.7.0)
26. Every employer can have an independent company home page: /company/<slug>/, with a public directory at /companies/. The page is a separate record from the account, so it can exist without a login (imported jobs) and be approved on its own. It is published only after an administrator approves it.
27. A company page shows the logo, description, industry, size, city, founding year, website and every published vacancy of that company. It never shows a contact detail: HR e-mail, phone and messenger handles are stripped server-side on every save, so the profile cannot be used to bypass the contact gates.
28. Employers edit the page from Account > Company page (?section=company). Changing an approved page keeps it live and flags it for an administrator re-check in CVJOBBOX > Companies.
29. CVJOBBOX > Companies is the review queue: approve (also verifies the linked employer account), send back, reject, take offline, and one button that builds company records from the company names already stored on jobs.
30. single.php + comments.php + page.php + index.php + 404.php render complete post, page and job content with the standard comment form. 7 widget areas (blog/page/job sidebars and 4 footer columns) are available in Appearance > Widgets, each with built-in default content. The footer also has a quick-link tool bar and a back-to-top button.
31. wp-admin > CVJOBBOX > Homepage & copy (or Appearance > Customize > CVJOBBOX Homepage & copy) edits every headline, note, logo subtitle and footer line. The home page is a board: search strip, Featured jobs, Latest jobs, companies, membership levels, footer. No job counts are hard-coded on the public site.
32. Signed-in members, including administrators, go straight to the account / #post-job screen. If wp-admin is logged in but the front end still shows "Sign in", WordPress Address and Site Address use different hosts (or http vs https) - align Settings > General and sign in again.
33. /how-it-works/ is a real page rendered by the how-it-works unit. Its copy is edited in wp-admin > Pages, in the "CVJOBBOX page copy" box under the editor, and CVJOBBOX > Pages & copy can restore the shipped text page by page.
34. Every page the theme builds in code, and every page a plugin seeds with starter text, is registered in the page-copy unit with its factory copy. Edits are stored as overrides only, so a restore cannot fail and a theme update still reaches pages nobody customised. It explains the permission model, the two server-side access gates and the live unit map, so the home page stays a job board with one strip linking to it. The page is created on theme activation, by CVJOBBOX Setup and by the Company Pages plugin; menu and footer links fall back to /how-it-works/ when it is missing.

v1.9.1
35. The sign-in / sign-up drawer exposes the neutral jobsapk/auth_quick_login action. The standalone CVJOBBOX Social Login plugin renders Google / WeChat / phone sign-in buttons there, each behind its own administrator switch; without the plugin the drawer shows no third-party buttons at all. Both forms also carry WeChat QR codes under the human check. On phones the top bar city strip wraps, the header keeps logo + sign in + Post a job, and the closed drawer is removed from the render tree so an off-screen panel can never create horizontal scroll.

v1.9.2
36. Sign out is available everywhere a signed-in member can land: the drawer button, the account page header row and the account-type chip row (plus the section nav of the focused ?section= screens). The header and chip links carry data-logout, which posts to the same jobsapk_logout endpoint the drawer uses and then returns to the home page; without JavaScript the plain wp_logout_url() link still works. Membership is now strictly an employer concept: a job seeker sees no membership panel, no "Compare levels" link and no plan names anywhere in the account page, and a pending employer sees one plain-language card that says membership opens after approval.

v1.9.3
37. The two account worlds no longer borrow each other's tools. An employer dashboard shows no resume upload, no saved-jobs panel and no "job seeker tools" chip, and ?view=seeker is ignored for employer accounts; a candidate sees no company page, no membership panel and no job editor. Employers edit their own company in place (companies/employer-panel -> company-form, already wired to the review state machine) and now edit their own vacancies in the front end too: ?section=edit-job&job=ID renders the same category / city / country / type pickers as the post form, pre-filled, and jobsapk_ajax_update_job re-checks ownership server-side. A live job stays live and is flagged for an administrator re-read; an empty picker never erases an imported city. The employer's "My job posts" card lists every own job with an Edit chip.

v1.9.4
38. The employer dashboard answers the four questions an employer actually asks, without leaving /account/: how many vacancies are live, in review or drafts; how many applications each one received; where to edit it; and what the current membership level allows. account/parts/employer-jobs.php prints a five-cell stat strip plus one row per vacancy with its state, its application count (and how many are still new), an Edit job link and an Applications link. account/parts/employer-applications.php lists the applications of one vacancy or of all of them, with a state selector (New / Shortlisted / Interview / Hired / Not selected) saved through jobsapk_app_status - the endpoint re-checks that the vacancy belongs to the caller, writes an audit entry and e-mails the candidate their own new state, never any contact data. Contact details still pass the two existing gates: the candidate's per-application authorisation and the employer's monthly quota or single pass. The membership card now states the current level, its country scope and expiry, shows an open request with its date and reminder count, and carries a "Tell the administrator" box: an optional message plus either a level request or a reminder. Both are e-mailed to the administrator with the employer's current level and this month's usage, and the admin request table shows the message and how many reminders were sent. A reminder is limited to one per 12 hours.

*/
/* CVJOBBOX visual system - colours are CSS variables; body[data-skin] switches the whole palette */

:root {
  --brand: #1b4dff;
  --brand-deep: #0d2f9e;
  --brand-soft: #eaf0ff;
  --accent: #ff6a2b;
  --accent-soft: #fff0e7;
  --ink: #10203f;
  --ink-2: #3e4e6b;
  --muted: #8896ad;
  --line: #e6ebf3;
  --bg: #f6f8fc;
  --surface: #ffffff;
  --success: #0fa88f;
  --radius: 16px;
  --radius-sm: 10px;
  --shadow: 0 10px 30px rgba(16, 32, 63, .08);
  --shadow-lg: 0 20px 60px rgba(16, 32, 63, .16);
  --container: 1200px;
}

body[data-skin="forest"] {
  --brand: #0f8f7e;
  --brand-deep: #075a50;
  --brand-soft: #e4f7f3;
  --accent: #f2a03d;
  --accent-soft: #fff5e6;
}

body[data-skin="violet"] {
  --brand: #7038d8;
  --brand-deep: #45219b;
  --brand-soft: #f1eaff;
  --accent: #f0508a;
  --accent-soft: #ffebf2;
}

/* CVJOBBOX Red - the original JobMonster brand orange */
body[data-skin="classic"] {
  --brand: #f14e3b;
  --brand-deep: #c93c2b;
  --brand-soft: #ffeeeb;
  --accent: #f2a900;
  --accent-soft: #fff6e0;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: "PingFang SC", "Microsoft YaHei", "Hiragino Sans GB", "Helvetica Neue", Arial, sans-serif;
  font-size: 15px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  /* clip (not hidden) never creates a scroll container, so the sticky header
     keeps working while any stray wide element is cut off on phones. */
  overflow-x: clip;
}

a { color: inherit; text-decoration: none; }
button, input, select { font: inherit; }
button { cursor: pointer; }
img { max-width: 100%; }

.container { width: min(var(--container), calc(100% - 48px)); margin-inline: auto; }
.muted { color: var(--muted); }
.text-accent { color: var(--accent); }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 42px;
  padding: 0 20px;
  border: 1px solid transparent;
  border-radius: 10px;
  font-weight: 600;
  font-size: 14px;
  white-space: nowrap;
  transition: transform .18s ease, box-shadow .18s ease, background .18s ease;
}
.btn:hover { transform: translateY(-1px); }
.btn-primary { background: var(--brand); color: #fff; box-shadow: 0 6px 16px rgba(27, 77, 255, .22); }
.btn-primary:hover { background: var(--brand-deep); }
.btn-accent { background: var(--accent); color: #fff; box-shadow: 0 6px 16px rgba(255, 106, 43, .24); }
.btn-outline { background: transparent; color: var(--brand); border-color: var(--line); }
.btn-outline:hover { border-color: var(--brand); background: var(--brand-soft); }
.btn-ghost { background: transparent; color: var(--ink-2); }
.btn-ghost:hover { color: var(--brand); }
.btn-lg { height: 52px; padding: 0 30px; font-size: 16px; border-radius: 12px; }
.btn-block { width: 100%; }

/* ---------- Top bar ---------- */
.topbar {
  background: #0d1c38;
  color: #b9c6dd;
  font-size: 12.5px;
  height: 36px;
  line-height: 36px;
}
.topbar .container { display: flex; align-items: center; justify-content: flex-end; }
.topbar a { color: #b9c6dd; }
.topbar a:hover { color: #fff; }
.topbar-links { display: flex; gap: 22px; align-items: center; }
.dot-sep { width: 3px; height: 3px; border-radius: 50%; background: #5c6d8d; }

/* ---------- Main navigation ---------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 60;
  background: rgba(255, 255, 255, .96);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line);
}
.header-inner { height: 74px; display: flex; align-items: center; gap: 36px; }
.logo { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
.logo-mark {
  width: 38px; height: 38px; border-radius: 11px;
  background: linear-gradient(135deg, var(--brand), var(--accent));
  color: #fff; font-weight: 800; font-size: 19px;
  display: grid; place-items: center;
  box-shadow: 0 6px 14px rgba(27, 77, 255, .22);
}
.logo-text { font-size: 21px; font-weight: 800; letter-spacing: -.5px; }
.logo-text span { color: var(--brand); }
.logo-sub { font-size: 11px; color: var(--muted); letter-spacing: 1px; margin-top: -4px; }
.main-nav { display: flex; gap: 30px; height: 100%; align-items: center; flex: 1; }
.main-nav a { font-size: 15px; font-weight: 500; color: var(--ink-2); position: relative; padding: 6px 0; }
.main-nav a:hover, .main-nav a.active { color: var(--brand); }
.main-nav a.active::after {
  content: ""; position: absolute; left: 50%; bottom: -14px; transform: translateX(-50%);
  width: 22px; height: 3px; border-radius: 3px; background: var(--brand);
}
.header-actions { display: flex; align-items: center; gap: 10px; }
.header-divider { width: 1px; height: 20px; background: var(--line); margin: 0 4px; }

/* ---------- Search strip (home page, replaces the hero poster) ---------- */
.search-strip { background: #fff; border-bottom: 1px solid var(--line); padding: 30px 0; }
.search-strip .search-box { max-width: 860px; margin: 0 auto; box-shadow: var(--shadow); border: 1px solid var(--line); }

.search-box {
  background: #fff; border-radius: 14px; padding: 8px;
  display: flex; align-items: center; gap: 6px;
  box-shadow: 0 18px 40px rgba(3, 14, 45, .25);
  max-width: 660px;
}
.search-field { display: flex; align-items: center; gap: 9px; padding: 0 12px; flex: 1; min-width: 0; }
.search-field svg { flex-shrink: 0; color: var(--muted); }
.search-field input, .search-field select {
  border: 0; outline: 0; background: transparent; color: var(--ink);
  height: 44px; width: 100%; font-size: 14.5px;
}
.search-field select { width: 110px; cursor: pointer; }
.field-divider { width: 1px; height: 24px; background: var(--line); }

/* ---------- Stats bar ---------- */
.stats-bar { background: #fff; border-bottom: 1px solid var(--line); }
.stats-inner { display: grid; grid-template-columns: repeat(4, 1fr); padding: 26px 0; }
.stat { text-align: center; border-right: 1px solid var(--line); }
.stat:last-child { border-right: 0; }
.stat b { display: block; font-size: 27px; font-weight: 800; color: var(--ink); letter-spacing: -.5px; }
.stat b span { color: var(--brand); }
.stat small { color: var(--muted); font-size: 13px; }

/* ---------- Sections ---------- */
.section { padding: 68px 0; }
.section.soft { background: #fff; }
.section-head { display: flex; align-items: flex-end; justify-content: space-between; margin-bottom: 32px; }
.section-head h2 { font-size: 28px; margin: 0 0 6px; letter-spacing: -.5px; }
.section-head p { margin: 0; color: var(--muted); font-size: 14px; }
.section-head a { color: var(--brand); font-size: 14px; font-weight: 600; }

/* ---------- Job categories ---------- */
.cat-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; }
.cat-card {
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  padding: 22px; transition: .2s ease; display: block;
}
.cat-card:hover { transform: translateY(-4px); box-shadow: var(--shadow); border-color: transparent; }
.cat-icon {
  width: 42px; height: 42px; border-radius: 12px; display: grid; place-items: center;
  background: var(--brand-soft); color: var(--brand); font-weight: 800; font-size: 17px; margin-bottom: 16px;
}
.cat-card:nth-child(2n) .cat-icon { background: var(--accent-soft); color: var(--accent); }
.cat-card h3 { margin: 0 0 6px; font-size: 16px; }
.cat-card p { margin: 0 0 14px; color: var(--muted); font-size: 13px; }

/* ---------- Job list ---------- */
.job-layout { display: grid; grid-template-columns: 1fr 300px; gap: 24px; align-items: start; }
.job-list { display: grid; gap: 14px; }

/* Featured (pinned) vacancies: a two-column band above the latest list. */
.featured-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 18px; }
.featured-grid .job-card { margin: 0; }
@media (max-width: 900px) { .featured-grid { grid-template-columns: 1fr; } }
.job-card {
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  padding: 22px 24px; display: grid; grid-template-columns: 56px 1fr auto; gap: 18px;
  align-items: center; transition: .2s ease;
}
.job-card:hover { border-color: var(--brand); box-shadow: var(--shadow); transform: translateY(-2px); }
/* A pinned vacancy: same card, one quiet marker. Placement is an editorial
   decision, so it is stated in words instead of shouting with a colour block. */
.job-card.is-pinned { border-color: #ffd9c4; }
.job-card.is-pinned:hover { border-color: var(--accent); }
.job-flag {
  display: inline-block; margin-left: 8px; padding: 1px 8px; border-radius: 999px;
  background: var(--accent-soft); color: var(--accent);
  font-size: 11px; font-weight: 700; letter-spacing: .02em; vertical-align: 2px; white-space: nowrap;
}
.company-logo {
  width: 56px; height: 56px; border-radius: 14px; display: grid; place-items: center;
  font-weight: 800; font-size: 20px; color: var(--brand); background: var(--brand-soft);
}
.company-logo.warm { color: var(--accent); background: var(--accent-soft); }
.job-title { font-size: 17px; font-weight: 700; margin: 0 0 6px; }
.job-title:hover { color: var(--brand); }
.job-company { font-size: 13px; color: var(--ink-2); margin-bottom: 10px; }
.job-company span { color: var(--muted); margin-left: 10px; }
.job-tags { display: flex; gap: 8px; flex-wrap: wrap; }
.job-tags span { background: var(--bg); color: var(--ink-2); font-size: 12px; padding: 3px 10px; border-radius: 6px; }
.job-side { text-align: right; min-width: 130px; }
.job-pay { color: var(--accent); font-weight: 800; font-size: 18px; white-space: nowrap; }
.job-time { color: var(--muted); font-size: 12px; margin: 6px 0 12px; }
.btn-apply { background: var(--brand-soft); color: var(--brand); border: 0; border-radius: 8px; padding: 7px 16px; font-size: 13px; font-weight: 700; }
.btn-apply:hover { background: var(--brand); color: #fff; }
.btn-apply.done { background: var(--success); color: #fff; }

/* Saved jobs (independent saved-jobs unit) */
.btn-save { display: block; margin: 8px 0 0 auto; background: transparent; border: 1px solid var(--line); color: var(--muted); border-radius: 8px; padding: 5px 12px; font-size: 12px; font-weight: 600; cursor: pointer; }
.btn-save:hover { border-color: var(--brand); color: var(--brand); }
.btn-save.is-saved { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }
.saved-card { scroll-margin-top: 90px; }
.saved-list { display: grid; gap: 10px; margin-top: 16px; }
.saved-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; padding: 14px 16px; border: 1px solid var(--line); border-radius: 10px; background: var(--bg); }
.saved-row-main { display: grid; gap: 4px; min-width: 0; }
.saved-row-main a { font-weight: 700; color: var(--ink); }
.saved-row-main a:hover { color: var(--brand); }
.saved-row-main .muted { font-size: 12.5px; }
.saved-empty { margin-top: 16px; padding: 26px 20px; border: 1px dashed var(--line); border-radius: 12px; text-align: center; background: var(--bg); }
.saved-empty b { display: block; font-size: 15px; margin-bottom: 8px; }
.saved-empty p { font-size: 13px; margin: 0 0 16px; }

.side-card { background: #fff; border: 1px solid var(--line); border-radius: var(--radius); padding: 24px; margin-bottom: 16px; }
.side-card h3 { margin: 0 0 16px; font-size: 17px; }
.filter-row { display: flex; flex-wrap: wrap; gap: 8px; }
.chip { border: 1px solid var(--line); background: #fff; color: var(--ink-2); border-radius: 8px; padding: 6px 12px; font-size: 13px; }
.chip:hover, .chip.active { border-color: var(--brand); color: var(--brand); background: var(--brand-soft); }
.side-cta { background: linear-gradient(135deg, var(--brand-deep), var(--brand)); color: #fff; border-radius: var(--radius); padding: 26px; }
.side-cta h3 { margin: 0 0 8px; font-size: 19px; }
.side-cta p { color: rgba(255,255,255,.8); font-size: 13px; margin: 0 0 18px; }
.side-cta .btn { background: #fff; color: var(--brand); }


/* ---------- Footer ---------- */
.site-footer { background: #0d1c38; color: #a9b7cf; padding: 56px 0 24px; }
.footer-grid { display: grid; grid-template-columns: 1.5fr repeat(4, 1fr); gap: 32px; padding-bottom: 40px; }
.footer-brand p { font-size: 13px; max-width: 260px; margin: 16px 0; }
.footer-col h4 { color: #fff; font-size: 14px; margin: 0 0 16px; }
.footer-col a { display: block; font-size: 13px; margin-bottom: 10px; }
.footer-col a:hover { color: #fff; }
.footer-bottom { border-top: 1px solid rgba(255,255,255,.1); padding-top: 20px; font-size: 12.5px; display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap; }

/* ---------- Right floating bar ---------- */
.float-bar {
  position: fixed; right: 18px; top: 50%; transform: translateY(-50%);
  z-index: 80; display: flex; flex-direction: column; gap: 8px;
}
.float-btn {
  width: 58px; min-height: 58px; border-radius: 14px; border: 1px solid var(--line);
  background: #fff; color: var(--ink-2); box-shadow: var(--shadow);
  display: grid; place-items: center; gap: 2px; padding: 8px 4px;
  font-size: 11px; line-height: 1.2; transition: .18s ease;
}
.float-btn svg { width: 19px; height: 19px; stroke: currentColor; fill: none; stroke-width: 1.8; }
.float-btn:hover { color: var(--brand); border-color: var(--brand); transform: translateX(-3px); }
.float-btn.primary { background: var(--accent); color: #fff; border-color: var(--accent); }
.float-btn.primary:hover { color: #fff; background: #e9591e; }
.float-btn.accent-soft { background: var(--brand); color: #fff; border-color: var(--brand); }
.float-btn.accent-soft:hover { color: #fff; }

/* ---------- Floating account drawer ---------- */
.drawer-mask {
  position: fixed; inset: 0; background: rgba(9, 20, 44, .48);
  backdrop-filter: blur(2px); z-index: 90; opacity: 0; visibility: hidden; transition: .25s ease;
}
.drawer-mask.open { opacity: 1; visibility: visible; }
.auth-drawer {
  position: fixed; top: 0; right: 0; bottom: 0; width: 400px; max-width: 92vw;
  background: #fff; z-index: 100; box-shadow: -20px 0 60px rgba(9, 20, 44, .2);
  transform: translateX(100%); visibility: hidden;
  transition: transform .3s cubic-bezier(.2,.8,.2,1), visibility 0s .3s;
  display: flex; flex-direction: column; overflow-y: auto;
}
/* visibility keeps the closed drawer out of the render tree: some mobile
   browsers turn an off-screen fixed element into horizontal page overflow. */
.auth-drawer.open { transform: translateX(0); visibility: visible; transition: transform .3s cubic-bezier(.2,.8,.2,1), visibility 0s; }
.drawer-head { padding: 24px 26px 0; position: relative; }
.drawer-close {
  position: absolute; top: 20px; right: 20px; width: 32px; height: 32px; border-radius: 50%;
  border: 0; background: var(--bg); color: var(--ink-2); font-size: 18px; line-height: 1;
}
.drawer-head h2 { margin: 0 0 4px; font-size: 23px; }
.drawer-head p { margin: 0; color: var(--muted); font-size: 13px; }
.drawer-logo { display: flex; align-items: center; gap: 9px; margin-bottom: 24px; }
.drawer-logo .logo-mark { width: 30px; height: 30px; font-size: 15px; border-radius: 9px; }
.drawer-logo b { font-size: 17px; }

.role-tabs { display: flex; background: var(--bg); border-radius: 11px; padding: 4px; margin: 22px 26px 0; }
.role-tab { flex: 1; height: 38px; border: 0; background: transparent; border-radius: 8px; color: var(--ink-2); font-weight: 600; font-size: 14px; }
.role-tab.active { background: #fff; color: var(--brand); box-shadow: 0 2px 8px rgba(16,32,63,.08); }

.drawer-body { padding: 22px 26px 30px; flex: 1; }
.form-field { margin-bottom: 16px; }
.form-field label { display: block; font-size: 13px; font-weight: 600; margin-bottom: 7px; color: var(--ink-2); }
.input-wrap { position: relative; }
.input-wrap input {
  width: 100%; height: 46px; padding: 0 14px; border: 1px solid var(--line);
  border-radius: 10px; outline: 0; background: #fff; color: var(--ink); transition: .18s;
}
.input-wrap input:focus { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-soft); }
.input-wrap .code-btn {
  position: absolute; right: 6px; top: 6px; height: 34px; border: 0; background: var(--brand-soft);
  color: var(--brand); border-radius: 7px; padding: 0 12px; font-size: 12.5px; font-weight: 600;
}
.form-row { display: flex; align-items: center; justify-content: space-between; font-size: 12.5px; color: var(--muted); margin: 4px 0 18px; }
.form-row a { color: var(--brand); }
.form-row label { display: flex; align-items: center; gap: 6px; cursor: pointer; }
.form-note { font-size: 12px; color: var(--muted); text-align: center; margin: 16px 0 0; }
.form-note a { color: var(--brand); font-weight: 600; }

/* English file picker: the browser's native "Choose file" label follows the
   visitor's OS language, so we hide the chrome and draw our own English UI.
   The real input stays on top (opacity 0) so required / focus / keyboard
   behaviour is unchanged. */
.cvjb-file-picker { position: relative; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; background: #fff; }
.cvjb-file-input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; z-index: 2; }
.cvjb-file-trigger { background: var(--brand-soft); color: var(--brand); border-radius: 8px; padding: 8px 16px; font-size: 13px; font-weight: 700; cursor: pointer; }
.cvjb-file-name { color: var(--muted); font-size: 13px; word-break: break-all; }
.cvjb-file-picker:focus-within { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-soft); }
.divider { display: flex; align-items: center; gap: 12px; color: var(--muted); font-size: 12px; margin: 24px 0 16px; }
.divider::before, .divider::after { content: ""; flex: 1; height: 1px; background: var(--line); }
.quick-login { display: flex; gap: 10px; }
.quick-btn { flex: 1; height: 42px; border: 1px solid var(--line); background: #fff; border-radius: 10px; color: var(--ink-2); font-size: 13px; font-weight: 600; }
.quick-btn:hover { border-color: var(--brand); color: var(--brand); }
.drawer-benefit { background: var(--bg); border-radius: 12px; padding: 14px 16px; margin-top: 22px; font-size: 12.5px; color: var(--ink-2); }
.drawer-benefit b { display: block; color: var(--ink); margin-bottom: 6px; font-size: 13px; }
.drawer-benefit ul { margin: 0; padding-left: 18px; }

.user-panel { text-align: center; padding-top: 12px; }
.user-avatar { width: 66px; height: 66px; border-radius: 50%; margin: 0 auto 14px; display: grid; place-items: center; background: var(--brand-soft); color: var(--brand); font-size: 24px; font-weight: 800; }
.user-panel h3 { margin: 0 0 4px; }
.user-panel p { color: var(--muted); font-size: 13px; margin: 0 0 22px; }
/* The signed-in account type, so a candidate never looks like an employer. */
.user-role-chip { display: inline-block; margin: 0 0 8px; padding: 3px 10px; border-radius: 999px; font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; background: var(--brand-soft); color: var(--brand); }
.user-role-chip[data-role="employer"] { background: #fff3e0; color: #a35700; }
.user-role-chip[data-role="pending_employer"] { background: #eef1f4; color: #55606c; }
.user-role-chip[data-role="administrator"] { background: #ecebff; color: #4034a8; }
.user-panel .user-type-note { font-size: 11.5px; line-height: 1.55; margin: 12px 0 16px; }
.user-links { display: grid; gap: 10px; text-align: left; }
.user-links[hidden] { display: none; }
.user-link { display: flex; justify-content: space-between; align-items: center; padding: 13px 16px; border: 1px solid var(--line); border-radius: 10px; font-size: 14px; }
.user-link:hover { border-color: var(--brand); color: var(--brand); }
.user-link span { color: var(--muted); font-size: 12px; }

/* ---------- Toasts ---------- */
.toast {
  position: fixed; left: 50%; top: 24px; transform: translate(-50%, -20px);
  background: var(--ink); color: #fff; padding: 11px 20px; border-radius: 10px;
  font-size: 13.5px; z-index: 200; opacity: 0; visibility: hidden; transition: .25s ease;
  box-shadow: var(--shadow-lg);
}
.toast.show { opacity: 1; visibility: visible; transform: translate(-50%, 0); }
.toast.ok { background: var(--success); }
.toast.err { background: #d8493f; }

/* ---------- WordPress menu / content / pagination ---------- */
.main-nav li { list-style: none; margin: 0; padding: 0; }
.main-nav .current-menu-item > a,
.main-nav .current_page_item > a { color: var(--brand); }
.main-nav .current-menu-item > a::after {
  content: ""; position: absolute; left: 50%; bottom: -14px; transform: translateX(-50%);
  width: 22px; height: 3px; border-radius: 3px; background: var(--brand);
}
.prose { font-size: 15px; color: var(--ink-2); line-height: 1.8; }
.prose h2, .prose h3 { color: var(--ink); margin: 24px 0 10px; }
.prose p { margin: 0 0 14px; }
.prose ul, .prose ol { padding-left: 20px; margin: 0 0 16px; }
.prose img { max-width: 100%; height: auto; border-radius: 12px; }
.prose a { color: var(--brand); text-decoration: underline; }
.prose pre { overflow: auto; background: var(--bg); padding: 14px; border-radius: 10px; }
.pagination { display: flex; gap: 8px; flex-wrap: wrap; }
.pagination .page-numbers { padding: 8px 14px; border: 1px solid var(--line); border-radius: 8px; background: #fff; color: var(--ink-2); }
.pagination .page-numbers.current { background: var(--brand); color: #fff; border-color: var(--brand); }

/* ---------- Permissions / privacy components ---------- */
.perm-badge {
  display: inline-flex; align-items: center; height: 26px; padding: 0 12px;
  border-radius: 30px; font-size: 12px; font-weight: 700; white-space: nowrap;
}
.role-private { background: var(--bg); color: var(--ink-2); border: 1px solid var(--line); }
.role-pending { background: var(--accent-soft); color: var(--accent); }
.role-public  { background: #e4f7ee; color: var(--success); }
.role-admin   { background: var(--brand-soft); color: var(--brand); }
.application-box { border: 1px solid var(--line); border-radius: 12px; padding: 16px; margin-top: 12px; }
.contact-box { margin-top: 12px; padding: 12px 14px; background: var(--bg); border-radius: 10px; font-size: 13.5px; color: var(--ink-2); }
.contact-box:empty { display: none; }
.contact-row { padding: 3px 0; }
.contact-row b { color: var(--ink); }
.perm-list { margin: 0; padding-left: 18px; font-size: 13.5px; color: var(--ink-2); line-height: 1.7; }
.perm-list li { margin-bottom: 7px; }
.perm-list b { color: var(--ink); }
.company-card h3 { font-size: 16px; }
.privacy-flow { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 22px; }
.privacy-step { flex: 1; min-width: 220px; background: #fff; border: 1px solid var(--line); border-radius: 14px; padding: 20px; }
.privacy-step b { color: var(--brand); font-size: 13px; letter-spacing: .4px; }
.privacy-step p { margin: 10px 0 0; color: var(--muted); font-size: 13px; }

/* ---------- Private resume files / mailbox modal ---------- */
.resume-mask {
  position: fixed; inset: 0; background: rgba(9, 20, 44, .52);
  backdrop-filter: blur(2px); z-index: 120; opacity: 0; visibility: hidden; transition: .25s ease;
}
.resume-mask.open { opacity: 1; visibility: visible; }
.resume-modal {
  position: fixed; left: 50%; top: 50%; transform: translate(-50%, -46%) scale(.98);
  width: 520px; max-width: calc(100vw - 32px); max-height: calc(100vh - 48px);
  overflow-y: auto; z-index: 130; background: #fff; border-radius: 18px;
  box-shadow: 0 30px 90px rgba(9, 20, 44, .32); padding: 30px;
  opacity: 0; visibility: hidden; transition: .25s ease;
}
.resume-modal.open { opacity: 1; visibility: visible; transform: translate(-50%, -50%) scale(1); }
.resume-close {
  position: absolute; top: 16px; right: 16px; width: 34px; height: 34px; border: 0;
  border-radius: 50%; background: var(--bg); color: var(--ink-2); font-size: 20px; line-height: 1;
}
.resume-modal h2 { margin: 14px 0 8px; font-size: 22px; }
.resume-modal > p.muted { margin: 0 0 20px; font-size: 13px; line-height: 1.65; }
.resume-mailbox {
  display: flex; justify-content: space-between; align-items: center; gap: 14px; flex-wrap: wrap;
  background: var(--bg); border: 1px solid var(--line); border-radius: 12px; padding: 16px;
}
.resume-mailbox span.muted, .resume-current span.muted { display: block; font-size: 11.5px; margin-bottom: 5px; }
.resume-mailbox b { font-size: 15px; word-break: break-all; }
.resume-mail-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.resume-mail-hint { margin-top: 12px; background: var(--brand-soft); border-radius: 12px; padding: 14px; }
.resume-mail-hint .form-note { margin-top: 8px; }
.resume-mail-hint[hidden], .resume-current[hidden] { display: none; }
.resume-upload-form { margin-top: 22px; padding-top: 20px; border-top: 1px solid var(--line); }
input[type="file"] {
  width: 100%; padding: 12px; border: 1px dashed var(--line); border-radius: 10px;
  background: #fff; color: var(--ink-2); font-size: 13px;
}
input[type="file"]:focus { outline: 0; border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-soft); }
.resume-upload-form .form-note, #resume .form-note { text-align: left; margin-top: 8px; line-height: 1.6; }
.resume-current {
  display: flex; justify-content: space-between; align-items: center; gap: 14px; flex-wrap: wrap;
  margin-top: 16px; padding: 14px 16px; border: 1px solid var(--line); border-radius: 12px;
}
.resume-current b { font-size: 13.5px; word-break: break-all; }
.resume-note {
  display: flex; justify-content: space-between; align-items: center; gap: 18px; flex-wrap: wrap;
  margin-top: 22px; background: #fff; border: 1px solid var(--line); border-left: 4px solid var(--brand);
  border-radius: 14px; padding: 20px 22px;
}
.resume-note b { font-size: 14.5px; }
.resume-note p { margin: 7px 0 0; color: var(--muted); font-size: 13px; max-width: 720px; line-height: 1.6; }
.contact-download {
  display: inline-block; margin-left: 8px; padding: 5px 11px; border-radius: 8px;
  background: var(--brand); color: #fff !important; font-size: 12px; font-weight: 700; text-decoration: none;
}
.contact-download:hover { background: var(--brand-deep); }

/* ---------- Module map ---------- */
.section-head .btn { flex-shrink: 0; }
.mod-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; }
.mod-card {
  text-align: left; width: 100%; cursor: pointer; font: inherit;
  background: #fff; border: 1px solid var(--line); border-radius: 14px;
  padding: 16px 18px; display: flex; flex-direction: column; gap: 8px;
  transition: .18s ease; min-height: 128px;
}
.mod-card:hover { transform: translateY(-3px); box-shadow: var(--shadow); border-color: var(--brand); }
.mod-card[data-locked="1"] { cursor: default; background: var(--bg); }
.mod-card[data-locked="1"]:hover { transform: none; box-shadow: none; border-color: var(--line); }
.mod-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.mod-head b { font-size: 14px; color: var(--ink); }
.mod-state {
  font-size: 11px; font-weight: 700; border-radius: 20px; padding: 3px 9px;
  background: #e4f7ee; color: var(--success); white-space: nowrap;
}
.mod-card[data-locked="1"] .mod-state { background: var(--brand-soft); color: var(--brand); }
.mod-card.is-off { opacity: .58; border-style: dashed; }
.mod-card.is-off .mod-state { background: #ffeaea; color: #c0392b; }
.mod-id { font-size: 11.5px; color: var(--brand); font-family: ui-monospace, Consolas, monospace; }
.mod-desc { font-size: 12.5px; color: var(--muted); line-height: 1.55; }
.resume-note code, .mod-card code { font-family: ui-monospace, Consolas, monospace; }

/* ---------- Responsive ---------- */
@media (max-width: 1080px) {
  .main-nav { gap: 18px; }
  .job-layout { grid-template-columns: 1fr; }
  .company-grid { grid-template-columns: repeat(2, 1fr); }
  .mod-grid { grid-template-columns: repeat(2, 1fr); }
  .footer-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 760px) {
  .container { width: calc(100% - 32px); }
  .topbar { height: auto; line-height: 1.5; padding: 7px 0; }
  .topbar .container { flex-wrap: wrap; gap: 4px 16px; }
  .header-inner { height: 62px; gap: 12px; }
  /* The header is the widest row on a phone: keep logo + Sign in + Post a job,
     drop the larger secondary buttons and shrink the rest so nothing overflows. */
  .header-actions { gap: 6px; margin-left: auto; flex-shrink: 0; }
  .header-actions .btn { height: 38px; padding: 0 12px; font-size: 13px; }
  .header-actions .btn-outline, .header-divider { display: none; }
  .header-actions .btn-ghost { display: inline-flex; }
  .logo-text { font-size: 17px; }
  .logo-mark { width: 32px; height: 32px; font-size: 16px; border-radius: 9px; }
  .logo-sub { display: none !important; }
  .search-box { flex-wrap: wrap; border-radius: 12px; }
  .search-field { flex-basis: 100%; }
  .field-divider { display: none; }
  .search-box .btn { width: 100%; }
  .stats-inner { grid-template-columns: repeat(2, 1fr); gap: 18px 0; }
  .stat:nth-child(2) { border-right: 0; }
  .cat-grid { grid-template-columns: repeat(2, 1fr); }
  .mod-grid { grid-template-columns: 1fr; }
  .section { padding: 48px 0; }
  .job-card { grid-template-columns: 46px 1fr; padding: 18px; }
  .company-logo { width: 46px; height: 46px; font-size: 16px; }
  .job-side { grid-column: 1 / -1; display: flex; align-items: center; justify-content: space-between; text-align: left; }
  .job-time { margin: 0; }
  .company-grid, .footer-grid { grid-template-columns: 1fr; }
  .float-bar { right: 10px; top: auto; bottom: 18px; transform: none; flex-direction: row; flex-wrap: wrap; width: calc(100% - 20px); justify-content: flex-end; }
  .float-btn { width: 48px; min-height: 48px; font-size: 10px; }
  .float-btn svg { width: 16px; height: 16px; }
  .resume-modal { padding: 24px 20px; }
  .resume-modal h2 { font-size: 19px; }
  .resume-mailbox, .resume-current, .resume-note { flex-direction: column; align-items: flex-start; }
}

/* ---------- v1.5.0: membership levels, quotas and single passes ---------- */
.input-wrap select {
  width: 100%; height: 46px; padding: 0 14px; border: 1px solid var(--line);
  border-radius: 10px; outline: 0; background: var(--surface); color: var(--ink); cursor: pointer;
}
.input-wrap select:focus { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-soft); }
.plan-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; margin-top: 20px; }
.plan-grid.compact { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.plan-card {
  position: relative; display: flex; flex-direction: column; gap: 8px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 24px 20px 20px; box-shadow: var(--shadow); min-width: 0;
}
.plan-card.featured { border-color: var(--brand); box-shadow: 0 16px 40px rgba(27, 77, 255, .16); }
.plan-card .perm-list { margin: 6px 0 12px; flex: 1; }
.plan-card .btn { margin-top: auto; }
.plan-ribbon {
  position: absolute; top: -11px; right: 16px; background: var(--brand); color: #fff;
  font-size: 10.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  padding: 5px 10px; border-radius: 20px;
}
.plan-name { font-size: 17px; color: var(--ink); }
.plan-note { font-size: 12.5px; color: var(--muted); line-height: 1.55; margin: 0 0 4px; min-height: 38px; }
.plan-line { font-size: 12.5px; color: var(--ink-2); }
.plan-grid.compact .plan-card { padding: 18px 16px; box-shadow: none; }
.plan-grid.compact .plan-note, .plan-grid.compact .perm-list { display: none; }

.pass-strip {
  display: flex; justify-content: space-between; align-items: center; gap: 24px; flex-wrap: wrap;
  margin-top: 20px; padding: 22px 26px; border-radius: var(--radius);
  background: var(--brand-soft); border: 1px solid var(--line);
}
.pass-strip h3 { margin: 0 0 6px; font-size: 18px; }
.pass-strip p { margin: 0; max-width: 620px; font-size: 13px; line-height: 1.6; }
.pass-strip-actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.pass-pill { background: var(--surface); border: 1px solid var(--line); border-radius: 20px; padding: 7px 13px; font-size: 12.5px; color: var(--muted); white-space: nowrap; }
.pass-pill b { color: var(--ink); }

.quota-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; margin: 16px 0; }
.quota-cell { background: var(--bg); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 14px; }
.quota-title { display: flex; justify-content: space-between; gap: 10px; font-size: 13px; color: var(--ink-2); margin-bottom: 10px; }
.quota-title b { color: var(--brand); }
.quota-bar { height: 7px; border-radius: 10px; background: var(--line); overflow: hidden; margin-bottom: 8px; }
.quota-bar i { display: block; height: 100%; background: var(--brand); border-radius: 10px; }
.plan-meta { display: flex; flex-wrap: wrap; gap: 8px 20px; font-size: 12.5px; color: var(--muted); padding: 12px 0 4px; border-top: 1px solid var(--line); }
.plan-meta b { color: var(--ink-2); font-weight: 600; }

.pass-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin-top: 14px; }
.pass-item { display: flex; flex-direction: column; gap: 8px; align-items: flex-start; background: var(--bg); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 16px; }
.pass-item b { font-size: 14px; color: var(--ink); display: block; }
.pass-item .muted { display: block; font-size: 12px; margin-top: 2px; }
.pass-count { font-size: 12px; color: var(--muted); }
.access-hint { margin-top: 10px; font-size: 12.5px; line-height: 1.55; color: var(--ink-2); background: var(--brand-soft); border-radius: 8px; padding: 9px 12px; }
.access-hint.blocked { background: var(--accent-soft); }

@media (max-width: 1080px) {
  .plan-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 760px) {
  .plan-grid, .plan-grid.compact, .quota-grid, .pass-row { grid-template-columns: 1fr; }
  .pass-strip { padding: 18px; }
  .pass-strip-actions { width: 100%; }
}

/* ---------- v1.5.0: full articles, widget areas and footer tool bar ---------- */
.crumbs { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; font-size: 12.5px; color: var(--muted); margin-bottom: 20px; }
.crumbs a { color: var(--brand); }
.content-layout { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 24px; align-items: start; }
.content-main, .content-aside { min-width: 0; }
.article-card { padding: 32px; }
.article-head h1 { margin: 0 0 12px; font-size: 32px; line-height: 1.25; color: var(--ink); }
.article-meta { display: flex; flex-wrap: wrap; gap: 8px 18px; font-size: 12.5px; color: var(--muted); margin-bottom: 22px; }
.article-meta a { color: var(--brand); }
.article-thumb { margin: 0 0 22px; }
.article-thumb img { width: 100%; height: auto; border-radius: 12px; }
.article-body { font-size: 15px; line-height: 1.85; }
.article-body img, .article-body iframe { max-width: 100%; height: auto; }
.article-foot { border-top: 1px solid var(--line); margin-top: 24px; padding-top: 16px; font-size: 12.5px; color: var(--muted); }
.article-foot a { color: var(--brand); }
.tag-list span { font-weight: 700; margin-right: 6px; }
.page-links { margin-top: 20px; font-size: 13px; }
.page-links span { font-weight: 700; margin-right: 8px; }
.post-nav { display: flex; justify-content: space-between; gap: 16px; margin: 18px 0; font-size: 14px; }
.post-nav a { color: var(--brand); }
.archive-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.read-more { display: inline-block; margin-top: 10px; font-size: 13px; font-weight: 700; color: var(--brand); }
.error-code { font-size: 56px; font-weight: 800; color: var(--brand); letter-spacing: -.04em; }

/* Widget areas (Appearance > Widgets) */
.cvjb-widget { background: #fff; border: 1px solid var(--line); border-radius: var(--radius); padding: 20px; margin-bottom: 16px; }
.cvjb-widget .widget-title { margin: 0 0 14px; font-size: 15px; color: var(--ink); }
.cvjb-widget ul { list-style: none; margin: 0; padding: 0; }
.cvjb-widget li { font-size: 13px; padding: 7px 0; border-bottom: 1px dashed var(--line); }
.cvjb-widget li:last-child { border-bottom: 0; }
.cvjb-widget a { color: var(--ink-2); }
.cvjb-widget a:hover { color: var(--brand); }
.cvjb-widget form { display: flex; gap: 8px; flex-wrap: wrap; }
.cvjb-widget input[type="search"], .cvjb-widget input[type="text"] { flex: 1 1 140px; min-width: 0; height: 40px; padding: 0 12px; border: 1px solid var(--line); border-radius: 8px; }
.cvjb-widget input[type="submit"] { border: 0; border-radius: 8px; padding: 0 14px; background: var(--brand); color: #fff; font-size: 13px; cursor: pointer; }
.job-widgets { margin-top: 16px; }
.content-aside .widget, .content-aside .cvjb-widget { width: 100%; }

/* Comments */
.comments-area { margin-top: 20px; }
.comments-title { font-size: 18px; margin: 0 0 18px; color: var(--ink); }
.comment-list { list-style: none; margin: 0 0 20px; padding: 0; }
.comment-list li { padding: 14px 0; border-bottom: 1px solid var(--line); font-size: 14px; }
.comment-list img.avatar { border-radius: 50%; }
.comment-form label { display: block; font-size: 13px; font-weight: 600; margin: 12px 0 6px; }
.comment-form input[type="text"], .comment-form input[type="email"], .comment-form input[type="url"], .comment-form textarea { width: 100%; padding: 10px 12px; border: 1px solid var(--line); border-radius: 9px; }
.comment-form textarea { min-height: 120px; }
.comment-form .form-submit { margin-top: 14px; }
.comment-form .submit { border: 0; cursor: pointer; }

/* Footer widget columns + quick tool bar (self-contained, no external assets) */
.site-footer .footer-col .widget-title { color: #fff; font-size: 14px; margin: 0 0 16px; }
.site-footer .footer-col .widget { background: transparent; border: 0; padding: 0; margin: 0 0 20px; color: #a9b7cf; }
.site-footer .footer-col .widget ul { list-style: none; margin: 0; padding: 0; }
.site-footer .footer-col .widget li { border: 0; padding: 0 0 10px; font-size: 13px; }
.site-footer .footer-col .widget a { color: #a9b7cf; }
.site-footer .footer-col .widget a:hover { color: #fff; }
.foot-toolbar { margin-top: 20px; border-top: 1px solid rgba(255,255,255,.1); padding-top: 18px; display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; }
.foot-tools { display: flex; gap: 8px 18px; flex-wrap: wrap; list-style: none; margin: 0; padding: 0; }
.foot-tools a { font-size: 12.5px; color: #a9b7cf; }
.foot-tools a:hover { color: #fff; }
.foot-top { background: transparent; border: 1px solid rgba(255,255,255,.25); color: #a9b7cf; border-radius: 8px; padding: 7px 14px; font-size: 12.5px; cursor: pointer; }
.foot-top:hover { color: #fff; border-color: #fff; }
.to-top { position: fixed; right: 18px; bottom: 24px; z-index: 85; width: 44px; height: 44px; border-radius: 50%; border: 1px solid var(--line); background: #fff; color: var(--brand); box-shadow: var(--shadow); font-size: 18px; cursor: pointer; opacity: 0; visibility: hidden; transition: .2s ease; }
.to-top.show { opacity: 1; visibility: visible; }
.to-top:hover { background: var(--brand); color: #fff; }

@media (max-width: 1080px) {
  .content-layout { grid-template-columns: 1fr; }
  .archive-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 760px) {
  .article-card { padding: 22px 18px; }
  .article-head h1 { font-size: 26px; }
  .archive-grid { grid-template-columns: 1fr; }
  .to-top { right: 12px; bottom: 82px; }
  .foot-toolbar { flex-direction: column; align-items: flex-start; }
}

/* In-page anchors (account dashboard + shortlist) */
#post-job, #membership, #membership-info, #privacy, #saved, #upgrade, #applications, #resume { scroll-margin-top: 92px; }
.cvjb-anchor-flash { outline: 2px solid var(--brand); outline-offset: 4px; border-radius: var(--radius); }

/*
PLUGINS (v1.5.2)
24. Deployment and frequently-updated helpers ship as separate small plugins and are NEVER bundled into the theme: CVJOBBOX Setup (one-click go-live), CVJOBBOX SMTP (465/SSL mail), CVJOBBOX Job Import (WXR job content), CVJOBBOX Module Packs (override a single feature unit), CVJOBBOX Slide Verify (server-verified slider) and CVJOBBOX Floating Bar (admin-defined tool bar). Each installs, updates and deactivates independently.
25. The registry exposes the 'jobsapk/module_dirs' filter. A small plugin can register its own modules/ directory; a unit with the same id is discovered after the theme copy and overrides it, so one feature can be updated frequently without editing the theme, the registry or any other unit.

v1.4.2
26. Full singular templates: single.php, page.php, comments.php, 404.php and a singular safety net in index.php. Posts, pages and jobs always render complete content and the standard comment form (the slide-verify plugin hooks into it).
27. Appearance > Widgets exposes 7 areas: blog sidebar, page sidebar, job sidebar and four footer columns. Every area has built-in fallback content, so an empty site never looks broken. The footer also has a quick-link tool bar and a back-to-top button.
28. wp-admin > CVJOBBOX > Homepage & copy edits every public headline / note / footer line. No job counts are hard-coded on the front end.
29. Signed-in members (including administrators) go straight to the account / #post-job screen. Guest CTAs carry data-member-url and are rewritten by JS after an AJAX sign-in, so nobody is asked to register twice.

v1.5.0
30. CVJOBBOX > Homepage & copy > Top bar edits the country label, city links and right-hand links. header.php renders only configured rows through the appearance.topbar contract; no country or city is hard-coded, and the contract fails closed to an empty bar.
31. Guests on /account/ (including /account/#post-job) are sent to the sign-in / registration drawer immediately. After a successful sign-in the page reloads with the original #hash, so the post-job form is shown. A one-time canonical-host redirect handles apex / WWW cookie mismatches.
32. Every right-hand floating-bar destination is a real link: signed-in members reach /account/, /account/#post-job and /account/#saved. Guest rows carry data-member-url and become real links after an AJAX sign-in. Only resume / theme / top stay as on-page actions.
33. The standalone CVJOBBOX Floating Bar plugin overrides ONLY the floating-ui unit; Tools > CVJOBBOX Floating Bar edits label, target, icon, visibility, style and order. jobsapk_render() now resolves parts from the winning manifest path, so an override unit can ship its own templates. Deactivating the plugin restores the theme default bar.

v1.5.1
34. /account/ always shows an Account type & permissions card for every signed-in role, including the job seeker role and its capability list. Administrators and verified employers can open their OWN job seeker tools with ?view=seeker; this never changes a role and never exposes another member's data.
35. Roles are repaired on demand: the site default role is job_seeker, role-less / Subscriber accounts are converted on registration and sign-in, and the sign-in drawer shows the real account type and permissions. The independent CVJOBBOX Account Roles plugin offers a one-click wp-admin audit and repair.
36. Contact details are a single dropdown picker with an Add button and a compact list, instead of one input row per channel. Values are whitelisted on the server and mirrored into the original meta keys, so the permission payload, admin readout and audit log are unchanged.

v1.5.2
37. All three account-drawer forms expose the neutral jobsapk/auth_form_guard action. The standalone CVJOBBOX Slide Verify plugin renders its human check into the HTML on the server, so a page cache, async script order or DOM rewrite cannot make the slider disappear. JavaScript injection remains a fallback; the performance plugin whitelists these first-party security assets.

v1.5.3
38. The home page is a job board again. The permission model, the two server-side gates and the unit map moved to a dedicated explainer page: page-how-it-works.php renders the how-it-works unit, and the front page keeps exactly one strip that links to it. Membership level cards stay on the home page; no long architecture text does.
39. how-it-works is an ordinary optional unit (the 17th folder, switchable in CVJOBBOX > Modules). It owns no data and no permission logic - it lays out the privacy unit's existing model, the two gates and the live unit map, and reads every number from the registry. The howitworks.url contract fails closed to an empty string.
40. The explainer page is created as a real page by the Company Pages plugin (slug how-it-works). Without that plugin the template still renders the model; footer and menu links fall back to /how-it-works/.

v1.5.4
41. Anonymous visitors were shown the signed-in account panel. wp_localize_script casts every scalar to a string, so a guest arrived as isLoggedIn:"0" - and "0" is truthy in JavaScript. app.js therefore hid the Job Seeker / Employer tabs and the three visitor forms (including the human check) and replaced the header "Sign in" caption with "My account". The theme now prints window.JOBSAPK with wp_json_encode, and app.js only accepts an explicit on-value.
42. The signed-in panel names the actual account type with a coloured role chip (Job seeker / Employer / Employer - pending / Administrator) and shows only that account type's tools: candidates get applications, saved jobs and the private resume, employers get post-a-job and membership, administrators get the review queue. Account type stays fixed at registration and is not switchable from the drawer.
*/

/* ---------- v1.5.1: account identity + focused-section navigation ---------- */
#account-type { scroll-margin-top: 92px; }
.cvjb-account-type { margin-bottom: 20px; }
.cvjb-type-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.cvjb-type-eyebrow { display: block; font-size: 11px; letter-spacing: .6px; text-transform: uppercase; }
.cvjb-account-type h2 { margin: 4px 0 2px; font-size: 22px; }
.cvjb-account-type p.muted { margin: 0; font-size: 13px; }
.cvjb-account-type h3 { font-size: 15px; margin: 18px 0 10px; }
.cvjb-account-type code { background: var(--bg); padding: 2px 6px; border-radius: 5px; font-size: 12px; }
.cvjb-view-banner { margin-top: 16px; padding: 12px 14px; border-radius: 10px; background: var(--brand-soft); color: var(--ink-2); font-size: 13px; line-height: 1.6; }
.cvjb-view-banner a { color: var(--brand); font-weight: 600; }
.cvjb-seeker-details { margin-top: 14px; border-top: 1px solid var(--line); padding-top: 12px; }
.cvjb-seeker-details summary { cursor: pointer; font-weight: 600; font-size: 13.5px; color: var(--ink-2); }
.cvjb-seeker-details ul { margin-top: 10px; }
.cvjb-seeker-details p { font-size: 12.5px; }
.cvjb-type-links { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 16px; }
.cvjb-type-links .chip { text-decoration: none; display: inline-block; }
.cvjb-section-nav { display: flex; gap: 8px 14px; flex-wrap: wrap; align-items: center; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 14px 16px; margin-bottom: 18px; font-size: 13px; }
.cvjb-section-nav a { color: var(--brand); font-weight: 600; text-decoration: none; }
.cvjb-section-nav a:hover { text-decoration: underline; }
.cvjb-section-role { color: var(--muted); margin-right: auto; }
.cvjb-section-role b { color: var(--ink); }

/* ---------- v1.5.1: contact method dropdown picker ---------- */
.cvjb-contact-picker { border: 1px solid var(--line); border-radius: 12px; padding: 16px; background: var(--bg); margin-bottom: 18px; }
.cvjb-picker-row { display: grid; grid-template-columns: minmax(150px, 1fr) minmax(180px, 1.4fr) auto; gap: 12px; align-items: end; }
.cvjb-picker-row .form-field { margin-bottom: 0; }
.cvjb-picker-add { height: 46px; white-space: nowrap; }
.cvjb-picker-hint { margin: 12px 0 0; text-align: left; }
.cvjb-contact-list { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 8px; }
.cvjb-contact-item { display: flex; align-items: center; gap: 12px; background: var(--surface); border: 1px solid var(--line); border-radius: 9px; padding: 9px 12px; font-size: 13.5px; }
.cvjb-contact-label { font-weight: 700; color: var(--ink-2); min-width: 110px; }
.cvjb-contact-value { flex: 1; color: var(--ink); word-break: break-all; }
.cvjb-contact-remove { border: 0; background: transparent; color: var(--muted); font-size: 19px; line-height: 1; cursor: pointer; padding: 0 4px; }
.cvjb-contact-remove:hover { color: var(--brand); }
.cvjb-contact-empty { margin: 12px 0 0; font-size: 12.5px; }

/* ---------- v1.5.1: sign-in drawer account type ---------- */
.drawer-account-type { margin: 22px 26px 0; }
.drawer-type-label { display: block; font-size: 11px; text-transform: uppercase; letter-spacing: .6px; color: var(--muted); margin-bottom: 8px; }
.drawer-account-type .role-tabs { margin: 0; }
.drawer-type-hint { margin: 9px 2px 0; font-size: 12px; color: var(--muted); line-height: 1.5; }
.reg-type-banner { background: var(--brand-soft); color: var(--brand-deep); border-radius: 9px; padding: 10px 12px; font-size: 12.5px; margin-bottom: 16px; }
.user-perms { margin: 12px 0 0; padding-left: 18px; font-size: 12px; color: var(--muted); line-height: 1.6; text-align: left; }

/* ---------- v1.9.1: WeChat QR codes under the sign-in / sign-up forms ---------- */
.drawer-qr { display: flex; gap: 18px; justify-content: center; margin-top: 22px; padding-top: 16px; border-top: 1px dashed var(--line); }
.drawer-qr figure { margin: 0; text-align: center; }
.drawer-qr img { width: 96px; height: 96px; display: block; margin: 0 auto 6px; border: 1px solid var(--line); border-radius: 10px; background: #fff; }
.drawer-qr figcaption { font-size: 11.5px; color: var(--muted); }

@media (max-width: 760px) {
  .cvjb-picker-row { grid-template-columns: 1fr; }
  .cvjb-picker-add { width: 100%; }
}

/* ---------- v1.5.2: server-rendered human check inside the account drawer ---------- */
/* The theme only exposes jobsapk/auth_form_guard; the standalone slide-verify
   plugin decides what to render. These rules keep its track full width and
   visible even when the drawer is narrow or a form is switched by JS. */
.auth-drawer .cvjbsv-wrap { display: block; width: 100%; margin: 16px 0 10px; }
.auth-drawer .cvjbsv-slider { min-width: 0; width: 100%; max-width: none; }
.auth-drawer .cvjbsv-label { color: var(--muted); }
.auth-drawer .cvjbsv-hp { position: absolute; left: -9999px; width: 1px; height: 1px; }

/* ---------- v1.5.3: the explainer page + the one home page pointer to it ---------- */
/* The permission model, the two access gates and the unit map moved off the
   home page onto /how-it-works/. The front page keeps a single strip that
   links to it, so it stays a job board. */
.hiw-head { padding-bottom: 26px; }
.hiw-kicker { display: inline-block; font-size: 11px; letter-spacing: .8px; text-transform: uppercase; font-weight: 700; color: var(--brand); margin-bottom: 6px; }
.hiw-head h1 { font-size: 34px; line-height: 1.2; margin: 0 0 8px; letter-spacing: -.6px; }
.hiw-jump { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 18px; }
.hiw-jump a { border: 1px solid var(--line); border-radius: 999px; padding: 7px 14px; font-size: 13px; color: var(--ink-2); background: var(--surface); text-decoration: none; }
.hiw-jump a:hover { border-color: var(--brand); color: var(--brand); }
.hiw-lead { max-width: 760px; }
.gate-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; }
.gate-grid .side-card { margin-bottom: 0; }
.gate-grid .side-card h3 { margin: 14px 0 12px; font-size: 17px; }
.resume-note .hiw-stats { display: flex; flex-wrap: wrap; gap: 6px 18px; margin-top: 12px; font-size: 12.5px; }
.hiw-stats b { color: var(--ink); }
.mod-card[data-locked="0"] { cursor: default; }

@media (max-width: 900px) {
  .gate-grid { grid-template-columns: 1fr; }
}
@media (max-width: 760px) {
  .hiw-head h1 { font-size: 26px; }
}

/* ---------------- Company home pages (v1.7.0) ----------------
   One public page per employer plus the employer editor and the directory.
   The visual hierarchy mirrors a single job card: square logo tile, one
   headline, a short meta line and one primary action. */
.company-logo img,
.company-hero-logo img,
.company-logo-preview img,
.company-card-logo img { width: 100%; height: 100%; object-fit: cover; border-radius: inherit; display: block; }
.job-company a { color: var(--ink-2); font-weight: 600; }
.job-company a:hover { color: var(--brand); }

.company-preview-bar { background: #fff7e0; border-bottom: 1px solid #f0dfae; color: #6b5400; font-size: 13px; padding: 10px 0; }
.company-head { padding-bottom: 8px; }
.company-hero {
  display: grid; grid-template-columns: 96px 1fr auto; gap: 24px; align-items: center;
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  padding: 28px; box-shadow: var(--shadow);
}
.company-hero-logo {
  width: 96px; height: 96px; border-radius: 22px; display: grid; place-items: center;
  background: var(--brand-soft); color: var(--brand); font-size: 34px; font-weight: 800; overflow: hidden;
}
.company-hero-body h1 { margin: 8px 0 6px; font-size: 30px; line-height: 1.2; }
.company-meta { margin: 0; color: var(--muted); font-size: 14px; }
.company-flags { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.chip-ghost { background: var(--bg); border-color: transparent; color: var(--ink-2); font-size: 12px; padding: 4px 10px; border-radius: 6px; }
.company-hero-actions { display: flex; gap: 10px; flex-wrap: wrap; justify-content: flex-end; }
.company-about h2 { margin: 0 0 14px; font-size: 22px; }
.company-about .prose { color: var(--ink-2); font-size: 15px; line-height: 1.75; }

.company-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 14px; }
.company-card {
  display: grid; grid-template-columns: 52px 1fr auto; gap: 14px; align-items: center;
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  padding: 18px; transition: .2s ease;
}
.company-card:hover { border-color: var(--brand); box-shadow: var(--shadow); transform: translateY(-2px); }
.company-card-logo {
  width: 52px; height: 52px; border-radius: 13px; display: grid; place-items: center;
  background: var(--brand-soft); color: var(--brand); font-weight: 800; overflow: hidden;
}
.company-card-body { display: grid; gap: 4px; min-width: 0; }
.company-card-body b { font-size: 15px; color: var(--ink); }
.company-card-body .muted { font-size: 12.5px; }
.company-card-count { text-align: right; }
.company-card-count b { display: block; font-size: 18px; color: var(--accent); }
.company-card-count span { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }

/* employer editor */
.company-editor-head { display: flex; gap: 14px; align-items: flex-start; justify-content: space-between; margin-bottom: 14px; }
.company-note { background: var(--bg); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 12px 14px; font-size: 13.5px; color: var(--ink-2); margin-bottom: 18px; }
.company-note.ok { background: #eafaf5; border-color: #bfe8dc; color: #075a50; }
.company-note.blocked { background: #fff2f0; border-color: #f6cfc8; color: #8a2b1c; }
.company-note a { font-weight: 600; }
.company-logo-row { display: flex; gap: 16px; align-items: center; margin-bottom: 20px; }
.company-logo-preview {
  width: 76px; height: 76px; border-radius: 18px; display: grid; place-items: center;
  background: var(--brand-soft); color: var(--brand); font-size: 26px; font-weight: 800; overflow: hidden; flex-shrink: 0;
}
.file-btn {
  display: inline-block; border: 1px solid var(--line); border-radius: 10px; padding: 9px 16px;
  font-size: 13.5px; font-weight: 600; color: var(--ink-2); cursor: pointer; background: #fff;
}
.file-btn:hover { border-color: var(--brand); color: var(--brand); background: var(--brand-soft); }
.form-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 16px; }
.company-form-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 6px; }
.company-summary-main { display: flex; gap: 14px; align-items: flex-start; justify-content: space-between; flex-wrap: wrap; }
.company-summary-jobs { margin-top: 14px; display: grid; gap: 8px; }

@media (max-width: 900px) {
  .company-hero { grid-template-columns: 76px 1fr; }
  .company-hero-logo { width: 76px; height: 76px; font-size: 26px; border-radius: 18px; }
  .company-hero-actions { grid-column: 1 / -1; justify-content: flex-start; }
  .company-hero-body h1 { font-size: 24px; }
}
@media (max-width: 620px) {
  .form-grid-2 { grid-template-columns: 1fr; }
  .company-grid { grid-template-columns: 1fr; }
}

/* ---------------- Job form pickers (v1.9.0) ----------------
   Category / city / type / country are chosen from the vocabulary the board
   already uses, with "add a new one" as the last option. The form is shared by
   the front end and mirrored in wp-admin, so these rules stay generic. */
.input-wrap textarea {
  width: 100%; min-height: 132px; padding: 12px 14px; border: 1px solid var(--line);
  border-radius: 10px; outline: 0; background: #fff; color: var(--ink);
  font: inherit; line-height: 1.65; resize: vertical; transition: .18s;
}
.input-wrap textarea:focus { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-soft); }
.form-hint { font-size: 12px; color: var(--muted); margin: 6px 0 0; line-height: 1.6; }
#post-job form .form-field:last-of-type { margin-bottom: 20px; }
#post-job .btn-block, #post-job [type="submit"] { width: 100%; }

/* ---------------- v1.9.1: small phones ----------------
   The drawer and the job-form picker collapse one column further on very
   narrow screens so no field is wider than the panel that holds it. */
@media (max-width: 480px) {
  .drawer-body { padding: 20px 18px 28px; }
  .drawer-account-type { margin-left: 18px; margin-right: 18px; }
  .cvjb-picker-row { grid-template-columns: 1fr; }
  .cvjb-picker-add { width: 100%; }
  .drawer-qr { gap: 14px; }
}

/* ---------------- v1.9.2: sign out on the account page ----------------
   The drawer already had a sign-out button; the account page did not, which
   is where most members look first. Both the header row and the section nav
   now carry one, and the membership panel is employer-only. */
.cvjb-head-actions { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.cvjb-head-actions .cvjb-signout { color: var(--muted); }
.cvjb-head-actions .cvjb-signout:hover { color: var(--brand); }
.cvjb-section-nav .cvjb-nav-signout { margin-left: auto; color: var(--muted); }
.cvjb-section-nav .cvjb-nav-signout:hover { color: var(--brand); }
@media (max-width: 560px) {
  .cvjb-head-actions { gap: 12px; }
  .cvjb-section-nav .cvjb-nav-signout { margin-left: 0; }
}

/* ---------------- v1.9.3 / v1.9.4: employer workbench ----------------
   The vacancy board answers four questions in one row: what the job is, is it
   live, how many applications arrived, and where to edit it. On phones the row
   stacks instead of scrolling sideways, and the header labels disappear
   because the badge and the links already say what they are. */
.cvjb-stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(108px, 1fr)); gap: 10px; margin: 18px 0 4px; }
.cvjb-stat { display: flex; flex-direction: column; gap: 2px; background: var(--bg); border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px; }
.cvjb-stat b { font-size: 22px; line-height: 1.1; color: var(--ink); }
.cvjb-stat span { font-size: 11px; letter-spacing: .4px; text-transform: uppercase; color: var(--muted); }
.cvjb-stat-new b { color: var(--brand); }

.cvjb-job-table { margin-top: 14px; }
.cvjb-job-head { display: grid; grid-template-columns: minmax(0, 1fr) 110px 150px 190px; gap: 12px; padding: 6px 0; border-bottom: 1px solid var(--line); font-size: 10.5px; letter-spacing: .5px; text-transform: uppercase; color: var(--muted); }
.cvjb-job-row { display: grid; grid-template-columns: minmax(0, 1fr) 110px 150px 190px; gap: 12px; align-items: center; padding: 12px 0; border-bottom: 1px solid var(--line); }
.cvjb-job-row:last-of-type { border-bottom: 0; }
.cvjb-job-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cvjb-job-main a, .cvjb-job-name { font-weight: 600; color: var(--ink); text-decoration: none; overflow-wrap: anywhere; }
.cvjb-job-main a:hover { color: var(--brand); }
.cvjb-job-main .muted { font-size: 11.5px; }
.cvjb-job-apps { font-size: 13px; color: var(--ink-2); text-decoration: none; }
.cvjb-job-apps:hover { color: var(--brand); }
.cvjb-job-new { display: inline-block; margin-left: 6px; padding: 1px 7px; border-radius: 20px; background: var(--brand-soft); color: var(--brand); font-size: 11px; }
.cvjb-job-actions { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.cvjb-job-actions .chip { flex-shrink: 0; text-decoration: none; }

.cvjb-app-filter { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 16px; }
.cvjb-app-filter .chip { text-decoration: none; }
.cvjb-app-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.cvjb-app-name { font-weight: 700; }
.cvjb-app-meta { font-size: 12.5px; }
.cvjb-app-meta a { color: var(--ink-2); }
.cvjb-app-tools { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 12px; }
.cvjb-app-status { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); }
.cvjb-app-status select { font: inherit; font-size: 12.5px; color: var(--ink); background: #fff; border: 1px solid var(--line); border-radius: 8px; padding: 5px 8px; }
.cvjb-badge-row { display: inline-flex; gap: 6px; flex-wrap: wrap; }

.cvjb-plan-ask { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line); }
.cvjb-plan-ask h4 { margin: 0 0 10px; font-size: 11px; letter-spacing: .6px; text-transform: uppercase; color: var(--muted); }
.cvjb-plan-pending { display: flex; flex-direction: column; gap: 4px; margin-bottom: 10px; padding: 10px 12px; border-radius: 10px; background: var(--brand-soft); font-size: 12.5px; }
.cvjb-plan-pending b { color: var(--brand-deep); }
.cvjb-plan-field { display: flex; flex-direction: column; gap: 5px; font-size: 12px; color: var(--muted); }
.cvjb-plan-field select, .cvjb-plan-field textarea { width: 100%; font: inherit; font-size: 13px; color: var(--ink); background: #fff; border: 1px solid var(--line); border-radius: 9px; padding: 8px 10px; }
.cvjb-plan-field textarea { resize: vertical; min-height: 66px; }
.cvjb-plan-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 10px; }
.cvjb-plan-row .btn { margin-top: 0; }

@media (max-width: 900px) {
  .cvjb-job-head { display: none; }
  .cvjb-job-row { grid-template-columns: minmax(0, 1fr) auto; row-gap: 8px; }
  .cvjb-job-main { grid-column: 1 / -1; }
  .cvjb-job-actions { grid-column: 1 / -1; justify-content: flex-start; }
}
@media (max-width: 540px) {
  .cvjb-stat { padding: 10px 12px; }
  .cvjb-stat b { font-size: 19px; }
}

/* ---------------- v2.0.0: job discovery ----------------
   The archive is now a real search surface: one bar, facet lists with
   counts, removable chips, a sort row and a result count. Everything is a
   link or a GET form, so it works without JavaScript and every filtered
   view has its own URL. */
.cvjb-searchbar {
  display: grid; grid-template-columns: minmax(0, 1fr) repeat(3, minmax(0, 170px)) auto;
  gap: 8px; align-items: end; background: #fff; border: 1px solid var(--line);
  border-radius: 14px; padding: 12px; margin-bottom: 18px; box-shadow: var(--shadow);
}
.cvjb-searchbar-key { display: flex; align-items: center; gap: 9px; padding: 0 10px; border: 1px solid var(--line); border-radius: 10px; height: 46px; }
.cvjb-searchbar-key svg { flex-shrink: 0; color: var(--muted); }
.cvjb-searchbar-key input { border: 0; outline: 0; background: transparent; width: 100%; height: 44px; font: inherit; font-size: 14.5px; color: var(--ink); }
.cvjb-searchbar-cell { display: flex; flex-direction: column; gap: 4px; }
.cvjb-searchbar-label { font-size: 10.5px; letter-spacing: .5px; text-transform: uppercase; color: var(--muted); padding-left: 2px; }
.cvjb-searchbar-cell select {
  width: 100%; height: 46px; font: inherit; font-size: 13.5px; color: var(--ink);
  background: #fff; border: 1px solid var(--line); border-radius: 10px; padding: 0 10px; cursor: pointer;
}
.cvjb-searchbar .btn { height: 46px; }

.cvjb-active-filters { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin: 0 0 20px; }
.cvjb-active-label { font-size: 11.5px; letter-spacing: .5px; text-transform: uppercase; color: var(--muted); }
.cvjb-filter-chip {
  display: inline-flex; align-items: center; gap: 7px; padding: 5px 10px; border-radius: 20px;
  background: var(--brand-soft); color: var(--brand-deep); font-size: 12.5px; text-decoration: none;
}
.cvjb-filter-chip span { font-size: 15px; line-height: 1; opacity: .55; }
.cvjb-filter-chip:hover span { opacity: 1; }
.cvjb-clear-all { font-size: 12.5px; color: var(--muted); text-decoration: underline; }

.cvjb-results-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  flex-wrap: wrap; padding: 0 2px 10px; border-bottom: 1px solid var(--line); font-size: 13px; color: var(--ink-2);
}
.cvjb-results-bar b { color: var(--ink); }
.cvjb-sort { display: inline-flex; align-items: center; gap: 12px; }
.cvjb-sort .muted { font-size: 11px; letter-spacing: .5px; text-transform: uppercase; }
.cvjb-sort a { color: var(--ink-2); text-decoration: none; }
.cvjb-sort a:hover { color: var(--brand); }
.cvjb-sort a.active { color: var(--brand); font-weight: 700; }

.cvjb-facet-list { display: flex; flex-direction: column; }
.cvjb-facet-list a {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 7px 0; border-bottom: 1px solid var(--line); font-size: 13.5px;
  color: var(--ink-2); text-decoration: none;
}
.cvjb-facet-list a:last-child { border-bottom: 0; }
.cvjb-facet-list a:hover { color: var(--brand); }
.cvjb-facet-list a.active { color: var(--brand); font-weight: 700; }
.cvjb-facet-list i { font-style: normal; font-size: 11.5px; color: var(--muted); }

@media (max-width: 900px) {
  .cvjb-searchbar { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .cvjb-searchbar-key { grid-column: 1 / -1; }
  .cvjb-searchbar .btn { grid-column: 1 / -1; }
}
@media (max-width: 520px) {
  .cvjb-searchbar { grid-template-columns: 1fr; }
}

/* A close / reopen control is a button, not a link: it changes state, so it
   must not look like navigation and must not be crawlable. */
.cvjb-job-state { cursor: pointer; font: inherit; }
.cvjb-job-state[data-job-state="closed"]:hover { border-color: #b4483f; color: #b4483f; background: #fdf2f1; }
.cvjb-job-state[data-job-state="open"]:hover { border-color: var(--brand); color: var(--brand); background: var(--brand-soft); }

/* ---------------- v2.0.0: job alerts (unit 20) ----------------
   The card keeps the same visual weight as the other sidebar cards: a
   heading, one sentence of explanation and one primary action. A saved
   alert is a row, not a table: the filter name is the link, the delivery
   rhythm is secondary, and the two controls (frequency, remove) sit on
   the right so the row still reads as a sentence on a phone. */
.cvjb-alert-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.cvjb-alert-head h3 { margin: 0; }
.cvjb-alert-note { margin: 12px 0 0; padding: 9px 12px; border-radius: 10px; font-size: 12.5px; }
.cvjb-alert-note.is-ok { background: var(--brand-soft); color: var(--brand-deep); }
.cvjb-alert-note.is-error { background: #fdf2f1; color: #b4483f; }
.cvjb-alert-form { display: flex; flex-direction: column; gap: 10px; margin-top: 12px; }
.cvjb-alert-freq { display: flex; align-items: center; justify-content: space-between; gap: 10px; font-size: 12.5px; color: var(--muted); }
.cvjb-alert-freq select { height: 36px; font: inherit; font-size: 13px; color: var(--ink); background: #fff; border: 1px solid var(--line); border-radius: 9px; padding: 0 8px; }
.cvjb-alert-fine { margin: 10px 0 0; font-size: 11.5px; color: var(--muted); }
.cvjb-alert-fine a { color: var(--brand); text-decoration: none; }
.cvjb-alert-current { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 12px 0 0; font-size: 13px; color: var(--ink-2); }
.cvjb-alert-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 12px; }
.cvjb-alert-actions form { margin: 0; }

.cvjb-alert-list { display: flex; flex-direction: column; margin-top: 12px; }
.cvjb-alert-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 11px 0; border-bottom: 1px solid var(--line);
}
.cvjb-alert-row:last-child { border-bottom: 0; }
.cvjb-alert-row-main { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.cvjb-alert-row-main a { font-weight: 600; color: var(--ink); text-decoration: none; overflow-wrap: anywhere; }
.cvjb-alert-row-main a:hover { color: var(--brand); }
.cvjb-alert-meta { font-size: 11.5px; color: var(--muted); }
.cvjb-alert-row-actions { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.cvjb-alert-inline { display: flex; align-items: center; gap: 6px; margin: 0; }
.cvjb-alert-inline select { height: 30px; font: inherit; font-size: 12px; color: var(--ink); background: #fff; border: 1px solid var(--line); border-radius: 8px; padding: 0 6px; }
.cvjb-alert-remove { cursor: pointer; font: inherit; background: #fff; }
.cvjb-alert-remove:hover { border-color: #b4483f; color: #b4483f; background: #fdf2f1; }
.cvjb-alert-empty { margin-top: 12px; }
.cvjb-alert-empty b { display: block; margin-bottom: 4px; }
.cvjb-alert-empty .btn { margin-top: 10px; }
.cvjb-alert-foot { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line); display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.cvjb-alert-foot .muted { margin: 0; font-size: 11.5px; max-width: 46ch; }
.cvjb-alert-foot form { margin: 0; }

@media (max-width: 700px) {
  .cvjb-alert-row { flex-direction: column; align-items: flex-start; gap: 8px; }
  .cvjb-alert-row-actions { justify-content: flex-start; }
  .cvjb-alert-foot { flex-direction: column; }
}

/* WordPress prints this class in themes that do not include core's helper. */
.screen-reader-text {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
