/* =============================================================
   GMFJ PWA — Career DNA + journey components
   Stepper, score visualisation, match badge, vacancy card,
   archetype card, coach chat. All brand-token driven.
   ============================================================= */

/* ---------------------------------------------------------------
   Career DNA — stepper / progress
   --------------------------------------------------------------- */
.stepper { display: flex; gap: 0.4rem; margin-bottom: var(--space-5); }
.stepper .step { flex: 1; height: 6px; border-radius: var(--radius-pill); background: var(--soft-blue-200); }
.stepper .step.done { background: var(--brand-gradient); }
.stepper .step.current { background: var(--deep-pink-200); }

.step-count { font-size: var(--fnt-small); font-weight: 700; color: var(--text-muted); margin-bottom: var(--space-2); }

/* multi-select chip grid + single-select cards */
.select-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-3); }
.select-card {
  border: 1.5px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface);
  padding: var(--space-4);
  display: flex; align-items: center; gap: var(--space-3);
  text-align: left; color: var(--text-strong); font-weight: 700;
  transition: border-color 0.12s ease, background 0.12s ease, transform 0.08s ease;
}
.select-card:active { transform: scale(0.98); }
.select-card .material-icons { font-size: 1.5rem; color: var(--indigo-300); }
.select-card.is-selected { border-color: var(--deep-pink-200); background: var(--light-blue-100); box-shadow: var(--shadow-sm); }
.select-card.is-selected .material-icons { color: var(--deep-pink-200); }
.select-list { display: grid; gap: var(--space-3); }
.select-list .select-card { width: 100%; }

/* ---------------------------------------------------------------
   Career DNA — score visualisation
   --------------------------------------------------------------- */

/* Big radial headline (conic-gradient ring) */
.dna-radial {
  --val: 0;
  --ring: var(--deep-pink-200);
  width: 168px; height: 168px;
  border-radius: 50%;
  margin: 0 auto var(--space-4);
  display: grid; place-items: center;
  background:
    radial-gradient(closest-side, var(--surface) 78%, transparent 79% 100%),
    conic-gradient(var(--ring) calc(var(--val) * 1%), var(--soft-blue-200) 0);
}
.dna-radial .val { font-family: var(--font-display); font-weight: var(--font-display-weight); font-size: 2.6rem; line-height: 1; color: var(--text-strong); }
.dna-radial .lbl { font-size: var(--fnt-small); font-weight: 700; color: var(--text-muted); }

/* Dimension bars */
.dim-list { display: grid; gap: var(--space-3); }
.dim {  }
.dim .dim-top { display: flex; justify-content: space-between; font-weight: 700; font-size: var(--fnt-small); margin-bottom: 0.3rem; }
.dim .dim-top .v { color: var(--text-muted); }
.dim .track { height: 10px; background: var(--soft-blue-200); border-radius: var(--radius-pill); overflow: hidden; }
.dim .fill { height: 100%; border-radius: var(--radius-pill); background: var(--brand-gradient); width: 0; transition: width 0.7s cubic-bezier(.2,.8,.2,1); }
/* per-dimension hue accents (non-colour-only: value always shown as text too) */
.dim.interest    .fill { background: linear-gradient(90deg, var(--pink-100), var(--deep-pink-200)); }
.dim.skill       .fill { background: linear-gradient(90deg, var(--coral-100), var(--red-200)); }
.dim.personality .fill { background: linear-gradient(90deg, var(--purple-300), var(--dark-purple-400)); }
.dim.ambition    .fill { background: linear-gradient(90deg, var(--amber-300), var(--tangerine-400)); }
.dim.opportunity .fill { background: linear-gradient(90deg, var(--aqua-300), var(--indigo-300)); }
.dim.progression .fill { background: linear-gradient(90deg, var(--mint-100), var(--teal-200)); }

/* Sector affinity list */
.sector { display: flex; align-items: center; gap: var(--space-3); margin-bottom: var(--space-2); }
.sector .name { width: 38%; font-weight: 700; font-size: var(--fnt-small); }
.sector .track { flex: 1; height: 8px; background: var(--soft-blue-200); border-radius: var(--radius-pill); overflow: hidden; }
.sector .fill { display: block; width: 0; height: 100%; background: var(--brand-gradient); border-radius: var(--radius-pill); transition: width 0.7s cubic-bezier(.2,.8,.2,1); }
.sector .v { width: 3rem; text-align: right; font-weight: 700; font-size: var(--fnt-small); color: var(--text-muted); }

/* ---------------------------------------------------------------
   Archetype card
   --------------------------------------------------------------- */
.archetype {
  background: var(--brand-gradient);
  color: #fff; border-radius: var(--radius-xl);
  padding: var(--space-5); text-align: center;
  position: relative; overflow: hidden;
  box-shadow: var(--shadow-md);
}
.archetype::after { content: ""; position: absolute; width: 200px; height: 200px; left: -50px; bottom: -80px; background: radial-gradient(circle, rgba(255,255,255,0.18), transparent 70%); }
.archetype .glyph { font-size: 3rem; }
/* Persona icon rendered as an image (SVG/PNG URL) rather than an emoji. */
.glyph-img { width: 64px; height: 64px; object-fit: contain; display: inline-block; }
.archetype .glyph-img { width: 88px; height: 88px; }
.coach-dna-glyph .glyph-img { width: 100%; height: 100%; }
.avatar .glyph-img { width: 78%; height: 78%; }
.archetype h2 { color: #fff; margin: var(--space-2) 0 0.25rem; font-size: 1.9rem; }
.archetype .tag { color: rgba(255,255,255,0.92); font-weight: 700; font-size: var(--fnt-small); }
.archetype p { color: rgba(255,255,255,0.92); margin: var(--space-3) 0 0; }

/* ---------------------------------------------------------------
   Match badge + reasons (the Career DNA "spine")
   --------------------------------------------------------------- */
.match-badge {
  display: inline-flex; align-items: center; gap: 0.35rem;
  padding: 0.25rem 0.6rem;
  border-radius: var(--radius-pill);
  font-weight: 700; font-size: 0.78rem;
  background: var(--soft-blue-200); color: var(--indigo-300);
}
.match-badge .material-icons { font-size: 0.95rem; }
.match-badge.high  { background: #d7f0e2; color: #1f7a4d; }
.match-badge.mid   { background: #fdeccb; color: #9a6a12; }
.match-badge.low   { background: var(--surface-alt); color: var(--text-muted); }

.match-ring {
  --val: 0; --ring: var(--teal-200);
  width: 64px; height: 64px; border-radius: 50%;
  display: grid; place-items: center; flex: none;
  background:
    radial-gradient(closest-side, var(--surface) 74%, transparent 75% 100%),
    conic-gradient(var(--ring) calc(var(--val) * 1%), var(--soft-blue-200) 0);
}
.match-ring .v { font-family: var(--font-display); font-weight: var(--font-display-weight); font-size: 1.05rem; color: var(--text-strong); }

.reasons { display: grid; gap: var(--space-2); }
.reasons li { display: flex; gap: var(--space-2); align-items: flex-start; font-size: var(--fnt-small); }
.reasons .material-icons { font-size: 1.05rem; color: var(--teal-200); flex: none; }

/* ---------------------------------------------------------------
   Vacancy card
   --------------------------------------------------------------- */
.vac-card { display: grid; gap: var(--space-3); }
.vac-card .vac-head { display: flex; gap: var(--space-3); align-items: flex-start; }
.vac-logo { width: 44px; height: 44px; border-radius: var(--radius); background: var(--surface-alt); display: grid; place-items: center; font-family: var(--font-display); font-weight: var(--font-display-weight); font-size: 1.1rem; color: var(--indigo-300); flex: none; overflow: hidden; position: relative; }
/* Real branding logo overlaid on the initials avatar (employer/provider). object-fit:contain on a
   white ground keeps logos undistorted; border-radius:inherit clips to the avatar's rounded corners. */
.vac-logo, .partner-logo, .partner-hero-logo { position: relative; }
.logo-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; background: #fff; border-radius: inherit; }
.vac-card .vac-title { font-family: var(--font-display); font-weight: var(--font-display-weight); font-size: 1.05rem; color: var(--text-strong); margin: 0; }
.vac-card .vac-emp { color: var(--text-muted); font-size: var(--fnt-small); font-weight: 700; }
.vac-card .save { margin-left: auto; }
.vac-foot { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }

/* ---------------------------------------------------------------
   Opportunity detail hero
   --------------------------------------------------------------- */
.opp-hero { position: relative; border-radius: var(--radius-lg); overflow: hidden; aspect-ratio: 16/9; background: var(--brand-gradient); display: grid; place-items: center; }
.opp-hero img { width: 100%; height: 100%; object-fit: cover; }
.opp-hero .play { position: absolute; width: 3.5rem; height: 3.5rem; border-radius: 50%; background: rgba(255,255,255,0.92); display: grid; place-items: center; box-shadow: var(--shadow-md); }
.opp-hero .play .material-icons { font-size: 2rem; color: var(--deep-pink-200); }

.kv { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-3); }
.kv .item { background: var(--surface-alt); border-radius: var(--radius); padding: var(--space-3); }
.kv .item .k { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); font-weight: 700; }
.kv .item .v { font-weight: 700; color: var(--text-strong); }

/* sticky apply bar inside opportunity — opaque band so the description text scrolling
   underneath never bleeds through behind the Apply button.
   bottom is negative, not 0: .app-main reserves padding-bottom of (bottomnav-h + space-5) so
   ordinary scrolled content clears the bottom nav, but that same padding is what a sticky
   offset resolves against — leaving an unwanted space-5 gap above the nav unless cancelled here. */
.apply-bar { position: sticky; bottom: calc(-1 * var(--space-5)); z-index: 20; background: var(--surface); border-top: 1px solid var(--line); box-shadow: 0 -8px 20px -6px rgba(0,0,0,0.35); backdrop-filter: blur(6px); padding: var(--space-3) var(--space-4); display: flex; gap: var(--space-3); align-items: center; margin: var(--space-5) calc(-1 * var(--space-4)) calc(-1 * var(--space-5)); }

/* ---------------------------------------------------------------
   Timeline (application tracker)
   --------------------------------------------------------------- */
.timeline { position: relative; padding-left: 1.6rem; }
.timeline::before { content: ""; position: absolute; left: 0.45rem; top: 0.3rem; bottom: 0.3rem; width: 2px; background: var(--soft-blue-200); }
.timeline li { position: relative; padding-bottom: var(--space-4); }
.timeline li::before { content: ""; position: absolute; left: -1.6rem; top: 0.15rem; width: 0.9rem; height: 0.9rem; border-radius: 50%; background: var(--surface); border: 2px solid var(--soft-blue-200); }
.timeline li.done::before { background: var(--teal-200); border-color: var(--teal-200); }
.timeline li.current::before { background: var(--deep-pink-200); border-color: var(--deep-pink-200); box-shadow: 0 0 0 4px rgba(198,11,136,0.18); }
.timeline .t-title { font-weight: 700; color: var(--text-strong); }
.timeline .t-time { font-size: var(--fnt-small); color: var(--text-muted); }

/* ---------------------------------------------------------------
   AI Career Coach chat
   --------------------------------------------------------------- */
.coach { display: flex; flex-direction: column; min-height: 100%; }
.chat-stream { display: flex; flex-direction: column; gap: var(--space-3); flex: 1; padding-bottom: var(--space-4); }
.bubble { max-width: 80%; padding: 0.7rem 0.95rem; border-radius: var(--radius-lg); font-size: 0.92rem; line-height: 1.4; }
.bubble.bot { align-self: flex-start; background: var(--surface-alt); color: var(--text-strong); border-bottom-left-radius: 0.25rem; }
.bubble.me { align-self: flex-end; background: var(--brand-gradient); color: #fff; border-bottom-right-radius: 0.25rem; }
/* Links in messages: inherit the bubble's text colour (white on "me", dark on "bot") so they read
   clearly on both, underlined to signal they're tappable. break long URLs so they don't overflow. */
.bubble .msg-link { color: inherit; text-decoration: underline; font-weight: 600; overflow-wrap: anywhere; }
/* Edit/delete affordance + markers on a message bubble. */
.bubble-foot { display: flex; align-items: center; justify-content: flex-end; gap: 6px; margin-top: 3px; }
.bubble-edited { font-size: 0.68rem; opacity: 0.7; }
.bubble-menu { background: transparent; border: 0; padding: 0; margin: 0; cursor: pointer; color: inherit; opacity: 0.65; line-height: 0; display: inline-flex; }
.bubble-menu .material-icons { font-size: 18px; }
.bubble-menu:hover { opacity: 1; }
.bubble-deleted { font-style: italic; opacity: 0.85; display: inline-flex; align-items: center; gap: 5px; }
.bubble-deleted .material-icons { font-size: 16px; }
.bubble.is-deleted { background: var(--surface-alt); color: var(--text-muted); }
.wgf-danger, .wgf-danger:hover { color: #c0392b !important; }
/* Photo messages: a tight frame around the image; a caption (if any) flows beneath it. */
.member-row { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-2) 0; border-bottom: 1px solid var(--line); }
.member-row:last-child { border-bottom: none; }
/* A member you can contact. It is a <button> wearing a row, so undo the control defaults the
   row does not set, and let the phone icon say why it is tappable at all. */
.member-row-tap { width: 100%; text-align: left; font: inherit; color: inherit; background: none; cursor: pointer; }
.member-row-tap .chev { color: var(--brand-accent); flex: none; }
.member-row-tap:hover .member-name { text-decoration: underline; }
.member-meta { flex: 1; min-width: 0; }
.member-name { font-weight: 700; font-size: 0.92rem; }
.member-rel { font-size: 0.78rem; color: var(--text-muted); }
.person-avatar.sm { width: 2rem; height: 2rem; font-size: 0.8rem; }
.bubble.has-img { padding: 0.3rem; }
.bubble.has-img .bubble-from { padding: 0.15rem 0.4rem 0.3rem; }
.bubble-img { display: block; max-width: min(240px, 68vw); max-height: 300px; border-radius: 12px; object-fit: cover; cursor: zoom-in; }
.img-lightbox { position: fixed; inset: 0; z-index: 3000; background: rgba(10, 6, 16, .9); display: flex; align-items: center; justify-content: center; padding: 16px; cursor: zoom-out; }
.img-lightbox img { max-width: 96vw; max-height: 92vh; border-radius: 12px; box-shadow: 0 20px 60px rgba(0, 0, 0, .5); }
.chat-suggest { display: flex; gap: var(--space-2); overflow-x: auto; padding: var(--space-2) 0; scrollbar-width: none; }
.chat-suggest::-webkit-scrollbar { display: none; }

/* Opportunity hero: location map background + provider/employer roundels */
.opp-hero-bg { position: absolute; inset: 0; background: linear-gradient(135deg, #232a44, #12151f); }
.opp-map { position: absolute; inset: 0; width: 100%; height: 100%; overflow: hidden; }
/* 1px larger than the 256px grid so adjacent tiles overlap slightly — kills hairline seams at any DPR.
   Scoped under .opp-hero (not a bare .osm-tile rule) so it beats .opp-hero img's specificity above —
   otherwise that rule's width/height:100% wins, stretching each tile to fill the whole hero and turning
   the map into overlapping, mismatched, zoomed-in tile fragments (misaligned lines, blank-looking bands). */
.opp-hero .osm-tile { position: absolute; width: 257px; height: 257px; max-width: none; }
.osm-pin { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -100%); z-index: 1; color: #e5484d; }
.osm-pin .material-icons { font-size: 2.1rem; filter: drop-shadow(0 1px 2px rgba(0,0,0,.45)); }
.osm-attr { position: absolute; right: 4px; bottom: 3px; z-index: 1; font-size: .62rem; color: rgba(255,255,255,.85); background: rgba(0,0,0,.35); padding: 1px 5px; border-radius: 4px; }
/* Dark-blue wash over the map (vertical — no diagonal seam), darker at the bottom for the caption. */
.opp-hero-tint { position: absolute; inset: 0; background: linear-gradient(to top, rgba(18,21,31,.92) 0%, rgba(26,36,66,.55) 60%, rgba(26,36,66,.4) 100%); }
.opp-hero-logos { position: absolute; top: .75rem; left: .75rem; display: flex; gap: .5rem; z-index: 1; }
.opp-roundel { width: 48px; height: 48px; border-radius: 50%; overflow: hidden; background: #fff; box-shadow: 0 2px 8px rgba(0,0,0,.28); flex: none; display: grid; place-items: center; }
/* Bookmark roundel, right side, same diameter as the logos. */
.opp-hero-save { position: absolute; top: .75rem; right: .75rem; z-index: 1; border: 0; cursor: pointer; padding: 0; }
.opp-hero-save .material-icons { color: var(--indigo-300); font-size: 1.5rem; }
.opp-roundel img { width: 100%; height: 100%; object-fit: contain; padding: 6px; display: block; }
/* Hero caption: the role title + location, over the map. */
.opp-hero-caption { position: absolute; left: 1rem; right: 1rem; bottom: .85rem; z-index: 1; }
.opp-hero-title { margin: 0 0 .2rem; color: #fff; font-family: var(--font-display); font-weight: var(--font-display-weight); font-size: 1.25rem; line-height: 1.2; text-shadow: 0 1px 5px rgba(0,0,0,.65); }
.opp-hero-loc { color: rgba(255,255,255,.92); font-size: .9rem; text-shadow: 0 1px 4px rgba(0,0,0,.65); }

/* Career DNA quiz */
.quiz-progress { flex: 1; height: 6px; border-radius: 999px; background: var(--surface-alt); overflow: hidden; }
.quiz-progress-fill { height: 100%; background: var(--brand-gradient); transition: width .3s ease; }
/* The question body is admin-authored HTML (built for a dark theme with white text) — force readable
   colours in the PWA and give its cards/utility classes sane fallbacks. */
.dna-q-body { margin-bottom: var(--space-4); }
.dna-q-body, .dna-q-body * { color: var(--text-strong) !important; }
.dna-q-body h1, .dna-q-body h2, .dna-q-body h3, .dna-q-body h4 { font-family: var(--font-display); font-weight: var(--font-display-weight); margin: 0 0 .5rem; }
.dna-q-body h2 { font-size: 1.4rem; }
.dna-q-body h4 { font-size: 1.1rem; }
.dna-q-body p { margin: 0 0 .5rem; }
.dna-q-body .text-center { text-align: center; }
/* Quiz question as a chat-style speech bubble: an avatar "asking" the statement, then a short instruction. */
.quiz-bubble-wrap { display: flex; align-items: flex-start; gap: .7rem; margin: 0 0 var(--space-3); }
.quiz-avatar { flex: 0 0 auto; width: 42px; height: 42px; border-radius: 50%; background: var(--brand-gradient); display: grid; place-items: center; box-shadow: 0 4px 12px rgba(0,0,0,.18); margin-top: 2px; }
.quiz-avatar .material-icons { color: #fff !important; font-size: 22px; }
.quiz-bubble { position: relative; background: var(--surface-alt); color: var(--text-strong) !important; border-radius: 6px 18px 18px 18px; padding: .9rem 1.05rem; font-family: var(--font-display); font-weight: var(--font-display-weight); font-size: 1.2rem; line-height: 1.4; max-width: 30ch; }
.quiz-bubble::before { content: ""; position: absolute; top: 15px; left: -7px; width: 0; height: 0; border: 7px solid transparent; border-right-color: var(--surface-alt); border-left: 0; }
.quiz-instruction { text-align: center; color: var(--text-muted) !important; font-size: .95rem; margin: 0 0 var(--space-3); }
/* Legacy: the old centred quote (kept so any cached view still renders sanely). */
.quiz-quote { text-align: center; font-family: var(--font-display); font-weight: var(--font-display-weight); font-size: 1.35rem; line-height: 1.4; color: var(--text-strong) !important; margin: 0 auto var(--space-2); max-width: 32ch; }
.dna-q-body .white-box { background: var(--surface-alt); border-radius: var(--radius); padding: var(--space-3); margin-top: var(--space-2); }

/* Collapsible "more about your persona" panel. */
.persona-detail > summary { list-style: none; display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); cursor: pointer; font-family: var(--font-display); font-weight: var(--font-display-weight); color: var(--text-strong); font-size: 1.05rem; }
.persona-detail > summary::-webkit-details-marker { display: none; }
.persona-detail > summary .chev { color: var(--text-muted); transition: transform .2s ease; }
.persona-detail[open] > summary .chev { transform: rotate(180deg); }

/* Persona strengths/growth blocks on the DNA results page (admin HTML with Tailwind-ish classes). */
.persona-html, .persona-html * { color: var(--text-strong) !important; }
.persona-html h4 { font-family: var(--font-display); font-weight: var(--font-display-weight); margin: var(--space-2) 0 .15rem; font-size: 1rem; }
.persona-html p { margin: 0 0 var(--space-2); color: var(--text) !important; padding-left: 0 !important; }
.persona-html .text-left { text-align: left !important; }
/* Embedded illustrations in the persona HTML come through full-size — keep them small + centred. */
.persona-html img { display: block; max-width: 56px; max-height: 56px; width: auto; height: auto; margin: var(--space-2) auto; }

/* 1–10 rating slider (the backend scores "rate" answers on a 1–10 scale). */
.rate-slider { display: flex; flex-direction: column; gap: var(--space-2); padding: 0 2px; }
.rate-value { text-align: center; font-family: var(--font-display); font-weight: var(--font-display-weight); font-size: 2.6rem; line-height: 1; color: var(--brand-accent); }
.rate-value .rate-max { font-size: 1rem; color: var(--text-muted); margin-left: 3px; }
.rate-range { -webkit-appearance: none; appearance: none; width: 100%; height: 10px; border-radius: 999px; outline: none; cursor: pointer; background: linear-gradient(to right, var(--brand-accent) var(--fill, 50%), var(--surface-alt) var(--fill, 50%)); }
.rate-range::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 30px; height: 30px; border-radius: 50%; background: #fff; border: 3px solid var(--brand-accent); box-shadow: 0 3px 10px rgba(0,0,0,.28); cursor: grab; transition: transform .05s ease; }
.rate-range::-webkit-slider-thumb:active { transform: scale(1.1); cursor: grabbing; }
.rate-range::-moz-range-thumb { width: 30px; height: 30px; border-radius: 50%; background: #fff; border: 3px solid var(--brand-accent); box-shadow: 0 3px 10px rgba(0,0,0,.28); cursor: grab; }
.rate-range:focus-visible { box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand-accent) 35%, transparent); }
.rate-hint { text-align: center; color: var(--text-muted); font-size: .85rem; margin: 2px 0 0; }
.rate-ends { display: flex; justify-content: space-between; margin-top: 0; font-size: .8rem; color: var(--text-muted); }

.rank-list { display: flex; flex-direction: column; gap: var(--space-2); }
.rank-card { display: flex; align-items: center; gap: var(--space-3); text-align: left; padding: var(--space-3); border-radius: var(--radius); border: 1.5px solid var(--border, rgba(127,127,127,.25)); background: var(--surface); cursor: pointer; }
.rank-card.is-selected { border-color: var(--indigo-300); background: var(--surface-alt); }
.rank-badge { width: 28px; height: 28px; border-radius: 50%; flex: none; display: grid; place-items: center; font-family: var(--font-display); font-weight: var(--font-display-weight); background: var(--surface-alt); color: var(--text-muted); }
.rank-card.is-selected .rank-badge { background: var(--brand-gradient); color: #fff; }
.rank-label { flex: 1; }
.rank-label * { margin: 0 !important; color: var(--text-strong) !important; font-size: 1rem !important; text-align: left !important; }

/* Profile field extras */
.field-hint { margin: .3rem 0 0; font-size: .8rem; color: var(--text-muted); }
.input[readonly] { background: var(--surface-alt); color: var(--text-muted); cursor: not-allowed; }

/* Radio-cards (e.g. "what are you doing now?") */
.radio-cards { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.radio-cards .radio-card { position: relative; display: inline-flex; align-items: center; padding: .55rem .95rem; border-radius: var(--radius-pill); border: 1.5px solid var(--border, rgba(127,127,127,.28)); background: var(--surface); cursor: pointer; font-size: .92rem; color: var(--text-strong); }
.radio-cards .radio-card input { position: absolute; opacity: 0; pointer-events: none; }
.radio-cards .radio-card:has(input:checked) { background: var(--brand-gradient); color: #fff; border-color: transparent; }
.radio-cards .radio-card.is-disabled { opacity: .55; cursor: not-allowed; }

/* School / college / university type-ahead */
.school-picker { position: relative; }
.school-selected { display: flex; align-items: center; gap: var(--space-2); padding: .7rem .9rem; border-radius: var(--radius); border: 1.5px solid var(--indigo-300); background: var(--surface-alt); }
.school-selected .material-icons { color: var(--indigo-300); }
.school-selected .school-name { font-weight: 700; color: var(--text-strong); flex: 1; }
.school-results { margin-top: var(--space-2); border: 1px solid var(--border, rgba(127,127,127,.22)); border-radius: var(--radius); overflow: hidden; max-height: 280px; overflow-y: auto; background: var(--surface); }
.school-result { display: flex; flex-direction: column; gap: 1px; text-align: left; width: 100%; padding: .6rem .8rem; background: none; border: 0; border-bottom: 1px solid var(--border, rgba(127,127,127,.14)); cursor: pointer; }
.school-result:last-child { border-bottom: 0; }
.school-result:hover { background: var(--surface-alt); }
.school-result.is-note { cursor: default; }
.school-result-name { font-weight: 600; color: var(--text-strong); }
.link { background: none; border: 0; padding: 0; color: var(--indigo-300); cursor: pointer; font-size: .85rem; text-decoration: underline; }

/* Dataset-backed suggest picker (industry single / skills multi) */
.suggest { position: relative; }
.suggest-tags { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-bottom: var(--space-2); }
.suggest-tags:empty { display: none; }
.suggest-chip { display: inline-flex; align-items: center; gap: .3rem; padding: .35rem .3rem .35rem .75rem; border-radius: var(--radius-pill); background: var(--brand-gradient); color: #fff; font-size: .88rem; }
.suggest-chip .chip-x { display: inline-grid; place-items: center; width: 20px; height: 20px; border-radius: 50%; border: 0; background: rgba(255,255,255,.25); color: #fff; cursor: pointer; font-size: 1rem; line-height: 1; }
.suggest-single { margin-bottom: 0; }

/* Registration form */
.check-row { display: flex; align-items: flex-start; gap: var(--space-3); font-size: 0.92rem; color: var(--text-strong); cursor: pointer; line-height: 1.4; }
.check-row input[type="checkbox"] { width: 20px; height: 20px; margin-top: 1px; flex: none; accent-color: var(--indigo-300); }
.req { color: #e5484d; }

/* Coach hub blocks */
.coach-dna { display: flex; align-items: center; gap: var(--space-3); }
.coach-dna-glyph { font-size: 1.9rem; width: 52px; height: 52px; border-radius: var(--radius); background: var(--surface-alt); display: grid; place-items: center; flex: none; }
.coach-nudge { display: flex; align-items: center; gap: var(--space-3); }
/* Inside a hub card the chat stream is bounded + scrolls (it's no longer the full-height flex child). */
.coach-chat { gap: var(--space-3); }
.coach-chat .chat-stream { flex: initial; max-height: 320px; overflow-y: auto; }
.chat-input { display: flex; gap: var(--space-2); align-items: center; position: sticky; bottom: 0; background: var(--surface); padding-top: var(--space-3); }
.typing { display: inline-flex; gap: 3px; }
.typing span { width: 6px; height: 6px; border-radius: 50%; background: var(--text-muted); animation: blink 1.2s infinite; }
.typing span:nth-child(2) { animation-delay: 0.2s; }
.typing span:nth-child(3) { animation-delay: 0.4s; }
@keyframes blink { 0%,80%,100% { opacity: 0.3; } 40% { opacity: 1; } }

/* ---------------------------------------------------------------
   Profile
   --------------------------------------------------------------- */
.avatar { width: 72px; height: 72px; border-radius: 50%; background: var(--brand-gradient); display: grid; place-items: center; color: #fff; font-family: var(--font-display); font-weight: var(--font-display-weight); font-size: 1.8rem; }
.profile-head { display: flex; align-items: center; gap: var(--space-4); }
.stat-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-3); text-align: center; }
.stat-row .stat { background: var(--surface-alt); border-radius: var(--radius); padding: var(--space-3); }
.stat-row .stat .n { font-family: var(--font-display); font-weight: var(--font-display-weight); font-size: 1.4rem; color: var(--text-strong); }
.stat-row .stat .l { font-size: 0.7rem; color: var(--text-muted); font-weight: 700; text-transform: uppercase; }

/* ---------------------------------------------------------------
   Profile sections (mirrors TH.Data.UserProfile)
   --------------------------------------------------------------- */
/* sticky section nav under the header */
.section-nav { position: sticky; top: 0; z-index: 10; background: var(--surface); padding: var(--space-2) 0; margin: 0 calc(-1 * var(--space-4)); padding-left: var(--space-4); padding-right: var(--space-4); }

.section-card { scroll-margin-top: var(--space-3); }
.section-subhead { font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); margin: var(--space-3) 0 var(--space-2); }
.divider { height: 1px; background: var(--line); margin: var(--space-3) 0; }
.edit-link { font-size: var(--fnt-small); font-weight: 700; }

/* definition list (label / value rows) */
.dl { margin: 0; display: grid; gap: var(--space-2); }
.dl-row { display: grid; grid-template-columns: 42% 1fr; gap: var(--space-3); align-items: baseline; }
.dl-row dt { color: var(--text-muted); font-size: var(--fnt-small); font-weight: 700; }
.dl-row dd { margin: 0; color: var(--text-strong); font-weight: 500; word-break: break-word; }

/* repeated list items (qualifications, experience, references) */
.list-item { padding: var(--space-3) 0; border-bottom: 1px solid var(--line); }
.list-item:last-child { border-bottom: none; padding-bottom: 0; }
.list-item:first-of-type { padding-top: 0; }
.addr-block { padding: var(--space-2) 0; }

/* sensitive-data treatment */
.sensitive-ic { font-size: 1rem; color: var(--amber-300); vertical-align: -2px; }
.sensitive-note { color: var(--text-muted); background: var(--surface-alt); border-radius: var(--radius); padding: var(--space-2) var(--space-3); margin: 0 0 var(--space-4); display: flex; gap: .4rem; align-items: flex-start; }

/* ---- Profile hub: completeness + section rows ---- */
.completeness .track { height: 10px; background: var(--soft-blue-200); border-radius: var(--radius-pill); overflow: hidden; }
.completeness .fill { height: 100%; width: 0; border-radius: var(--radius-pill); background: var(--brand-gradient); transition: width 0.7s cubic-bezier(.2,.8,.2,1); }

.sec-list { display: grid; gap: var(--space-2); }
.sec-row {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-sm);
  text-decoration: none; color: var(--text-strong);
  transition: box-shadow 0.15s ease, transform 0.08s ease;
}
.sec-row:active { transform: scale(0.995); }
.sec-row:hover { box-shadow: var(--shadow-md); }
.sec-ic { width: 2.4rem; height: 2.4rem; border-radius: var(--radius-pill); display: grid; place-items: center; flex: none; background: var(--surface-alt); color: var(--indigo-300); }
.sec-ic .material-icons { font-size: 1.25rem; }
.sec-body { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.sec-title { font-weight: 700; }
.sec-sub { font-size: var(--fnt-small); color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sec-status .material-icons { font-size: 1.5rem; }
/* These two icons ARE the profile's progress readout — the only per-section signal of
   what's done and what isn't. They were --teal-200 (1.57:1) and --line (1.32:1): the most
   important glyphs on the screen were the faintest things on it. Same palette, legible
   weight. */
/* --aqua-300 was still only 1.98:1 on white. --success (#249689) reaches 3.62:1, clearing
   the 3:1 threshold that applies to meaningful icons. The pale aqua is fine on dark. */
.sec-status.complete { color: var(--success); }
:root[data-theme="dark"] .sec-status.complete { color: var(--aqua-300); }
.sec-status.todo { color: #9a91a6; }
:root[data-theme="dark"] .sec-status.todo { color: #8b7d98; }

/* ---- Section detail (edit form) ---- */
.detail-head { display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-3); }
.detail-head h1 { margin: 0; font-size: 1.4rem; }
.list-edit { border: 1px solid var(--line); border-radius: var(--radius-lg); padding: var(--space-3); margin-bottom: var(--space-3); background: var(--surface-alt); }
.list-edit-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-2); }
/* direct-child only: must not uppercase the delete icon's <span class="material-icons"> (breaks the ligature) */
.list-edit-head > span { font-weight: 700; font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); }
/* belt-and-braces: never let inherited text-transform break icon ligatures */
.material-icons { text-transform: none; }
/* This is the "delete this qualification / job" button. It was 32px with --red-200 at
   2.01:1 — a destructive control that was both the smallest target on the form and the
   faintest thing on it. Being more specific than the base .icon-btn rule, it also survived
   the global bump to 44px, so it needs fixing here rather than there. */
.list-edit-head .icon-btn { width: 2.75rem; height: 2.75rem; background: transparent; color: #c62f3a; }
:root[data-theme="dark"] .list-edit-head .icon-btn { color: var(--red-200); }
.list-edit .field:last-child { margin-bottom: 0; }
/* Pinned Save/Cancel bar. The sticky positioning was right; the presentation wasn't — with
   no top edge and a --surface fill that didn't match the --surface-alt page behind it, the
   bar appeared to float in the middle of the form, slicing through the Qualifications card
   as content scrolled underneath. A border, a lift and a full-bleed background make it read
   as a bar sitting ON the page rather than debris in it. */
.form-actions {
  display: flex;
  gap: var(--space-3);
  margin-top: var(--space-5);
  position: sticky;
  bottom: 0;
  z-index: 5;
  /* Full-bleed past .view-pad's 16px inset so the bar meets both edges. */
  margin-left: calc(-1 * var(--space-4));
  margin-right: calc(-1 * var(--space-4));
  padding: var(--space-3) var(--space-4);
  background: var(--surface-alt);
  border-top: 1px solid var(--line);
  box-shadow: 0 -6px 16px -8px rgba(35, 18, 48, 0.18);
}
:root[data-theme="dark"] .form-actions { box-shadow: 0 -6px 16px -8px rgba(0, 0, 0, 0.55); }
/* Without this, a button's default flex min-width: auto keeps it at its unwrapped label width,
   which on a narrow screen forces the whole row (e.g. "Add to my profile") past the viewport edge
   instead of shrinking or wrapping its label onto a second line. */
.form-actions .btn { min-width: 0; white-space: normal; text-align: center; }

/* notification item */
.note { display: flex; gap: var(--space-3); padding: var(--space-3) 0; border-bottom: 1px solid var(--line); }
.note .ic { width: 2.4rem; height: 2.4rem; border-radius: var(--radius-pill); display: grid; place-items: center; flex: none; }
.note.match .ic { background: #d7f0e2; color: #1f7a4d; }
.note.status .ic { background: var(--soft-blue-200); color: var(--indigo-300); }
.note.dna .ic { background: #e6d6f3; color: var(--dark-purple-400); }
.note.unread { background: var(--light-blue-100); margin: 0 calc(-1 * var(--space-4)); padding-left: var(--space-4); padding-right: var(--space-4); }
.note .t { font-weight: 700; color: var(--text-strong); }
.note .time { font-size: 0.72rem; color: var(--text-muted); }

/* ---------------------------------------------------------------
   Opportunity search: toolbar, active filters, filter sheet
   --------------------------------------------------------------- */
.toolbar { display: flex; align-items: center; gap: var(--space-2); }
.filter-btn {
  display: inline-flex; align-items: center; gap: 0.4rem;
  padding: 0.55rem 0.95rem;
  border-radius: var(--radius-pill);
  background: var(--surface);
  border: 1.5px solid var(--line);
  box-shadow: var(--shadow-sm);
  color: var(--text-strong);
  font-family: var(--font-body);
  font-size: var(--fnt-small);
  font-weight: 700;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  position: relative;
  transition: background .15s ease, border-color .15s ease, color .15s ease, box-shadow .15s ease;
  -webkit-tap-highlight-color: transparent;
}
.filter-btn .material-icons { font-size: 1.15rem; color: var(--text-muted); transition: color .15s ease; }
.filter-btn:hover { border-color: var(--indigo-300); color: var(--indigo-300); }
.filter-btn:hover .material-icons { color: var(--indigo-300); }
.filter-btn:active { transform: translateY(1px); box-shadow: none; }
.filter-btn:focus-visible { outline: 2px solid var(--indigo-300); outline-offset: 2px; }
/* Filters shows the app's "selected" tint when any filter is applied — matches .chip.is-selected. */
.filter-btn.is-active { background: var(--soft-blue-200); border-color: var(--indigo-300); color: var(--indigo-300); }
.filter-btn.is-active .material-icons { color: var(--indigo-300); }
.filter-count { background: var(--deep-pink-200); color: #fff; font-size: 0.7rem; font-weight: 700; min-width: 1.2rem; height: 1.2rem; border-radius: var(--radius-pill); display: inline-grid; place-items: center; padding: 0 0.3rem; }
.sort-select { margin-left: auto; display: inline-flex; align-items: center; background: var(--surface); border: 1.5px solid var(--line); border-radius: var(--radius-pill); box-shadow: var(--shadow-sm); padding: 0 0.4rem 0 0.2rem; }
.sort-select select { appearance: none; -webkit-appearance: none; border: none; background: transparent; font: inherit; font-weight: 700; color: var(--text-strong); padding: 0.55rem 1.4rem 0.55rem 0.7rem; cursor: pointer;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%236b6e7c' stroke-width='2'><polyline points='6 9 12 15 18 9'/></svg>"); background-repeat: no-repeat; background-position: right 0.2rem center; }
.sort-select select:focus { outline: none; }
:root[data-theme="dark"] .sort-select select { background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%238b91a7' stroke-width='2'><polyline points='6 9 12 15 18 9'/></svg>"); }

.active-head { display: flex; align-items: center; justify-content: space-between; font-size: var(--fnt-small); color: var(--text-muted); margin-bottom: var(--space-2); letter-spacing: 0.03em; }
.chip.is-active { background: var(--soft-blue-200); border-color: var(--indigo-300); color: var(--indigo-300); }
.chip.is-active .x { font-size: 0.95rem; opacity: 0.7; }
.link-btn { background: none; border: none; color: var(--indigo-300); font: inherit; font-weight: 700; font-size: var(--fnt-small); display: inline-flex; align-items: center; gap: 0.3rem; padding: var(--space-2) 0; cursor: pointer; }
.link-btn .material-icons { font-size: 1.05rem; }

.empty-card { text-align: center; padding: var(--space-6) var(--space-4); }

/* ---- bottom-sheet ---- */
.sheet-overlay { position: absolute; inset: 0; background: rgba(0,0,0,0.45); z-index: 60; display: flex; align-items: flex-end; }
.sheet { background: var(--surface); width: 100%; max-height: 92%; border-radius: var(--radius-xl) var(--radius-xl) 0 0; display: flex; flex-direction: column; box-shadow: var(--shadow-lg); animation: sheetUp 0.25s cubic-bezier(.2,.8,.2,1) both; }
@keyframes sheetUp { from { transform: translateY(100%); } to { transform: none; } }
@media (prefers-reduced-motion: reduce) { .sheet { animation: none; } }
.sheet-head { display: flex; align-items: center; justify-content: space-between; padding: var(--space-4); border-bottom: 1px solid var(--line); }
.sheet-body { padding: var(--space-4); overflow-y: auto; }

/* Confirmation dialog (App.confirm) — centred card */
.confirm-overlay { align-items: center; justify-content: center; padding: var(--space-5); }
.confirm-card { background: var(--surface); width: 100%; max-width: 21rem; border-radius: var(--radius-xl); padding: var(--space-5) var(--space-4) var(--space-4); text-align: center; box-shadow: var(--shadow-lg); animation: sheetUp 0.2s cubic-bezier(.2,.8,.2,1) both; }
.confirm-icon { width: 3rem; height: 3rem; border-radius: 50%; display: grid; place-items: center; margin: 0 auto var(--space-3); background: var(--soft-blue-200); }
.confirm-icon .material-icons { font-size: 1.6rem; color: var(--indigo-300); }
.confirm-icon.danger { background: rgba(220,60,60,0.14); }
.confirm-icon.danger .material-icons { color: var(--red-200); }
.confirm-title { margin: 0 0 var(--space-2); font-size: 1.15rem; }
.confirm-msg { margin: 0; color: var(--text-muted); font-size: 0.9rem; line-height: 1.4; }
.confirm-actions { display: flex; gap: var(--space-3); margin-top: var(--space-4); }
.confirm-actions .btn { flex: 1; }
.confirm-presets { justify-content: center; margin-top: var(--space-3); }
.confirm-input { margin-top: var(--space-3); text-align: left; min-height: 4.5rem; }
.btn-danger { background: var(--red-200); color: #fff; }

/* Post-registration invite sheet (App.invitePrompt) — a centred card like .confirm-card, but it
   holds a small form, so it is left-aligned and allowed to scroll: the relationship list is
   server-fed and can be longer than a short phone screen once the keyboard is up. */
.invite-overlay { align-items: center; justify-content: center; padding: var(--space-4); }
.invite-sheet {
  background: var(--surface); width: 100%; max-width: 23rem; max-height: 100%;
  overflow-y: auto; border-radius: var(--radius-xl);
  padding: var(--space-5) var(--space-4) var(--space-4);
  box-shadow: var(--shadow-lg);
  animation: sheetUp 0.2s cubic-bezier(.2,.8,.2,1) both;
}
@media (prefers-reduced-motion: reduce) { .invite-sheet { animation: none; } }
.invite-head, .invite-sent { text-align: center; }
.invite-icon, .invite-tick {
  width: 3rem; height: 3rem; border-radius: 50%; display: grid; place-items: center;
  margin: 0 auto var(--space-3); background: var(--brand-accent-soft);
  color: var(--brand-accent); font-size: 1.6rem;
}
.invite-tick { background: rgba(76,175,80,.16); color: #4caf50; }
.invite-title { margin: 0 0 var(--space-2); font-size: 1.15rem; }
.invite-sub { margin: 0 0 var(--space-4); font-size: 0.9rem; line-height: 1.45; }
.invite-sheet .field { text-align: left; }
.invite-actions { display: flex; gap: var(--space-3); margin-top: var(--space-4); }
.invite-actions .btn { flex: 1; justify-content: center; }

/* "Show more" sentinel for the lazy-loaded opportunity list */
.load-more { display: flex; align-items: center; justify-content: center; gap: 0.4rem; width: 100%; padding: var(--space-3); margin-top: var(--space-1); background: var(--surface-alt); border: 1px dashed var(--line); border-radius: var(--radius-lg); color: var(--text-muted); font-weight: 700; font-size: 0.85rem; cursor: pointer; }
.load-more:hover { color: var(--text-strong); border-color: var(--indigo-300); }
.load-more .material-icons { font-size: 1.1rem; }

/* "+N more locations" chip on partner profiles */
.chip-more { background: var(--soft-blue-200); color: var(--indigo-300); font-weight: 700; border: none; cursor: pointer; }
.chip-more:hover { background: var(--indigo-300); color: #fff; }
.sheet-foot { display: flex; gap: var(--space-3); padding: var(--space-3) var(--space-4); border-top: 1px solid var(--line); background: var(--surface); }
/* Several full-width actions rather than one — the row default would cramp them. */
.sheet-foot.stack { flex-direction: column; gap: var(--space-2); }

/* One way of contacting someone, in the sheet UI.contactSheet draws. A full-width tap target
   rather than a button row: these are four separate destinations, not variations of one, and
   a thumb reaching the bottom of a phone should not have to aim. */
.contact-row {
  display: flex; align-items: center; gap: var(--space-3);
  margin-bottom: var(--space-2); text-decoration: none; color: inherit;
}
.contact-row:last-of-type { margin-bottom: 0; }
.contact-icon { color: var(--brand-accent); flex: none; }
.contact-label { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.contact-label .small { margin-top: 0.1rem; }
.contact-row .chev { color: var(--text-muted); flex: none; }

.facet-group { display: block; }
.facet-head { font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); margin-bottom: var(--space-3); display: flex; align-items: center; gap: 0.4rem; }
.facet-badge { background: var(--deep-pink-200); color: #fff; min-width: 1.1rem; height: 1.1rem; border-radius: var(--radius-pill); font-size: 0.65rem; display: inline-grid; place-items: center; padding: 0 0.3rem; }
.facet-sub { font-size: var(--fnt-small); font-weight: 700; color: var(--text-muted); margin: var(--space-3) 0 var(--space-2); }

/* segmented toggle (Postcode / By county) */
.seg { display: flex; background: var(--surface-alt); border-radius: var(--radius-pill); padding: 3px; margin-bottom: var(--space-3); }
.seg button { flex: 1; border: none; background: transparent; padding: 0.5rem; border-radius: var(--radius-pill); font: inherit; font-weight: 700; color: var(--text-muted); cursor: pointer; }
.seg button.active { background: var(--surface); color: var(--text-strong); box-shadow: var(--shadow-sm); }

.small-bar { padding: 0.1rem 0.3rem 0.1rem 0.85rem; margin-bottom: var(--space-2); }
.small-bar input { padding: 0.55rem 0; }
.small-bar .btn { padding: 0.5rem 0.9rem; }

/* level facet chips with count */
.facet { display: inline-flex; align-items: center; gap: 0.35rem; padding: 0.4rem 0.8rem; border-radius: var(--radius-pill); background: var(--surface); border: 1.5px solid var(--line); color: var(--text-strong); font-size: var(--fnt-small); font-weight: 700; cursor: pointer; }
.facet .count { color: var(--text-muted); font-weight: 700; font-size: 0.7rem; }
.facet.is-selected { background: var(--soft-blue-200); border-color: var(--indigo-300); color: var(--indigo-300); }
.facet.is-selected .count { color: var(--indigo-300); }
.facet.is-disabled { opacity: 0.4; cursor: default; }
.facet-list { max-height: 16rem; overflow-y: auto; }

/* ---------------------------------------------------------------
   Profile Glow-Up ✨ (AI CV import — renamed from "CV Glow-Up", which didn't describe what it does)
   --------------------------------------------------------------- */
/* hub entry card */
.cv-autofill-card {
  display: flex; align-items: center; gap: var(--space-3);
  background: var(--brand-gradient); color: #fff;
  border-radius: var(--radius-lg); padding: var(--space-4);
  box-shadow: var(--shadow-md); text-decoration: none;
  position: relative; overflow: hidden;
}
.cv-autofill-card::after { content: ""; position: absolute; width: 160px; height: 160px; right: -40px; top: -60px; background: radial-gradient(circle, rgba(255,255,255,0.22), transparent 70%); }
.cv-autofill-card .cv-autofill-ic { font-size: 1.6rem; }
.cv-autofill-card-body { display: flex; flex-direction: column; flex: 1; }
.cv-autofill-card-body .small { color: rgba(255,255,255,0.9); }
.cv-autofill-card .material-icons:last-child { color: rgba(255,255,255,0.9); }

/* hero on the import screen */
.cv-hero { text-align: center; padding: var(--space-5) var(--space-3) var(--space-4); }
.cv-hero h1 { margin: var(--space-2) 0 .25rem; }
.cv-hero p { color: var(--text-muted); margin: 0 auto; max-width: 30ch; }
.cv-sparkle { font-size: 3rem; line-height: 1; display: inline-block; }
.cv-sparkle.spin { animation: sparkle-pulse 1.4s ease-in-out infinite; }
@keyframes sparkle-pulse { 0%,100% { transform: rotate(-8deg) scale(1); } 50% { transform: rotate(8deg) scale(1.12); } }

/* dropzone */
.dropzone {
  display: flex; flex-direction: column; align-items: center; gap: 0.4rem;
  border: 2px dashed var(--indigo-300); border-radius: var(--radius-lg);
  background: var(--surface-alt); padding: var(--space-6) var(--space-4);
  text-align: center; cursor: pointer; transition: background 0.15s ease, border-color 0.15s ease;
}
.dropzone:hover { background: var(--soft-blue-200); }
.dropzone .material-icons { font-size: 2.4rem; color: var(--indigo-300); }
.dropzone strong { color: var(--text-strong); }

.cv-autofill-steps-card { display: grid; gap: var(--space-3); margin-top: var(--space-4); }
.cv-autofill-how { display: flex; gap: var(--space-3); align-items: flex-start; }
.cv-autofill-how .material-icons { color: var(--deep-pink-200); }

/* parsing steps */
.parse-steps { display: grid; gap: var(--space-3); margin-top: var(--space-4); }
/* min-width: 0 overrides the flex/grid-item default of min-width: auto, which otherwise refuses to
   shrink an item below its unwrapped content width — without it, a long step label pushes the row
   (and the page) wider than the viewport instead of wrapping onto a second line. */
.parse-steps li { display: flex; align-items: center; gap: var(--space-3); min-width: 0; color: var(--text-muted); font-weight: 700; opacity: 0.5; transition: opacity 0.3s ease; }
.parse-steps li .material-icons { flex: none; }
.parse-steps li > span:last-child { min-width: 0; overflow-wrap: break-word; }
.parse-steps li.active { opacity: 1; color: var(--text-strong); }
.parse-steps li.done { opacity: 1; color: var(--text); }
.parse-steps li.done .material-icons { color: var(--teal-200); }
.spinner { animation: spin 0.9s linear infinite; color: var(--indigo-300); }
@keyframes spin { to { transform: rotate(360deg); } }

/* review */
.confidence-pill { display: inline-flex; align-items: center; gap: 0.4rem; background: var(--soft-blue-200); color: var(--indigo-300); font-weight: 700; font-size: var(--fnt-small); padding: 0.4rem 0.8rem; border-radius: var(--radius-pill); }
.confidence-pill .material-icons { font-size: 1rem; }
.review-group .rg-head { display: flex; align-items: center; gap: var(--space-3); margin-bottom: var(--space-2); }
.review-group .rg-title { font-weight: 700; flex: 1; }
.review-group .rg-body .t-title { font-weight: 700; color: var(--text-strong); }

/* toggle switch */
.switch { position: relative; width: 44px; height: 26px; flex: none; }
.switch input { opacity: 0; width: 0; height: 0; }
.switch .slider { position: absolute; inset: 0; background: var(--line); border-radius: var(--radius-pill); transition: background 0.2s ease; }
.switch .slider::before { content: ""; position: absolute; width: 20px; height: 20px; left: 3px; top: 3px; background: #fff; border-radius: 50%; transition: transform 0.2s ease; box-shadow: var(--shadow-sm); }
.switch input:checked + .slider { background: var(--deep-pink-200); }
.switch input:checked + .slider::before { transform: translateX(18px); }

/* ---------------------------------------------------------------
   Application questions (apply flow)
   --------------------------------------------------------------- */
.q-card { display: block; }
.q-card.has-error { border-color: var(--red-200); box-shadow: 0 0 0 3px rgba(235,74,38,0.12); }
.q-meta { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-2); }
.q-type-badge { font-size: 0.62rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.05em; color: var(--indigo-300); background: var(--soft-blue-200); padding: 0.2rem 0.5rem; border-radius: var(--radius-pill); }
.q-num { font-size: 0.7rem; font-weight: 700; color: var(--text-muted); }
.q-text { font-weight: 700; color: var(--text-strong); margin: 0 0 var(--space-3); }
.req-star { color: var(--red-200); margin-left: 2px; }
.q-error { color: var(--red-200); font-size: var(--fnt-small); font-weight: 700; margin-top: var(--space-2); }
.q-error:empty { display: none; }
.file-name { margin-top: var(--space-2); }

/* Apply wizard — one question at a time (Career-DNA-quiz style stepper) */
.apply-wizard { min-height: calc(100dvh - var(--header-h)); display: flex; flex-direction: column; padding-bottom: var(--space-3); }
.apply-q { margin: var(--space-2) 0 var(--space-4); }
.apply-q .q-type-badge { display: inline-block; margin-bottom: var(--space-3); }
.apply-q .q-text-lg { font-family: var(--font-display); font-weight: var(--font-display-weight); font-size: 1.3rem; line-height: 1.3; color: var(--text-strong); margin: 0 0 var(--space-4); }
.apply-opts { display: flex; flex-direction: column; gap: var(--space-2); }
.apply-opt { display: flex; align-items: center; gap: var(--space-3); width: 100%; text-align: left; padding: var(--space-3) var(--space-4); border-radius: var(--radius); border: 1.5px solid var(--border, rgba(127,127,127,.25)); background: var(--surface); color: var(--text-strong); font-size: 1rem; cursor: pointer; }
.apply-opt > span:first-child { flex: 1; }
.apply-opt.is-selected { border-color: transparent; background: var(--brand-gradient); color: #fff; }
.apply-opt .material-icons { opacity: 0; font-size: 1.2rem; }
.apply-opt.is-selected .material-icons { opacity: 1; }
.apply-foot { position: sticky; bottom: 0; background: var(--surface); padding-top: var(--space-3); }
/* Ready-reckoner: a slim "what am I applying for" strip on every wizard step. */
.apply-rr { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-2) var(--space-3); margin-bottom: var(--space-3); border-radius: var(--radius); border: 1px solid var(--border, rgba(127,127,127,.2)); background: var(--surface-alt); }
.apply-rr .vac-logo { flex: none; }
.apply-rr-txt { min-width: 0; }
.apply-rr-title { font-family: var(--font-display); font-weight: var(--font-display-weight); font-size: .98rem; color: var(--text-strong); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.apply-rr-sub { font-size: .8rem; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ---------------------------------------------------------------
   Partners directory (employers & training providers)
   --------------------------------------------------------------- */
.partner-card { display: flex; align-items: center; gap: var(--space-3); text-decoration: none; color: var(--text-strong); }
.partner-logo { width: 48px; height: 48px; border-radius: var(--radius); background: var(--surface-alt); display: grid; place-items: center; font-family: var(--font-display); font-weight: var(--font-display-weight); font-size: 1.15rem; color: var(--indigo-300); flex: none; }
.partner-body { flex: 1; min-width: 0; }
.partner-name { font-family: var(--font-display); font-weight: var(--font-display-weight); color: var(--text-strong); display: flex; align-items: center; gap: 0.3rem; }
.partner-name .feat { font-size: 1rem; color: var(--amber-300); }
.partner-meta { margin-top: var(--space-2); }

.partner-hero { text-align: center; padding: var(--space-5) var(--space-4) var(--space-5); background: var(--brand-gradient); color: #fff; border-radius: 0 0 var(--radius-xl) var(--radius-xl); position: relative; overflow: hidden; }
.partner-hero::after { content: ""; position: absolute; width: 200px; height: 200px; right: -50px; top: -70px; background: radial-gradient(circle, rgba(255,255,255,0.18), transparent 70%); }
.partner-hero h1 { color: #fff; margin: var(--space-3) 0 0.25rem; }
.partner-hero-logo { width: 72px; height: 72px; border-radius: var(--radius-lg); background: rgba(255,255,255,0.16); display: grid; place-items: center; font-family: var(--font-display); font-weight: var(--font-display-weight); font-size: 1.8rem; color: #fff; margin: 0 auto; backdrop-filter: blur(4px); }
.partner-hero-tag { color: rgba(255,255,255,0.92); font-weight: 700; font-size: var(--fnt-small); }

/* ---------------------------------------------------------------
   Header menu sheet
   --------------------------------------------------------------- */
.menu-overlay { align-items: stretch; justify-content: flex-end; }
.menu-sheet { width: 86%; max-width: 340px; max-height: 100%; height: 100%; border-radius: var(--radius-xl) 0 0 var(--radius-xl); animation: menuIn 0.22s ease both; }
@keyframes menuIn { from { transform: translateX(100%); } to { transform: none; } }
@media (prefers-reduced-motion: reduce) { .menu-sheet { animation: none; } }
.menu-group { margin-bottom: var(--space-5); }
.menu-h { font-size: 0.68rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-muted); margin-bottom: var(--space-2); }
.menu-item { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) var(--space-2); border-radius: var(--radius); color: var(--text-strong); text-decoration: none; font-weight: 700; }
.menu-item:hover { background: var(--surface-alt); }
.menu-item .material-icons { color: var(--indigo-300); }
.menu-item.signout { color: var(--red-200); margin-top: var(--space-3); border-top: 1px solid var(--line); padding-top: var(--space-4); }
.menu-item.signout .material-icons { color: var(--red-200); }

/* ---------------------------------------------------------------
   Legal / info pages
   --------------------------------------------------------------- */
.legal-copy h3 { margin: var(--space-5) 0 var(--space-2); }
.legal-copy p { color: var(--text); }
.legal-copy .reasons { margin: var(--space-2) 0; }
.legal-table-stack { display: grid; gap: var(--space-3); margin: var(--space-2) 0 var(--space-3); }
.legal-table-row { border: 1px solid var(--line); border-radius: var(--radius-lg); padding: var(--space-3) var(--space-4); background: var(--surface-alt); }
.legal-table-title { font-weight: 700; color: var(--text-strong); }
.legal-table-field { font-size: var(--fnt-small); color: var(--text); margin-top: var(--space-2); }
.legal-table-label { display: block; font-size: 0.7rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); margin-bottom: 0.15rem; }
.legal-footer a { font-weight: 700; }

/* =============================================================
   Dark-mode component adjustments
   The brand hues stay, but a few "soft pastel" backgrounds and
   low-contrast selected states are re-tinted for dark surfaces.
   ============================================================= */
:root[data-theme="dark"] .chip.is-selected {
  background: rgba(239, 85, 139, 0.18);
  border-color: var(--pink-100);
  color: var(--pink-100);
}
:root[data-theme="dark"] .select-card.is-selected {
  background: rgba(198, 11, 136, 0.16);
  border-color: var(--deep-pink-200);
}
:root[data-theme="dark"] .select-card.is-selected .material-icons { color: var(--pink-100); }

/* Skeletons: sit slightly above the card surface */
:root[data-theme="dark"] .skeleton { background: #2b3146; }
:root[data-theme="dark"] .skeleton::after {
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.08), transparent);
}

/* Status pills / match badges: tinted translucent fills instead of bright pastels */
:root[data-theme="dark"] .pill-applied   { background: rgba(60, 95, 156, 0.28);  color: #aebfe6; }
:root[data-theme="dark"] .pill-reviewing { background: rgba(238, 171, 68, 0.22);  color: #f2c878; }
:root[data-theme="dark"] .pill-interview { background: rgba(164, 72, 159, 0.28);  color: #d8a6e0; }
:root[data-theme="dark"] .pill-offer     { background: rgba(103, 192, 150, 0.24); color: #8fe0b6; }
:root[data-theme="dark"] .pill-rejected  { background: rgba(235, 74, 38, 0.22);   color: #f29b86; }
:root[data-theme="dark"] .pill-st-received     { background: rgba(60, 95, 156, 0.28);   color: #aebfe6; }
:root[data-theme="dark"] .pill-st-reviewing    { background: rgba(238, 171, 68, 0.22);  color: #f2c878; }
:root[data-theme="dark"] .pill-st-next_steps   { background: rgba(164, 72, 159, 0.28);  color: #d8a6e0; }
:root[data-theme="dark"] .pill-st-action       { background: rgba(228, 63, 138, 0.24);  color: #f2a0c6; }
:root[data-theme="dark"] .pill-st-external     { background: rgba(60, 95, 156, 0.18);   color: #aebfe6; }
:root[data-theme="dark"] .pill-st-successful   { background: rgba(103, 192, 150, 0.24); color: #8fe0b6; }
:root[data-theme="dark"] .pill-st-unsuccessful { background: rgba(235, 74, 38, 0.22);   color: #f29b86; }
:root[data-theme="dark"] .pill-st-withdrawn    { background: rgba(127, 127, 127, 0.18); color: var(--text-muted); }

:root[data-theme="dark"] .match-badge        { background: var(--surface-alt); color: var(--text); }
:root[data-theme="dark"] .match-badge.high   { background: rgba(103, 192, 150, 0.22); color: #8fe0b6; }
:root[data-theme="dark"] .match-badge.mid    { background: rgba(238, 171, 68, 0.20);  color: #f2c878; }

:root[data-theme="dark"] .note.match .ic  { background: rgba(103, 192, 150, 0.22); color: #8fe0b6; }
:root[data-theme="dark"] .note.status .ic { background: rgba(60, 95, 156, 0.30);  color: #aebfe6; }
:root[data-theme="dark"] .note.dna .ic    { background: rgba(164, 72, 159, 0.28);  color: #d8a6e0; }

:root[data-theme="dark"] .todo-flag { background: rgba(238, 150, 68, 0.14); }

/* "Let employers find me" — proactive-search visibility (profile hub + Privacy & consents) */
.visibility-card { margin: var(--space-4) 0; }
.toggle-field { margin: 0; }
.visibility-row { display: flex; align-items: flex-start; gap: var(--space-3); cursor: pointer; }
.visibility-row .visibility-text { display: flex; flex-direction: column; gap: .2rem; flex: 1; min-width: 0; }
.visibility-row .switch { margin-top: 2px; }
.visibility-status { display: flex; align-items: center; gap: var(--space-3); text-decoration: none; color: inherit; }
.visibility-status > span:nth-child(2) { display: flex; flex-direction: column; min-width: 0; }
.visibility-status.is-on > .material-icons:first-child { color: var(--success, #1e7f55); }
.visibility-status.is-off > .material-icons:first-child { color: var(--text-muted); }
.discovery-notice { border-left: 4px solid var(--success, #1e7f55); }
.discovery-notice p { margin: .35rem 0; }
.discovery-notice-actions { display: flex; gap: var(--space-2); margin-top: var(--space-2); flex-wrap: wrap; }

/* ---- Careers quizzes (employer-branded Pathfinder quizzes: careers-quizzes.html / careers-quiz.html) ---- */
.cq-card { display: flex; align-items: center; gap: var(--space-3); text-decoration: none; }
.cq-card-body { display: flex; flex-direction: column; gap: .15rem; flex: 1; min-width: 0; }
.cq-logo { width: 56px; height: 56px; flex: none; padding: 4px; box-sizing: border-box; border-radius: var(--radius, 12px); background: #fff; border: 1px solid rgba(0,0,0,.08); display: flex; align-items: center; justify-content: center; overflow: hidden; font-size: 1.6rem; }
.cq-logo img { max-width: 100%; max-height: 100%; object-fit: contain; border-radius: 6px; }
.cq-logo-house { background: var(--deep-pink-50, #fce4f1); color: var(--deep-pink-600, #c60b88); border-color: transparent; }
.cq-hero { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-4); border-radius: var(--radius-lg, 16px); color: #fff; }
.cq-hero .cq-logo { width: 64px; height: 64px; }
.cq-hero .cq-logo { border-color: rgba(255,255,255,.35); background: transparent; }

/* =============================================================
   WG Futures components
   Everything below is WG-specific and was added when the shell
   was cloned from gmfj-app. Anything above this line came across
   unchanged and should stay diffable against the sibling apps.
   ============================================================= */

/* ---- shared utilities the WG views rely on ---- */
.track { height: 10px; background: var(--surface-soft); border-radius: var(--radius-pill); overflow: hidden; }
.fill  { height: 100%; width: 0; border-radius: var(--radius-pill); background: var(--brand-gradient);
         transition: width .7s cubic-bezier(.2,.8,.2,1); display: block; }
.chev  { color: var(--text-muted); flex-shrink: 0; }
.sk-card-wrap { padding: var(--space-4); }

.pill.brand { background: var(--brand-accent-soft); color: var(--brand-accent); }
.pill.warn  { background: #fdf0d5; color: #8a5a00; }
.pill.ok    { background: #dcf1ee; color: #14675d; }
:root[data-theme="dark"] .pill.warn { background: #4a3410; color: #f9cf58; }
:root[data-theme="dark"] .pill.ok   { background: #12403a; color: #7fc5bd; }

/* ---- avatars ---- */
.person-avatar {
  width: 42px; height: 42px; flex: 0 0 42px;
  border-radius: 50%;
  background: var(--brand-gradient);
  color: #fff; font-weight: 700; font-size: .85rem;
  display: inline-flex; align-items: center; justify-content: center;
}
.person-avatar.lg { width: 64px; height: 64px; flex-basis: 64px; font-size: 1.15rem; }
.person-avatar .material-icons { font-size: 20px; }

/* ---- unread indicators ---- */
.badge-dot {
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--tangerine-400); flex-shrink: 0;
}
.badge-count {
  min-width: 20px; height: 20px; padding: 0 5px;
  border-radius: var(--radius-pill);
  background: var(--tangerine-400); color: #241432;
  font-size: .72rem; font-weight: 700; line-height: 20px; text-align: center;
}

/* ---- support group row ---- */
.person-row { display: flex; align-items: center; gap: var(--space-3); }
.person-body { flex: 1; min-width: 0; }
.person-name { margin: 0; font-size: var(--fnt-h4); }
.person-meta { display: flex; flex-wrap: wrap; gap: var(--space-1); margin-top: 3px; }
/* A pending link must LOOK pending — it grants nothing until approved. */
.person-row.is-pending { border-style: dashed; opacity: .8; }

/* ---- task row ---- */
.task-row { display: flex; align-items: flex-start; gap: var(--space-3); }
.task-state { color: var(--text-muted); }
.task-state.done { color: var(--asparagus); }
.task-body { flex: 1; min-width: 0; }
.task-title { margin: 0; font-size: var(--fnt-h4); }
.task-title.struck { text-decoration: line-through; color: var(--text-muted); }
.task-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-top: 4px; }
.task-meta .material-icons { font-size: .95rem; vertical-align: -2px; }

/* ---- chat list row ---- */
.chat-row { display: flex; align-items: center; gap: var(--space-3); }
.chat-body { flex: 1; min-width: 0; }
.chat-title { margin: 0; font-size: var(--fnt-h4); }
.chat-snippet { margin: 2px 0 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-side { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; flex-shrink: 0; }
.chat-row.is-unread .chat-title { font-weight: 900; }
.chat-row.is-unread .chat-snippet { color: var(--text-strong); }

/* ---- documents ---- */
.doc-row { display: flex; align-items: center; gap: var(--space-3); }
.doc-icon { color: var(--brand-accent); }
.doc-body { flex: 1; min-width: 0; }
.doc-name { margin: 0; font-size: var(--fnt-h4); word-break: break-word; }

/* ---- welcome ---- */
.wgf-welcome {
  min-height: 100%;
  display: flex; flex-direction: column; justify-content: space-between;
  background: var(--brand-gradient); color: #fff;
  padding: var(--space-7) var(--space-5) var(--space-5);
}
.wgf-welcome-logo { width: 132px; margin-bottom: var(--space-6); }
.wgf-welcome-top .display { color: #fff; margin: 0 0 var(--space-4); }
.wgf-welcome-sub { color: rgba(255,255,255,.86); font-size: var(--fnt-body); margin: 0; }
.wgf-welcome-actions { display: grid; gap: var(--space-2); margin-top: var(--space-6); }
.wgf-welcome-actions .btn-outline { border-color: rgba(255,255,255,.6); color: #fff; background: transparent; }
.wgf-welcome-actions .btn-ghost { color: rgba(255,255,255,.86); }
.wgf-welcome .link { color: #fff; text-decoration: underline; }
.wgf-welcome .small.muted { color: rgba(255,255,255,.7); }

/* ---- onboarding carousel ---- */
.wgf-onboard-panel { text-align: center; padding: var(--space-6) var(--space-2); }
.wgf-onboard-ic {
  font-size: 56px; color: var(--brand-accent);
  background: var(--brand-accent-soft);
  width: 96px; height: 96px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  margin-bottom: var(--space-4);
}
.wgf-onboard-panel h1 { margin: 0 0 var(--space-3); }
.wgf-steps { padding-left: 1.1rem; margin: 0; }
.wgf-steps li { margin-bottom: var(--space-3); }

/* ---- auth screens ---- */
.wgf-auth-back { padding-left: 0; margin-bottom: var(--space-2); }
.wgf-auth h1 { margin-bottom: var(--space-2); }
.wgf-code { letter-spacing: .5em; text-align: center; font-size: 1.4rem; font-weight: 700; }
.wgf-code-out {
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 1.05rem; font-weight: 800; letter-spacing: .08em;
  color: var(--brand-accent); text-align: center;
  background: var(--brand-accent-soft); border-radius: var(--radius);
  padding: var(--space-3); margin: var(--space-3) 0;
  /* The code is now 8 characters shown as two groups of four, so it fits a phone screen without
     wrapping — but keep the wrap rules as a floor in case InviteCodeLength is raised. */
  overflow-wrap: anywhere; word-break: break-word; max-width: 100%;
  font-size: 1.5rem; letter-spacing: .14em;
}
.wgf-qr {
  display: flex; justify-content: center;
  padding: var(--space-3); margin: var(--space-3) 0;
  background: #fff; border-radius: var(--radius);   /* QR needs a light quiet-zone to scan */
}
.wgf-qr img, .wgf-qr canvas { display: block; width: 160px; height: 160px; }

/* ---- careers lead contact details (person screen) ----
   The legacy app let you tap a lead's number to call them; these are the controls for that.
   Wraps rather than scrolls: three buttons at large text sizes won't fit one line on a small
   phone, and a horizontally clipped Call button is worse than a second row. */
.wgf-phone {
  font-size: 1.25rem; font-weight: 800; letter-spacing: .02em;
  color: var(--text-strong);
}
.wgf-contact-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.wgf-contact-actions .btn { flex: 1 1 auto; min-width: 7.5rem; justify-content: center; }

/* ---- home ---- */
.wgf-home-hero { padding: var(--space-6) var(--space-5) var(--space-5); }
.wgf-home-hi { margin: 0; color: rgba(255,255,255,.8); font-size: var(--fnt-small); }
.wgf-home-hero h1 { margin: 2px 0 0; color: #fff; }
.wgf-home-sub { margin: var(--space-2) 0 0; color: rgba(255,255,255,.85); font-size: var(--fnt-small); }

/* ---- thread ---- */
.wgf-thread { display: flex; flex-direction: column; height: 100%; }
.wgf-thread-title { flex: 1; min-width: 0; }
.wgf-thread-title h2 { margin: 0; font-size: var(--fnt-h3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wgf-thread-title p { margin: 0; }
.wgf-thread-body { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.wgf-thread-body .chat-stream { overflow-y: auto; }

/* ---- job detail ---- */
.wgf-job-head { display: flex; align-items: center; gap: var(--space-3); }
.wgf-job .detail-head { display: flex; align-items: center; justify-content: space-between; padding: var(--space-3) var(--space-4) 0; }

/* ---- profile ---- */
.wgf-profile-hero { display: flex; align-items: center; gap: var(--space-4); padding: var(--space-6) var(--space-5); }
.wgf-profile-hero h1 { color: #fff; }
.wgf-danger { color: var(--error); }

/* ---- fixes found by screenshotting the shell ---- */

/* Base .pill carries no background, so a tone-less pill rendered as bare uppercase
   text. Give the default a neutral chip so `UI.pill(x)` is always legible. */
.pill { background: var(--surface-soft); color: var(--text-muted); }

/* .edit-link had no gap, so "＋Invite" ran together. */
.edit-link { display: inline-flex; align-items: center; gap: 4px; }

/* The Chat tab carries two actions ("New message" and "Invite"); .section-head only spaces its
   direct children apart, so they need their own row to sit in. "New message" is a <button>
   rather than a link, hence the reset — it must read as the same control as its sibling. */
.chat-head-actions { display: flex; align-items: center; gap: var(--space-4); }
.chat-head-actions button.edit-link {
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; font-size: var(--fnt-small); font-weight: 700; color: var(--brand-accent);
}

/* A picker row is a <button> wearing .card, so undo the control defaults the card doesn't. */
.pick-row {
  width: 100%; text-align: left; font: inherit; color: inherit; cursor: pointer;
}
.pick-row[disabled] { opacity: 0.6; cursor: default; }
.pick-row > .material-icons { color: var(--text-muted); flex: none; }
.edit-link .material-icons { font-size: 1.05rem; }

/* Thread: pin the composer to the bottom of the viewport rather than to the end of a
   short message list. 100dvh accounts for mobile browser chrome. */
.wgf-thread { min-height: calc(100dvh - var(--header-h) - var(--bottomnav-h)); }
.wgf-thread-body { flex: 1; }
.wgf-thread-body .chat-stream { flex: 1; justify-content: flex-end; }

/* Welcome screen sits on the brand gradient, so the ghost button's inherited light
   background made white label text unreadable. Force both buttons transparent and
   fill the viewport — the view is chrome-less, so there is no header/nav to subtract. */
.wgf-welcome { min-height: 100dvh; }
.wgf-welcome-actions .btn-ghost,
.wgf-welcome-actions .btn-outline {
  background: transparent;
  box-shadow: none;
}
.wgf-welcome-actions .btn-ghost:hover,
.wgf-welcome-actions .btn-outline:hover { background: rgba(255,255,255,.12); }
.wgf-welcome-actions .btn-primary { background: rgba(255,255,255,.16); border: 1.5px solid rgba(255,255,255,.5); }
.wgf-welcome-actions .btn-primary:hover { background: rgba(255,255,255,.24); }

/* =============================================================
   Visual polish pass — WG Futures
   Appended so the fixes sit together and are easy to review.
   Every rule here traces to a finding from the screenshot audit
   (scratchpad/shoot.js), noted inline.
   ============================================================= */

/* ---- "Needed" pill, replacing the unexplained red asterisk ---- */
.req-pill {
  display: inline-block;
  margin-left: var(--space-2);
  padding: 1px 8px;
  border-radius: var(--radius-pill);
  background: var(--coral-100);
  color: #8a3d1a;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  vertical-align: 2px;
}
:root[data-theme="dark"] .req-pill { background: #4a2a18; color: #f8c9a8; }

/* ---- Dark theme: surfaces that were hard-coded light ----
   These all used light palette values in BOTH themes. The worst was .note.unread: a
   near-white lavender band behind near-white text in dark mode, measured at 1.17:1 — the
   unread notification, the one row on the screen meant to stand out, was the one row you
   could not read. */
:root[data-theme="dark"] .note.unread { background: #2f1c40; }
:root[data-theme="dark"] .note.match .ic  { background: #17402c; color: #7fd0a4; }
:root[data-theme="dark"] .note.status .ic { background: #262a4a; color: #b9bbdc; }
:root[data-theme="dark"] .note.dna .ic    { background: #3a2450; color: #d9bff0; }
:root[data-theme="dark"] .confirm-icon    { background: #262a4a; }
:root[data-theme="dark"] .chip.is-active  { background: #2c3050; border-color: var(--indigo-300); color: #c6c8e8; }
:root[data-theme="dark"] .filter-count    { background: var(--deep-pink-600); }

/* Unread notifications need a second signal — colour alone fails anyone who can't see it,
   and on a dark ground a subtle tint is easy to miss regardless. */
.note.unread { position: relative; }
.note.unread::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
  background: var(--brand-accent);
}

/* ---- Empty-state icons ----
   48px glyphs at 1.79:1 read as a rendering fault rather than an illustration. */
.empty-card .material-icons,
.empty .material-icons { color: #a99fb5; }
:root[data-theme="dark"] .empty-card .material-icons,
:root[data-theme="dark"] .empty .material-icons { color: #6d6279; }

/* ---- Destructive actions ----
   delete_outline sat at 2.01:1 — a destructive control should be clearly legible, not
   whispered. Still red, just a red you can actually see on white. */
.icon-btn .material-icons[data-danger],
.wgf-danger .material-icons,
.icon-btn.is-danger .material-icons { color: #c62f3a; }
:root[data-theme="dark"] .icon-btn.is-danger .material-icons,
:root[data-theme="dark"] .wgf-danger .material-icons { color: var(--red-200); }

/* ---- .edit-link on a <button> vs an <a> ----
   7 of these are anchors and pick up `a { color: var(--indigo-300) }`; one ("Mark all
   read") is a button and picked up the browser's default grey box with black text, which in
   dark mode looked like an unstyled control dropped on the page. Reset the chrome so both
   element types render identically. */
.edit-link {
  background: none;
  border: none;
  font: inherit;
  font-weight: 700;
  font-size: var(--fnt-small);
  color: var(--link-ink);
  cursor: pointer;
}

/* =============================================================
   Touch targets

   Phone-only app, so 44px is the floor rather than an aspiration.
   The audit found icon buttons at 36px, filter chips at 31px,
   checkboxes at 13px and inline actions at 20px. Where a control
   is deliberately small, the HIT AREA is grown with padding and
   pulled back with a negative margin, so nothing moves visually.
   ============================================================= */

.icon-btn { width: 2.75rem; height: 2.75rem; }          /* 36 -> 44 */
.icon-btn .material-icons { font-size: 1.35rem; }        /* keep the glyph proportionate */

.chip { min-height: 2.75rem; }                           /* 31 -> 44 */

.btn { min-height: 2.75rem; }                            /* 43 -> 44; one pixel, but free */

/* Inline text actions ("See all", "New", "Invite", "Mark all read"). Visual size is
   unchanged — only the tappable box grows. */
.edit-link, .link-btn {
  padding-top: 12px; padding-bottom: 12px;
  margin-top: -12px; margin-bottom: -12px;
}

/* Checkboxes and radios were rendering at 13px — under a third of the floor, and these are
   the controls for consent and for multi-select filters. */
input[type="checkbox"],
input[type="radio"] {
  width: 1.35rem; height: 1.35rem;
  accent-color: var(--brand-accent);
  flex: none;
}
/* The label is the real target — a whole tappable row beats a slightly bigger box.
   Deliberately min-height ONLY. `.check-row` and `.radio-cards .radio-card` already own
   their layout, and an earlier draft of this rule set `align-items: center`, which would
   have overridden `.check-row`'s `flex-start` — that value is load-bearing, because it
   keeps the checkbox level with the FIRST line of a three-line consent label instead of
   floating against its vertical middle. Setting display/gap/alignment here would fight
   working CSS for no gain. */
label:has(> input[type="checkbox"]),
label:has(> input[type="radio"]),
.check-row,
.radio-cards .radio-card {
  min-height: 2.75rem;
  cursor: pointer;
}

/* ---- person row: pending-invite contact line + unread count ---- */
.person-contact {
  margin: 1px 0 0;
  font-size: var(--fnt-small);
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;   /* phone numbers shouldn't wobble between rows */
}
/* Replaces the bare .badge-dot, which said "something's here" without saying how much,
   and did so in place of the chevron. */
.badge-count {
  min-width: 1.35rem; height: 1.35rem;
  padding: 0 0.35rem;
  border-radius: var(--radius-pill);
  background: var(--brand-accent);
  color: #fff;
  font-size: 0.72rem; font-weight: 700;
  display: inline-grid; place-items: center;
  flex: none;
  font-variant-numeric: tabular-nums;
}

/* ---- Welcome screen ---- */

/* The three claims that replace the dead gradient. */
.wgf-welcome-points {
  list-style: none;
  margin: var(--space-6) 0 0;
  padding: 0;
  display: grid;
  gap: var(--space-4);
}
.wgf-welcome-points li {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  color: rgba(255, 255, 255, 0.92);
  font-size: var(--fnt-body);
  line-height: 1.35;
}
.wgf-welcome-points .material-icons {
  font-size: 1.4rem;
  color: #fff;
  background: rgba(255, 255, 255, 0.16);
  width: 2.5rem; height: 2.5rem;
  border-radius: var(--radius-pill);
  display: grid; place-items: center;
  flex: none;
}

/* "Sign in" is the primary action, but it was rgba(255,255,255,.16) with a .5 white border
   — all but identical to the .btn-outline directly beneath it, so the screen offered three
   near-identical choices and no steer. Solid white on the violet gradient is unmistakably
   the main action, and at 13.4:1 it's the most legible thing on the screen. */
.wgf-welcome-actions .btn-primary {
  background: #fff;
  border: 1.5px solid #fff;
  color: var(--russian-violet);
  box-shadow: var(--shadow-md);
}
.wgf-welcome-actions .btn-primary:hover { background: rgba(255, 255, 255, 0.9); }

/* ---- Chat bubbles: message runs ---- */

/* The sender caption is now only on the first bubble of a run, so it needs to read as a
   label rather than as a dimmed copy of the message text (it was an inline .small at .75
   opacity, which looked like a failed load). */
.bubble-from {
  display: block;
  margin-bottom: 3px;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--brand-accent);
}
:root[data-theme="dark"] .bubble-from { color: #cf9ada; }

/* Consecutive messages from one person belong together: tight inside a run, with real
   separation between runs. Without this every bubble sat at the same distance and a
   four-message burst looked like four unrelated messages. */
.chat-stream .bubble + .bubble { margin-top: 3px; }
.chat-stream .bubble.has-name { margin-top: var(--space-4); }
.chat-stream .bubble.me + .bubble.bot,
.chat-stream .bubble.bot + .bubble.me { margin-top: var(--space-4); }
.chat-stream .bubble:first-child { margin-top: 0; }

/* Square off the inner corners of a run so it reads as one block of speech. */
.chat-stream .bubble.bot + .bubble.bot:not(.has-name) { border-top-left-radius: 0.25rem; }
.chat-stream .bubble.me + .bubble.me { border-top-right-radius: 0.25rem; }

/* Start-of-conversation marker. Sits above the first bubble, so the empty space on a short
   thread says something instead of looking like a failed render. */
.chat-start {
  margin: 0 auto var(--space-5);
  padding: var(--space-2) var(--space-4);
  max-width: 88%;
  text-align: center;
  font-size: var(--fnt-small);
  color: var(--text-muted);
  background: var(--surface-soft);
  border-radius: var(--radius-pill);
  line-height: 1.35;
}

/* ---- Pinned bottom bars need a full-height container ----
   `position: sticky; bottom: 0` pins against the containing block. On a page whose content
   is shorter than the screen — a job with a two-line description, a short form — that block
   ends early, so the bar landed mid-screen with blank space beneath it and read as a
   floating fragment rather than a pinned action.

   A bare `min-height: 100%` on the padded block does NOT fix it: a percentage min-height
   resolved against an auto-height ancestor computes to `auto`, so the first attempt at this
   silently did nothing. The height has to come down an unbroken chain from .app-main, which
   has a definite height (flex: 1 inside the 100dvh shell) — flex hands it to each link.

   The two screens nest their bar at DIFFERENT depths — `.view > .wgf-job > .view-pad` for a
   job, `.view > .view-pad > #psBody` for a form — so no fixed-depth rule serves both. Used
   as a descendant selector, `:has()` matches every element on the path from .view down to
   the bar's own parent, which is exactly the chain that has to grow. */
.app-main > .view:has(.apply-bar),
.app-main > .view:has(.form-actions) { min-height: 100%; }

.app-main > .view:has(.apply-bar),
.app-main > .view:has(.apply-bar) :has(.apply-bar),
.app-main > .view:has(.form-actions),
.app-main > .view:has(.form-actions) :has(.form-actions) {
  display: flex;
  flex-direction: column;
}
.app-main > .view:has(.apply-bar) :has(.apply-bar),
.app-main > .view:has(.form-actions) :has(.form-actions) {
  flex: 1;
  min-height: 0;
}

/* Sticky positioning alone CANNOT do this. A bottom-stuck element is only ever offset
   upward — it is never pushed below its static position. On a short page that static
   position is immediately after the content, which is precisely where the bar was
   stranding itself. `margin-top: auto` walks it to the bottom in normal flow; sticky then
   takes over once there is enough content to scroll. */
.apply-bar,
.form-actions { margin-top: auto; }

/* .app-main carries `padding-bottom: bottomnav-h + space-5`, so the scrollport's content
   box ends 24px above the nav — a docked bar sitting there leaves a stripe of page below
   it. .apply-bar already compensated with a negative offset; .form-actions needs the same
   or the two bars dock at different heights. */
.form-actions { bottom: calc(-1 * var(--space-5)); }

/* ---- Favourite heart ----
   Rendered in --text-strong, so a saved job showed a solid BLACK heart — it read as a
   glyph that had failed to pick up its colour rather than as a deliberate "saved" state.
   Outline stays neutral; filled takes the brand accent. */
.icon-btn#jvFav .material-icons,
.icon-btn.save .material-icons { color: var(--text-muted); }
.icon-btn#jvFav.is-saved .material-icons,
.icon-btn.save.is-saved .material-icons { color: var(--brand-accent); }

/* .app-main pads its bottom by `bottomnav-h + space-5` so ordinary scrolled content clears
   the nav with a little air. A docked action bar IS the end of the page, so that extra
   --space-5 just leaves a stripe of background between the bar and the nav. Drop it on
   these pages and the bar meets the nav exactly; the negative `bottom` offsets that were
   previously compensating for it are no longer needed and would now overshoot. */
.app-main:has(.apply-bar),
.app-main:has(.form-actions) { padding-bottom: var(--bottomnav-h); }

.app-main:has(.apply-bar) .apply-bar,
.app-main:has(.form-actions) .form-actions { bottom: 0; }

/* The docked-bar pages turn their content container into a flex column (see above), and a
   flex item stretches on the cross axis by default — which blew the compact "← Profile"
   back pill out to the full width of the screen. It is a small button and should look
   like one; the fields around it still stretch as intended. */
.wgf-auth-back { align-self: flex-start; }

/* ---- Task category (legacy tr_name) ----
   On its own line under the meta row. Category names are long — "Work Experience and
   Internships" is 32 characters — so as another chip beside the status pill and due date
   they wrapped the row into three ragged lines. Quiet by design: the category is context,
   not the point of the row. */
.task-cat {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-top: 2px;
  font-size: 0.78rem;
  color: var(--text-muted);
  min-width: 0;
}
.task-cat .material-icons { font-size: 0.95rem; flex: none; }

/* =============================================================
   Job detail — polished hero, fact chips and a details card.
   Scoped under .wgf-job so nothing here touches other screens.
   All colour comes from tokens, so both themes track for free.
   ============================================================= */
.wgf-job .job-hero { display: flex; gap: var(--space-3); align-items: flex-start; margin-top: var(--space-2); }
.wgf-job .job-hero-logo {
  width: 60px; height: 60px; flex: none; border-radius: var(--radius-lg);
  background: var(--brand-accent-soft); color: var(--brand-accent);
  display: grid; place-items: center; overflow: hidden;
  font-family: var(--font-display); font-weight: 700; font-size: 1.4rem;
  box-shadow: inset 0 0 0 1px var(--line);
}
.wgf-job .job-hero-logo img { width: 100%; height: 100%; object-fit: cover; }
.wgf-job .job-hero-logo .material-icons { font-size: 28px; }
.wgf-job .job-hero-text { min-width: 0; padding-top: 2px; }
.wgf-job .job-title { margin: 0 0 3px; font-size: var(--fnt-h1); line-height: 1.15; }
.wgf-job .job-employer { margin: 0; color: var(--text-muted); font-weight: 600; font-size: var(--fnt-small); }
.wgf-job .job-tag {
  display: inline-block; margin-top: var(--space-2);
  padding: 3px 10px; border-radius: var(--radius-pill);
  background: var(--brand-accent-soft); color: var(--brand-accent);
  font-size: 0.72rem; font-weight: 700; letter-spacing: .03em; text-transform: uppercase;
}

.wgf-job .job-chips { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-4); }
.wgf-job .job-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 13px; border-radius: var(--radius-pill);
  background: var(--surface-soft); color: var(--text);
  font-size: var(--fnt-small); font-weight: 600;
}
.wgf-job .job-chip .material-icons { font-size: 17px; color: var(--brand-accent); }
.wgf-job .job-chip.is-wage { background: var(--brand-accent-soft); color: var(--brand-accent); }
.wgf-job .job-chip.is-wage .material-icons { color: var(--brand-accent); }

.wgf-job .job-facts {
  margin-top: var(--space-5);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-sm);
  padding: 0 var(--space-4);
}
.wgf-job .job-fact { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) 0; }
.wgf-job .job-fact + .job-fact { border-top: 1px solid var(--line); }
.wgf-job .job-fact > .material-icons { font-size: 20px; color: var(--brand-accent); flex: none; }
.wgf-job .job-fact-label { color: var(--text-muted); font-weight: 600; font-size: var(--fnt-small); }
.wgf-job .job-fact-value { margin-left: auto; color: var(--text-strong); font-weight: 600; text-align: right; }

.wgf-job .job-about { margin-top: var(--space-6); }
.wgf-job .job-about h2 { margin: 0 0 var(--space-2); font-size: var(--fnt-h3); }
.wgf-job .job-about p { margin: 0; color: var(--text); line-height: 1.62; }

/* A short wage note ("plus a completion bonus") sits with the wage chip, not as a section. */
.wgf-job .job-wage-note { margin: var(--space-2) 0 0; }

/* ---- Detail-page content sections (added 7 Oct 2026) ----
   The advert carries nine text fields plus three lists that the detail page never showed. Each
   section only renders when its field is filled, so these rules have to look right for a role
   with one section and for a role with all of them. */
.wgf-job .job-section { margin-top: var(--space-6); }
.wgf-job .job-section h2 {
  display: flex; align-items: center; gap: var(--space-2);
  margin: 0 0 var(--space-2); font-size: var(--fnt-h3);
}
.wgf-job .job-section h2 > .material-icons { font-size: 20px; color: var(--brand-accent); flex: none; }

/* pre-line, not pre-wrap: these come from a textarea, so the paragraph breaks the employer typed
   are meaningful and must survive, but their trailing spaces and indentation shouldn't. */
.wgf-job .job-body {
  margin: 0; color: var(--text); line-height: 1.62;
  white-space: pre-line; overflow-wrap: anywhere;
}

/* The full description is sanitised HTML rather than textarea text, so its breaks are real
   elements. pre-line on top of them would double every gap — the markup carries the spacing. */
.wgf-job .job-rich { white-space: normal; }
.wgf-job .job-rich > :first-child { margin-top: 0; }
.wgf-job .job-rich > :last-child { margin-bottom: 0; }
.wgf-job .job-rich p { margin: 0 0 var(--space-3); }
/* Editors leave "<p></p>" behind constantly — the live feed opens adverts with one. Without this
   every such advert starts with a stray blank line. "<p><br></p>" is left alone: that one is a
   deliberate spacer the employer typed. */
.wgf-job .job-rich p:empty { display: none; }
.wgf-job .job-rich h3,
.wgf-job .job-rich h4 {
  margin: var(--space-4) 0 var(--space-2);
  font-size: var(--fnt-h3); color: var(--text-strong);
}
.wgf-job .job-rich ul,
.wgf-job .job-rich ol { margin: 0 0 var(--space-3); padding-left: 1.25em; }
.wgf-job .job-rich li { margin: 0 0 var(--space-1); }
.wgf-job .job-rich a { color: var(--brand-accent); text-decoration: underline; }
.wgf-job .job-rich strong, .wgf-job .job-rich b { color: var(--text-strong); font-weight: 600; }
/* The short description reads as a standfirst above the full one. */
.wgf-job .job-lede { margin: 0 0 var(--space-3); color: var(--text-strong); font-weight: 600; line-height: 1.55; }

.wgf-job .job-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-2); }
.wgf-job .job-list li { display: flex; align-items: flex-start; gap: var(--space-2); color: var(--text); line-height: 1.5; }
.wgf-job .job-list li > .material-icons { font-size: 18px; color: var(--brand-accent); flex: none; margin-top: 2px; }
