/* ==========================================================================
   Internship Bazaar — Components
   ========================================================================== */

/* ---------- Buttons ------------------------------------------------------ */
.btn {
  --btn-bg: var(--surface); --btn-fg: var(--text); --btn-br: var(--border);
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  padding: .65rem 1.1rem; border-radius: var(--r-md);
  border: 1px solid var(--btn-br); background: var(--btn-bg); color: var(--btn-fg);
  font-weight: 700; font-size: var(--fs-base); line-height: 1.2;
  cursor: pointer; white-space: nowrap; text-decoration: none;
  transition: background var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease),
              color var(--t-fast) var(--ease), transform var(--t-fast) var(--ease),
              box-shadow var(--t-fast) var(--ease);
}
@media (hover: hover) { .btn:hover { text-decoration: none; } }
.btn:active { transform: translateY(1px); }
.btn:disabled, .btn[aria-disabled="true"] { opacity: .55; cursor: not-allowed; transform: none; }

.btn-primary { --btn-bg: var(--primary); --btn-fg: var(--on-primary); --btn-br: var(--primary); box-shadow: var(--shadow-sm); }
@media (hover: hover) { .btn-primary:hover { --btn-bg: var(--primary-hover); --btn-br: var(--primary-hover); box-shadow: var(--shadow-md); } }
.btn-primary:active { --btn-bg: var(--primary-active); }

.btn-ghost { --btn-bg: transparent; --btn-br: transparent; --btn-fg: var(--text-muted); }
@media (hover: hover) { .btn-ghost:hover { --btn-bg: var(--surface-hover); --btn-fg: var(--text); } }

@media (hover: hover) { .btn-outline:hover { --btn-br: var(--primary); --btn-fg: var(--primary); --btn-bg: var(--primary-soft); } }

.btn-soft { --btn-bg: var(--primary-soft); --btn-br: var(--primary-soft-br); --btn-fg: var(--primary); }
@media (hover: hover) { .btn-soft:hover { --btn-bg: var(--primary-soft-br); } }

.btn-danger { --btn-bg: var(--red-500); --btn-fg: #fff; --btn-br: var(--red-500); }
@media (hover: hover) { .btn-danger:hover { --btn-bg: var(--red-600); --btn-br: var(--red-600); } }
.btn-danger-soft { --btn-bg: var(--red-50); --btn-fg: var(--red-500); --btn-br: transparent; }
/* It had no hover state at all, so pointing at Withdraw or Remove gave no
   sign it was live. Fills solid red, the same end state as .btn-danger. */
@media (hover: hover) { .btn-danger-soft:hover { --btn-bg: var(--red-500); --btn-fg: #fff; } }

.btn-lg { padding: .9rem 1.6rem; font-size: var(--fs-md); border-radius: var(--r-lg); }
.btn-sm { padding: .42rem .8rem; font-size: var(--fs-sm); border-radius: var(--r-sm); }
.btn-icon { padding: .55rem; width: 2.4rem; height: 2.4rem; border-radius: var(--r-md); }
.btn-block { width: 100%; }

/* Google's brand button stays legible on a white pill in both themes, since
   the multi-colour "G" mark only reads correctly on a light background. */
.btn-google { --btn-bg: #fff; --btn-fg: #1F1F1F; --btn-br: #dadce0; gap: .65rem; }
@media (hover: hover) { .btn-google:hover { --btn-bg: #f8f9fa; } }
:root[data-theme="dark"] .btn-google { --btn-br: var(--border); }

.or-divider { display: flex; align-items: center; gap: .75rem; margin: 1.1rem 0; }
.or-divider span:not(.or-label) { flex: 1; height: 1px; background: var(--border); }
.or-label { font-size: var(--fs-xs); font-weight: 800; color: var(--text-subtle); letter-spacing: .04em; }

/* ---------- Badges / chips ---------------------------------------------- */
.badge {
  display: inline-flex; align-items: center; gap: .32rem;
  padding: .24rem .6rem; border-radius: var(--r-full);
  font-size: var(--fs-xs); font-weight: 700; line-height: 1.5;
  background: var(--bg-subtle); color: var(--text-muted); border: 1px solid transparent;
  white-space: nowrap;
}
.badge-verified { background: var(--green-50); color: var(--green-600); }
.badge-beginner { background: var(--violet-50); color: var(--violet-500); }
.badge-wfh      { background: var(--blue-50);   color: var(--blue-500); }
.badge-urgent   { background: var(--amber-100); color: var(--amber-600); }
.badge-primary  { background: var(--primary-soft); color: var(--primary); border-color: var(--primary-soft-br); }
.badge-danger   { background: var(--red-50); color: var(--red-500); }
.badge-neutral  { background: var(--bg-subtle); color: var(--text-muted); border-color: var(--border); }
:root[data-theme="dark"] .badge-verified { color: #4ADE80; }
:root[data-theme="dark"] .badge-beginner { color: #C4B5FD; }
:root[data-theme="dark"] .badge-wfh { color: #93C5FD; }
:root[data-theme="dark"] .badge-urgent { color: var(--amber-300); }
:root[data-theme="dark"] .badge-danger { color: #FCA5A5; }

.chip {
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .32rem .7rem; border-radius: var(--r-full);
  background: var(--bg-subtle); border: 1px solid var(--border);
  font-size: var(--fs-xs); font-weight: 600; color: var(--text-muted);
}
.chip-match { background: var(--primary-soft); border-color: var(--primary-soft-br); color: var(--primary); }
.chip button { background: none; border: 0; cursor: pointer; display: flex; padding: 0; color: inherit; opacity: .7; }
@media (hover: hover) { .chip button:hover { opacity: 1; } }

/* ---------- Cards -------------------------------------------------------- */
.card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); padding: 1.35rem; }
.card-pad-lg { padding: 1.75rem; }
.card-interactive { transition: border-color var(--t) var(--ease), box-shadow var(--t) var(--ease), transform var(--t) var(--ease); }
@media (hover: hover) { .card-interactive:hover { border-color: var(--primary-soft-br); box-shadow: var(--shadow-md); transform: translateY(-2px); } }

/* ---------- Forms -------------------------------------------------------- */
.field { display: block; }
.field + .field { margin-top: 1.1rem; }
/* Any .field that is a direct grid item (e.g. the 2-column "Full name /
   Email" rows on the profile and post-internship forms) must NOT pick up
   the sibling margin above — the grid's own `gap` already spaces the rows.
   Without this, every field past the first in DOM order gets an extra
   1.1rem pushed onto its top, which does nothing visible in a single
   column but silently knocks a 2-column row's second cell down out of
   alignment with the first, since grid siblings sit in the same row and
   are supposed to share the same top edge. */
.grid > .field { margin-top: 0; }

/* Breathing room under a form's section heading, whatever comes first
   under it. This was inconsistent by accident: sections whose first child
   happened to be a `.grid mt-2` (Role, Timing & openings) got 1rem, while
   ones starting with a bare `.field` (Stipend, Skills & eligibility,
   Description, and Apply's cover-note section) got none — so those
   headings sat directly on top of their first label. One rule here rather
   than remembering an mt-2 on each section's first child. Scoped to
   .card so it only touches the card-based forms, not the prose/marketing
   headings elsewhere, which have their own typographic spacing. */
.card h3 + .field, .card h3 + .grid, .card h3 + .role-toggle,
.card h4 + .field, .card h4 + .grid { margin-top: 1rem; }
/* Same gap in the other direction: `.field + .field` spaces consecutive
   fields by 1.1rem, but a field whose previous sibling is the section's
   description paragraph matched nothing and sat flush against it — which
   is what jammed "Skills" up under the Skills & interests blurb. */
.card p + .field { margin-top: 1.1rem; }
/* A subtitle line is part of the heading, not the content under it, so it
   sits close rather than a full 1rem away — Apply's "Sent from your
   profile" sat at a flat 0 before this, touching the heading above it. */
.card h3 + p { margin-top: .35rem; }
.label { display: block; font-weight: 700; font-size: var(--fs-sm); margin-bottom: .4rem; }
.label .req { color: var(--red-500); }
.hint { font-size: var(--fs-xs); color: var(--text-subtle); margin-top: .35rem; }
.error-text { font-size: var(--fs-xs); color: var(--red-500); margin-top: .35rem; font-weight: 600; }

/* Show/hide toggle inside a password field — the input gets right padding
   so its own text never runs under the button. */
.pw-input-wrap { position: relative; }
.pw-input-wrap .input { padding-right: 2.6rem; }
.pw-toggle {
  position: absolute; right: .35rem; top: 50%; transform: translateY(-50%);
  border: 0; background: none; padding: .4rem; cursor: pointer;
  color: var(--text-subtle); display: flex; align-items: center; justify-content: center;
  border-radius: var(--r-sm);
}
@media (hover: hover) { .pw-toggle:hover { color: var(--text); background: var(--surface-hover); } }
.pw-toggle:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }

.input, .select, .textarea {
  width: 100%; padding: .65rem .85rem;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--r-md);
  transition: border-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.input::placeholder, .textarea::placeholder { color: var(--text-subtle); }
@media (hover: hover) { .input:hover, .select:hover, .textarea:hover { border-color: var(--border-strong); } }
.input:focus, .select:focus, .textarea:focus {
  outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft);
}
.input[aria-invalid="true"] { border-color: var(--red-500); }

/* File pickers — the bare native control reads as an unfinished dev widget
   (tiny grey "Choose File" button, "no file chosen" in the browser's own
   font). Styling the button half to match the rest of the form and dimming
   the native filename text makes it look like a considered part of the UI. */
.input[type="file"] {
  padding: .5rem; cursor: pointer; color: var(--text-subtle); font-size: var(--fs-sm);
}
.input[type="file"]::file-selector-button {
  margin-right: .75rem; padding: .55rem 1rem;
  border: 1px solid transparent; border-radius: var(--r-sm);
  background: var(--primary-soft); color: var(--primary);
  font-weight: 700; font-size: var(--fs-sm); font-family: inherit;
  cursor: pointer;
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
@media (hover: hover) { .input[type="file"]::file-selector-button:hover { background: var(--primary); color: #fff; } }

/* A file picker with a live thumbnail (the employer logo field) — one
   bordered control holding the preview and the button together, instead of
   a separate floating avatar beside a second boxed input. */
.logo-upload {
  display: flex; align-items: center; gap: .75rem;
  padding: .4rem .75rem .4rem .4rem;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--r-md);
  transition: border-color var(--t-fast) var(--ease);
}
@media (hover: hover) { .logo-upload:hover { border-color: var(--border-strong); } }
.logo-upload:focus-within { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft); }
.logo-upload-preview {
  width: 2.75rem; height: 2.75rem; flex: none;
  border-radius: var(--r-sm); object-fit: cover;
  display: flex; align-items: center; justify-content: center;
  background: var(--primary-soft); color: var(--primary);
}
.logo-upload-input {
  flex: 1; min-width: 0; border: none; background: transparent; padding: 0;
  color: var(--text-subtle); font-size: var(--fs-sm); font-family: inherit; cursor: pointer;
}
.logo-upload-input:focus { outline: none; }
.logo-upload-input::file-selector-button {
  margin-right: .75rem; padding: .55rem 1rem;
  border: 1px solid transparent; border-radius: var(--r-sm);
  background: var(--primary-soft); color: var(--primary);
  font-weight: 700; font-size: var(--fs-sm); font-family: inherit;
  cursor: pointer;
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
@media (hover: hover) { .logo-upload-input::file-selector-button:hover { background: var(--primary); color: #fff; } }
.textarea { resize: vertical; min-height: 7rem; line-height: 1.6; }
.select {
  appearance: none; padding-right: 2.2rem; cursor: pointer;
  accent-color: var(--primary);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%235A6779' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right .7rem center;
}
:root[data-theme="dark"] .select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2398A6BA' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
}
/* The closed .select box is fully themed above, but the opened native
   options list defaults to plain OS chrome (white, system font, blue
   selection) that reads as unfinished next to the rest of the UI. Chromium
   respects background/color/padding on <option> even though it won't hand
   over the popup's shadow or corner radius — this is the ceiling of what a
   plain <select> can look like without rebuilding it as a custom listbox. */
.select option {
  background: var(--surface); color: var(--text);
  padding: .55rem .75rem; font-size: var(--fs-sm);
}
.select option:checked { background: var(--primary-soft); color: var(--primary); font-weight: 700; }
@media (hover: hover) { .select option:hover { background: var(--primary-soft); color: var(--primary); } }

/* ---------- Themed select (components/select.js) --------------------------
   The real fix for the note above: a page-painted listbox, so the OPEN
   list gets the site's own styling — green tick, green highlighted row,
   the same rounded/shadowed surface as every other menu — which a native
   <select> popup can't be given. The closed control below is deliberately
   pixel-matched to .input/.select so a form mixing the two never looks
   half-converted. */
.select-toggle {
  display: flex; align-items: center; justify-content: space-between; gap: .5rem;
  width: 100%; padding: .65rem .85rem; cursor: pointer; text-align: left;
  background: var(--surface); color: var(--text-subtle);
  border: 1px solid var(--border); border-radius: var(--r-md);
  font-family: inherit; font-size: var(--fs-base); font-weight: 500;
  transition: border-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
/* Once something is chosen it reads as real content, not placeholder text —
   a darker colour than the placeholder is enough to say that; it doesn't
   need to be bold as well; a normal <input> with real text in it isn't
   bold either. */
.select-toggle.has-value { color: var(--text); font-weight: 500; }
.select-toggle svg { color: var(--primary); flex: none; transition: transform var(--t-fast) var(--ease); }
@media (hover: hover) { .select-toggle:hover { border-color: var(--primary); } }
.select-toggle[aria-expanded="true"] {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 18%, transparent);
}
.select-toggle[aria-expanded="true"] svg { transform: rotate(180deg); }

/* Full width of the field rather than .menu's default right-anchored
   min-width, so it lines up with the control it belongs to. */
.select-menu { left: 0; right: 0; min-width: 0; max-height: 17rem; overflow-y: auto; }
.select-menu .menu-item { font-weight: 500; }
@media (hover: hover) { .select-menu .menu-item:hover { background: var(--primary-soft); color: var(--primary); } }
.select-menu .menu-item[aria-selected="true"] { color: var(--primary); font-weight: 700; }
/* Fixed-width tick column keeps every label on the same left edge whether
   or not the row is the selected one. */
.select-tick { display: inline-flex; width: 15px; flex: none; color: var(--primary); }
/* Set by validateThemedSelects() on a required dropdown left empty —
   the stand-in for the red outline reportValidity() gives a real field. */
.select-toggle.is-invalid { border-color: var(--red-500); }
.select-toggle.is-invalid svg { color: var(--red-500); }

.check { display: flex; align-items: flex-start; gap: .6rem; cursor: pointer; padding: .28rem 0; }
.check input { width: 1.05rem; height: 1.05rem; margin-top: .2rem; accent-color: var(--primary); cursor: pointer; flex: none; }
.check span { font-size: var(--fs-base); }
.check-count { margin-left: auto; font-size: var(--fs-xs); color: var(--text-subtle); }

input[type="range"] { width: 100%; accent-color: var(--primary); cursor: pointer; }

/* ---------- Tables ------------------------------------------------------- */
.table-wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--surface); }
table.table { width: 100%; border-collapse: collapse; min-width: 640px; }
.table th, .table td { padding: .85rem 1rem; text-align: left; border-bottom: 1px solid var(--border); }
.table th {
  font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .06em;
  color: var(--text-subtle); font-weight: 800; background: var(--bg-subtle);
}
.table tbody tr:last-child td { border-bottom: 0; }
@media (hover: hover) { .table tbody tr:hover { background: var(--surface-hover); } }

/* ---------- Status pills (application tracking) -------------------------- */
.status {
  display: inline-flex; align-items: center; gap: .4rem; padding: .28rem .7rem;
  border-radius: var(--r-full); font-size: var(--fs-xs); font-weight: 700;
}
.status::before { content: ""; width: .45rem; height: .45rem; border-radius: 50%; background: currentColor; }
/* One color for every status pill, on request — was previously color-coded
   per status (grey/blue/amber/violet/green/red); all six now share the
   same green as the toggle button's resting state. */
.status-applied, .status-under_review, .status-shortlisted,
.status-interview, .status-offered, .status-rejected {
  background: var(--green-50); color: var(--green-600);
}
:root[data-theme="dark"] .status-applied,
:root[data-theme="dark"] .status-under_review,
:root[data-theme="dark"] .status-shortlisted,
:root[data-theme="dark"] .status-interview,
:root[data-theme="dark"] .status-offered,
:root[data-theme="dark"] .status-rejected { color: #4ADE80; }

/* The clickable version of a status pill (applicants list) — one button
   that shows the current status as its own label, instead of a static
   status pill sitting next to a separately-labelled "Change status"
   button. Same colors as the plain, non-interactive .status above. */
.status-toggle {
  border: 0; cursor: pointer; font-family: inherit;
  transition: filter var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
@media (hover: hover) { .status-toggle:hover { filter: brightness(0.94); } }
@media (hover: hover) { :root[data-theme="dark"] .status-toggle:hover { filter: brightness(1.25); } }
.status-toggle:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.status-toggle svg { flex: none; transition: transform var(--t-fast) var(--ease); }
.status-toggle[aria-expanded="true"] svg { transform: rotate(180deg); }

/* ---------- Toast -------------------------------------------------------- */
.toast-root {
  position: fixed; z-index: 120; bottom: 1.25rem; right: 1.25rem;
  display: flex; flex-direction: column; gap: .6rem; pointer-events: none;
}
/* The chat launcher occupies the same corner. When one is on screen, lift
   the toast stack above it rather than letting the two overlap — the
   launcher only exists for accounts that actually have a conversation, so
   the default position above is still the common case. */
body:has(.cw-launcher) .toast-root { bottom: 5.75rem; }
.toast {
  display: flex; align-items: center; gap: .65rem;
  background: var(--ink-900); color: #fff; padding: .8rem 1.1rem;
  border-radius: var(--r-md); box-shadow: var(--shadow-lg); font-weight: 600;
  font-size: var(--fs-base); max-width: 22rem; pointer-events: auto;
  animation: toast-in .28s var(--ease-out);
}
:root[data-theme="dark"] .toast { background: var(--ink-700); border: 1px solid var(--border); }
.toast-success .toast-dot { color: #4ADE80; }
.toast-error .toast-dot { color: #FCA5A5; }
@keyframes toast-in { from { opacity: 0; transform: translateY(10px) scale(.96); } to { opacity: 1; transform: none; } }

/* ---------- Notification popup -------------------------------------------
 * Top-right, separate from the bottom-right action toasts above, so a
 * "new message" popup never gets confused with (or overlaps) "Profile
 * saved". See core/ui.js's showNotificationPopup(). */
.notif-popup-root {
  position: fixed; z-index: 130; top: calc(var(--nav-h, 4rem) + .75rem); right: 1.25rem;
  display: flex; flex-direction: column; gap: .6rem; max-width: 22rem; width: calc(100% - 2.5rem);
}
.notif-popup {
  display: flex; align-items: flex-start; gap: .7rem; cursor: pointer;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg); padding: .85rem 1rem; animation: notif-pop-in .3s var(--ease-out);
  transition: opacity .2s, transform .2s;
}
@media (hover: hover) { .notif-popup:hover { border-color: var(--primary-soft-br); } }
.notif-popup.is-leaving { opacity: 0; transform: translateX(8px); }
.notif-popup-ico {
  flex: none; width: 2.1rem; height: 2.1rem; border-radius: 50%;
  display: grid; place-items: center; background: var(--primary-soft); color: var(--primary);
}
.notif-popup-body { min-width: 0; flex: 1; }
.notif-popup-body b { display: block; font-size: var(--fs-sm); color: var(--text); line-height: 1.35; }
.notif-popup-body p { margin: .2rem 0 0; font-size: var(--fs-xs); color: var(--text-muted); line-height: 1.5;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.notif-popup-close {
  flex: none; border: 0; background: none; color: var(--text-subtle); cursor: pointer;
  padding: .2rem; border-radius: var(--r-sm); line-height: 0; margin: -.1rem -.2rem 0 0;
}
@media (hover: hover) { .notif-popup-close:hover { color: var(--text); background: var(--surface-hover); } }
@keyframes notif-pop-in { from { opacity: 0; transform: translateX(16px); } to { opacity: 1; transform: none; } }
@media (max-width: 640px) {
  .notif-popup-root { left: 1rem; right: 1rem; width: auto; max-width: none; top: calc(var(--nav-h, 4rem) + .5rem); }
}

/* ---------- Modal -------------------------------------------------------- */
.modal-backdrop {
  position: fixed; inset: 0; z-index: 130; background: rgba(7, 11, 18, .55);
  backdrop-filter: blur(4px); display: flex; align-items: center; justify-content: center;
  padding: 1.25rem; animation: fade .18s var(--ease);
}
.modal {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-xl);
  box-shadow: var(--shadow-xl); width: 100%; max-width: 32rem;
  max-height: 88vh; overflow-y: auto; animation: modal-in .26s var(--ease-out);
  /* A tall dialog scrolls with no visible track cutting into its rounded
     corner — site-wide rule in styles.css. */
}
.modal-lg { max-width: 46rem; }
/* Document preview dialog: the pages scroll inside their own panel, so the
   dialog itself never grows a second scrollbar. */
.modal-pdf { max-width: 56rem; overflow: hidden; display: flex; flex-direction: column; }
.modal-pdf .modal-body { padding-top: .75rem; }
.pdf-bar { display: flex; align-items: center; justify-content: space-between; gap: .75rem; flex-wrap: wrap; margin-bottom: .75rem; }
.pdf-scroll {
  overflow-y: auto; background: var(--bg-subtle); border-radius: var(--r-md); padding: .75rem;
  scrollbar-width: thin; scrollbar-color: var(--border-strong, #c4ccd6) transparent;
}
.pdf-scroll::-webkit-scrollbar { width: 5px; }
.pdf-scroll::-webkit-scrollbar-track { background: transparent; }
.pdf-scroll::-webkit-scrollbar-thumb { background: var(--border-strong, #c4ccd6); border-radius: 999px; }
.pdf-page { display: block; width: 100%; height: auto; margin: 0 auto .75rem; background: #fff; box-shadow: 0 1px 6px rgba(15, 23, 42, .12); border-radius: 2px; }
.pdf-page:last-child { margin-bottom: 0; }
.modal-head { display: flex; align-items: flex-start; gap: 1rem; padding: 1.4rem 1.5rem 0; }
.modal-head h3 { flex: 1; }
.modal-body { padding: 1.1rem 1.5rem; }
.modal-foot { display: flex; gap: .6rem; justify-content: flex-end; padding: 0 1.5rem 1.5rem; flex-wrap: wrap; }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes modal-in { from { opacity: 0; transform: translateY(14px) scale(.97); } to { opacity: 1; transform: none; } }

/* ---------- Message thread (components/chatWidget.js) --------------------
 * A real chat surface, not a form field with bubbles bolted on: a tinted
 * scroll panel to separate the conversation from the modal chrome, avatars
 * top-aligned with the first line of their bubble instead of pinned to the
 * bubble's bottom edge, one flattened corner per side so a bubble visually
 * "points" at its own avatar, and a composer that reads as its own docked
 * bar instead of just another form field floating in the body padding. */
.msg-panel {
  background: var(--bg-subtle); border: 1px solid var(--border); border-radius: var(--r-lg);
  padding: 1rem; max-height: 50vh; overflow-y: auto;
}
.msg-row { display: flex; gap: .6rem; align-items: flex-start; margin-bottom: 1rem; }
.msg-row:last-child { margin-bottom: 0; }
.msg-row.is-mine { flex-direction: row-reverse; }
.msg-avatar { flex: none; width: 2rem; height: 2rem; border-radius: 50%; object-fit: cover; margin-top: 1.35rem; }
.msg-col { min-width: 0; max-width: 78%; display: flex; flex-direction: column; }
.msg-row.is-mine .msg-col { align-items: flex-end; }
.msg-meta { font-size: var(--fs-xs); color: var(--text-subtle); margin-bottom: .3rem; padding-inline: .2rem; }
.msg-bubble {
  padding: .6rem .9rem; border-radius: var(--r-lg); white-space: pre-wrap; word-break: break-word;
  font-size: var(--fs-sm); line-height: 1.5; box-shadow: var(--shadow-sm);
}
.msg-row:not(.is-mine) .msg-bubble { background: var(--surface); color: var(--text); border-bottom-left-radius: var(--r-xs); }
.msg-row.is-mine .msg-bubble { background: var(--primary); color: var(--on-primary); border-bottom-right-radius: var(--r-xs); }

.msg-composer { display: flex; gap: .6rem; align-items: flex-end; margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--border); }
.msg-composer .textarea { min-height: 2.75rem; resize: none; }
.msg-locked {
  display: flex; gap: .6rem; align-items: center; margin-top: 1rem; padding: .9rem 1.1rem;
  background: var(--bg-subtle); border: 1px solid var(--border); border-radius: var(--r-md);
  color: var(--text-muted); font-size: var(--fs-sm);
}

/* ---------- Misc --------------------------------------------------------- */
.divider { height: 1px; background: var(--border); margin-block: 1.25rem; }
.empty {
  text-align: center; padding: 3.5rem 1.5rem; border: 1px dashed var(--border);
  border-radius: var(--r-lg); background: var(--bg-subtle);
}
.empty-icon {
  width: 3.5rem; height: 3.5rem; margin: 0 auto 1rem; display: grid; place-items: center;
  border-radius: var(--r-full); background: var(--surface); border: 1px solid var(--border); color: var(--text-subtle);
}
.empty h3 { font-size: var(--fs-lg); margin-bottom: .4rem; }
.empty p { color: var(--text-muted); max-width: 26rem; margin-inline: auto; }

.avatar {
  flex: none; display: grid; place-items: center; border-radius: var(--r-md);
  background: var(--primary-soft); color: var(--primary);
  font-weight: 800; letter-spacing: -.02em; border: 1px solid var(--primary-soft-br);
}
.avatar-sm { width: 2rem; height: 2rem; font-size: var(--fs-xs); }
.avatar-md { width: 3rem; height: 3rem; font-size: var(--fs-base); }
.avatar-lg { width: 4.5rem; height: 4.5rem; font-size: var(--fs-xl); border-radius: var(--r-lg); }
.avatar-round { border-radius: var(--r-full); }

/* ---------- Photo uploader (profile page) --------------------------------- */
.photo-uploader { display: flex; gap: 1.1rem; align-items: center; }
@media (max-width: 480px) {
  /* Avatar above the text, not beside it. In a card on a 375px screen the
     two-column row left the hint about 150px wide and pushed Change and
     Remove onto separate lines each; stacked, the text gets the full width
     and both buttons fit on one row. */
  .photo-uploader { flex-direction: column; align-items: flex-start; gap: .85rem; }
}
.photo-avatar-btn {
  position: relative; flex: none; padding: 0; border: 0; background: none; cursor: pointer;
  border-radius: var(--r-full); transition: transform var(--t-fast) var(--ease);
}
@media (hover: hover) { .photo-avatar-btn:hover { transform: scale(1.04); } }
.photo-avatar-btn:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.photo-avatar-btn .avatar-lg { border: 3px solid var(--surface); box-shadow: 0 0 0 1px var(--border); }
.photo-avatar-btn img.avatar-lg-img {
  width: 4.5rem; height: 4.5rem; border-radius: var(--r-full); object-fit: cover;
  border: 3px solid var(--surface); box-shadow: 0 0 0 1px var(--border); display: block;
}

/* A real photo OF A PERSON crops from the top, never the middle. A head
   sits in the upper part of almost any portrait, so `object-fit: cover`
   with its default centre position is exactly what slices faces off —
   which is what was happening to the profile photo here.
   Company logos deliberately keep the centred crop: a logo's content is
   centred, not top-weighted, so anchoring one to the top would be the
   wrong call. That's why this is an opt-in class rather than a blanket
   rule on every img.avatar — plenty of those are logos. */
.avatar-photo, .avatar-lg-img, .msg-avatar { object-position: center top; }
.photo-badge {
  position: absolute; bottom: -.15rem; right: -.15rem; width: 1.6rem; height: 1.6rem;
  display: grid; place-items: center; border-radius: var(--r-full);
  background: var(--primary); color: #fff; border: 2px solid var(--surface);
}

/* ---------- Profile photo cropper --------------------------------------- */
/* The square framing stage. overflow:hidden is what does the cropping on
   screen; the canvas in photoCropper.js repeats the same maths to cut the
   file that actually gets uploaded. */
.crop-stage {
  position: relative; overflow: hidden; margin: 0 auto;
  border-radius: var(--r-lg); background: var(--bg-sunken);
  cursor: grab; touch-action: none; user-select: none;
  max-width: 100%;
}
.crop-stage.is-dragging { cursor: grabbing; }
/* touch-action:none above is required, not cosmetic: without it a drag on
   a phone scrolls the page instead of moving the photo, and pointermove
   stops arriving once the browser claims the gesture. */
/* max-width/height:none is load-bearing. The stylesheet has a global
   `img { max-width: 100% }`, which clamped the sized-up image back to the
   stage width - so a 900x500 photo rendered as a squashed 260x260 square
   with dead space beside it instead of covering the frame. The cropper
   sets exact pixel dimensions on purpose and has to opt out. */
.crop-img {
  position: absolute; top: 0; left: 0; transform-origin: 0 0; display: block;
  max-width: none; max-height: none;
}
/* The circle people will actually see, drawn over the square frame. The
   huge spread shade dims everything outside it, so the visible result is
   obvious while the whole photo stays visible for positioning. */
.crop-ring {
  position: absolute; inset: 0; border-radius: var(--r-lg); pointer-events: none;
}
.crop-ring::after {
  content: ''; position: absolute; inset: 50% auto auto 50%;
  width: 100%; height: 100%; transform: translate(-50%, -50%);
  border-radius: var(--r-full);
  box-shadow: 0 0 0 9999px rgba(7, 11, 18, .45);
  border: 2px solid rgba(255, 255, 255, .9);
}
.crop-zoom { width: 100%; accent-color: var(--primary); }
@media (pointer: coarse) {
  /* A 20px-tall range input is unusable with a thumb. */
  .crop-zoom { height: 2.5rem; }
}
.link-btn {
  border: 0; background: none; padding: 0; cursor: pointer; color: var(--primary);
  font-weight: 700; font-size: var(--fs-sm);
}
@media (hover: hover) { .link-btn:hover { text-decoration: underline; } }

/* Onboarding's "Upload your resume" drop target — the one place in the app
   that accepts drag-and-drop, so this is intentionally its own oversized,
   unmissable target rather than a small file-picker button like profile.js's
   "Change file" uses. */
.dropzone {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  padding: 2.5rem 1.5rem; border: 2px dashed var(--border); border-radius: var(--r-lg);
  cursor: pointer; transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.dropzone-icon {
  display: grid; place-items: center; width: 3.25rem; height: 3.25rem; border-radius: var(--r-full);
  background: var(--primary-soft); color: var(--primary);
}
.dropzone:hover, .dropzone:focus-visible { border-color: var(--primary); background: var(--primary-soft); outline: none; }
.dropzone.is-dragover { border-color: var(--primary); background: var(--primary-soft); }
.dropzone.is-busy { cursor: wait; opacity: .75; }
.dropzone.is-done { border-color: var(--green-500); border-style: solid; }
.dropzone.is-done .dropzone-icon { background: var(--green-50); color: var(--green-600); }

.progress { height: .5rem; background: var(--bg-sunken); border-radius: var(--r-full); overflow: hidden; }
.progress-bar { height: 100%; background: var(--primary); border-radius: var(--r-full); transition: width var(--t-slow) var(--ease-out); }
.progress-bar.warn { background: var(--accent); }
.progress-bar.bad { background: var(--red-500); }

.skeleton {
  background: linear-gradient(90deg, var(--bg-subtle) 25%, var(--surface-hover) 37%, var(--bg-subtle) 63%);
  background-size: 400% 100%; animation: shimmer 1.3s ease infinite; border-radius: var(--r-sm);
}
@keyframes shimmer { from { background-position: 100% 0; } to { background-position: -100% 0; } }


/* ---------- Floating chat widget -----------------------------------------
 * The round launcher pinned bottom-right and the panel it opens — the
 * pattern every site with support/inbox chat uses, so a new message is
 * visible from any page instead of only from the application row it
 * belongs to. See components/chatWidget.js for when it renders at all
 * (never for an account with no conversation).
 *
 * Sits below the toast stack (120) and the modal overlay (130): a toast
 * confirming a send, and any modal, must both be readable over an open
 * panel. */
.cw-launcher {
  position: fixed; z-index: 115; bottom: 1.25rem; right: 1.25rem;
  width: 3.5rem; height: 3.5rem; border-radius: 50%; border: none;
  display: grid; place-items: center; cursor: pointer;
  background: var(--primary); color: var(--on-primary);
  box-shadow: 0 6px 20px rgba(7, 11, 18, .22);
  transition: transform var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease),
              background var(--t-fast) var(--ease);
}
@media (hover: hover) { .cw-launcher:hover { transform: translateY(-2px) scale(1.04); box-shadow: 0 10px 26px rgba(7, 11, 18, .28); } }
.cw-launcher:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; }
/* A quiet pulse only while something is genuinely unread — it stops the
   moment the conversation is opened, so it never becomes wallpaper. */
.cw-launcher.has-unread { animation: cw-pulse 2.4s var(--ease) infinite; }
@keyframes cw-pulse {
  0%, 100% { box-shadow: 0 6px 20px rgba(7, 11, 18, .22), 0 0 0 0 var(--primary-soft); }
  50%      { box-shadow: 0 6px 20px rgba(7, 11, 18, .22), 0 0 0 .55rem transparent; }
}
@media (prefers-reduced-motion: reduce) {
  .cw-launcher, .cw-launcher.has-unread { animation: none; transition: none; }
  @media (hover: hover) { .cw-launcher:hover { transform: none; } }
}
.cw-badge {
  position: absolute; top: -.15rem; right: -.15rem; min-width: 1.3rem; height: 1.3rem;
  padding: 0 .3rem; border-radius: var(--r-full); background: var(--red-500);
  color: #fff; font-size: .72rem; font-weight: 800; line-height: 1.3rem; text-align: center;
  border: 2px solid var(--bg);
}

.cw-panel {
  position: fixed; z-index: 115; bottom: 5.5rem; right: 1.25rem;
  width: min(23rem, calc(100vw - 2.5rem)); max-height: min(32rem, calc(100vh - 8rem));
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg);
  box-shadow: 0 16px 44px rgba(7, 11, 18, .26);
  animation: cw-rise var(--t-fast) var(--ease);
}
@keyframes cw-rise { from { opacity: 0; transform: translateY(.6rem); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .cw-panel { animation: none; } }

.cw-head {
  display: flex; align-items: center; gap: .6rem; flex: none;
  padding: .8rem .9rem; border-bottom: 1px solid var(--border); background: var(--bg-subtle);
}
.cw-head-title { min-width: 0; flex: 1; display: flex; flex-direction: column; }
.cw-head-title b { font-size: var(--fs-sm); line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cw-head-title small { font-size: var(--fs-xs); color: var(--text-subtle); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cw-icon-btn {
  flex: none; width: 2rem; height: 2rem; border-radius: var(--r-md); border: none; cursor: pointer;
  display: grid; place-items: center; background: transparent; color: var(--text-muted);
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
@media (hover: hover) { .cw-icon-btn:hover { background: var(--surface); color: var(--text); } }
.cw-icon-btn:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

.cw-body { flex: 1; min-height: 0; overflow-y: auto; padding: .75rem; }
.cw-list { padding: .4rem; }

.cw-thread {
  display: flex; align-items: flex-start; gap: .65rem; width: 100%; text-align: left;
  padding: .65rem; border: none; background: transparent; border-radius: var(--r-md);
  cursor: pointer; position: relative;
  transition: background var(--t-fast) var(--ease);
}
@media (hover: hover) { .cw-thread:hover { background: var(--bg-subtle); } }
.cw-thread:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.cw-thread-body { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: .1rem; }
.cw-thread-top { display: flex; align-items: baseline; gap: .5rem; }
.cw-thread-top b { font-size: var(--fs-sm); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cw-thread-top small { margin-left: auto; flex: none; font-size: var(--fs-xs); color: var(--text-subtle); }
.cw-thread-sub, .cw-thread-last {
  font-size: var(--fs-xs); color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cw-thread-sub { color: var(--text-subtle); }
.cw-thread.is-unread .cw-thread-last { color: var(--text); font-weight: 700; }
.cw-dot { flex: none; width: .5rem; height: .5rem; border-radius: 50%; background: var(--primary); margin-top: .55rem; }

/* Inside the widget the chat has the panel's own chrome around it already,
   so it drops the modal's card look and stretches to fill instead. */
.cw-body .msg-col { max-width: 85%; }

/* ---------- Chat composer -------------------------------------------------
 * Scoped to `.cw-panel >`, not `.cw-body`. The composer and the locked
 * notice are SIBLINGS of the scrolling body, not children of it, so the
 * `.cw-body .msg-composer` rules that used to live here never matched
 * anything - which left the composer wearing the modal's margin-top with no
 * horizontal or bottom padding at all. That is why the textarea sat flush
 * against the panel walls and the send button hung over the rounded corner.
 *
 * Padding on the form itself (not margins on its children) is what keeps
 * the textarea and the button inset by the same amount on every side. */
.cw-panel > .msg-composer {
  flex: none; display: flex; align-items: flex-end; gap: .5rem;
  margin: 0; padding: .75rem; border-top: 1px solid var(--border);
}
.cw-panel > .msg-composer .textarea {
  min-height: 2.5rem; max-height: 7rem; font-size: var(--fs-sm); resize: none;
  /* A textarea is inline-block by default, so its parent reserves a few
     pixels of baseline gap underneath it - which left the send button
     sitting ~7px lower than the field it is meant to line up with. */
  display: block;
}
/* Square, and exactly as tall as the collapsed textarea, so the two bottom
   edges line up instead of the button floating a few pixels low. */
.cw-panel > .msg-composer .btn {
  flex: none; width: 2.5rem; height: 2.5rem; padding: 0;
  display: grid; place-items: center;
}
.cw-panel > .msg-locked {
  flex: none; margin: 0; padding: .75rem; font-size: var(--fs-xs);
  border-radius: 0; border: 0; border-top: 1px solid var(--border);
}

@media (max-width: 480px) {
  .cw-panel {
    right: .75rem; left: .75rem; bottom: 5rem;
    width: auto; max-height: calc(100vh - 7rem);
  }
  .cw-launcher { bottom: 1rem; right: 1rem; width: 3.2rem; height: 3.2rem; }
}

/* ---------- Chat widget: panel internals ---------------------------------
 * Added with the conversation-based rewrite: search, grouping, presence,
 * receipts, typing, report form and the loading/empty/error states. All of
 * it reuses the existing tokens and the .msg-* bubble rules above, so the
 * panel reads as the same product as the rest of the site. */
.cw-search { flex: none; display: flex; align-items: center; gap: .5rem; padding: .55rem .8rem;
  border-bottom: 1px solid var(--border); color: var(--text-subtle); }
.cw-search input { flex: 1; min-width: 0; border: none; background: transparent; color: var(--text);
  font-size: var(--fs-sm); font-family: inherit; }
.cw-search input:focus { outline: none; }
/* The input above drops its outline and has no border or background, and
   nothing on the bar replaced it - so focusing the chat search showed no
   change at all. The bar already has a bottom rule; on focus it becomes a
   2px --primary line and the search icon takes the same colour (5.47:1 on
   the panel), which reads as "this is where typing goes" without adding a
   box inside a strip that is meant to stay flat. */
.cw-search:focus-within { color: var(--primary); box-shadow: inset 0 -2px 0 var(--primary); }
@media (pointer: coarse) {
  /* This is a bare <input>, so the site-wide 16px touch rule (which targets
     .input/.select/.textarea) never reached it: at --fs-sm it was 13px, and
     iOS Safari zooms the whole page when a field under 16px takes focus. */
  .cw-search input { font-size: 16px; }
}

.cw-group { padding: .6rem .65rem .3rem; font-size: var(--fs-xs); font-weight: 700;
  color: var(--text-subtle); text-transform: none; }

.cw-avatar-wrap { position: relative; flex: none; display: flex; }
.cw-online { position: absolute; right: -1px; bottom: -1px; width: .6rem; height: .6rem;
  border-radius: 50%; background: var(--green-500); border: 2px solid var(--surface); }

.cw-count { flex: none; min-width: 1.25rem; height: 1.25rem; padding: 0 .3rem; border-radius: var(--r-full);
  background: var(--primary); color: var(--on-primary); font-size: .7rem; font-weight: 800;
  line-height: 1.25rem; text-align: center; margin-top: .35rem; }

.cw-state { display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .5rem; padding: 2.5rem 1.25rem; text-align: center; color: var(--text-muted);
  font-size: var(--fs-sm); line-height: 1.55; }
.cw-state b { color: var(--text); font-size: var(--fs-base); }
.cw-empty-mark { display: grid; place-items: center; width: 3rem; height: 3rem; margin-bottom: .2rem;
  border-radius: 50%; background: var(--primary-soft); color: var(--primary); }


.cw-thread-body { display: flex; flex-direction: column; }

/* ---------- Chat thread rhythm -------------------------------------------
 * A turn in the conversation is a name + time line followed by one or more
 * bubbles. The gap between turns is bigger than the gap between bubbles
 * inside one, which is what makes a thread scannable rather than an even
 * column of loose boxes. */
.cw-body .msg-row { margin-bottom: .85rem; }
.cw-body .msg-row.is-grouped { margin-bottom: .2rem; }
.cw-body .msg-row:last-child { margin-bottom: 0; }
.cw-body .msg-meta {
  display: flex; align-items: center; gap: .3rem; flex-wrap: nowrap;
  margin-bottom: .25rem; padding-inline: .15rem; white-space: nowrap;
}
.cw-body .msg-meta b { font-weight: 700; color: var(--text-muted); }
/* Squarer corners on the inner bubbles of a run, so a group reads as one
   block of speech instead of separate, identical pills. */
.cw-body .msg-row.is-grouped:not(.is-mine) .msg-bubble { border-top-left-radius: var(--r-xs); }
.cw-body .msg-row.is-grouped.is-mine .msg-bubble { border-top-right-radius: var(--r-xs); }
/* The receipt for a grouped outgoing message, which has no meta line to
   carry it. */
.cw-tail-receipt { display: block; margin-top: .15rem; padding-inline: .15rem;
  color: var(--text-subtle); line-height: 1; }
.msg-row.is-mine .cw-tail-receipt { text-align: right; }
.cw-body .msg-row.is-pending { opacity: .6; }
.cw-body .msg-row.is-failed .msg-bubble { background: var(--red-50); color: var(--red-600); }
.cw-receipt { display: inline-flex; margin-left: .3rem; vertical-align: -1px; }
.cw-receipt svg + svg { margin-left: -6px; }
.cw-retry { display: block; margin-top: .25rem; border: none; background: none; padding: 0;
  color: var(--red-500); font-size: var(--fs-xs); font-weight: 700; cursor: pointer; font-family: inherit; }
/* Report now lives inside the meta line, so it costs no layout of its own.
   It used to be a block at opacity:0 underneath the bubble - invisible but
   still reserving a line, and only under INCOMING messages, which is what
   made the two sides of the thread fail to line up. */
.cw-report-msg {
  border: none; background: none; padding: 0; margin-left: .1rem;
  color: var(--text-subtle); cursor: pointer; font-family: inherit;
  display: inline-flex; vertical-align: -1px; opacity: 0;
  transition: opacity var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.msg-row:hover .cw-report-msg, .cw-report-msg:focus-visible { opacity: 1; }
@media (hover: hover) { .cw-report-msg:hover { color: var(--red-500); } }

.cw-typing { display: flex; gap: .25rem; padding: .5rem .2rem; }
.cw-typing span { width: .4rem; height: .4rem; border-radius: 50%; background: var(--text-subtle);
  animation: cw-blink 1.2s infinite; }
.cw-typing span:nth-child(2) { animation-delay: .2s; }
.cw-typing span:nth-child(3) { animation-delay: .4s; }
@keyframes cw-blink { 0%, 60%, 100% { opacity: .25; } 30% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .cw-typing span { animation: none; opacity: .5; } }

.cw-report { flex: none; display: flex; flex-direction: column; gap: .5rem; padding: .75rem;
  border-top: 1px solid var(--border); background: var(--bg-subtle); }
.cw-report .input, .cw-report .textarea { font-size: var(--fs-sm); }
.cw-report-actions { display: flex; justify-content: flex-end; gap: .5rem; }

.cw-reasons { border: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: .35rem; }
.cw-reasons legend { padding: 0; margin-bottom: .45rem; font-size: var(--fs-xs); color: var(--text-muted); }
.cw-reason { position: relative; }
.cw-reason input { position: absolute; opacity: 0; width: 0; height: 0; }
.cw-reason span { display: inline-block; padding: .3rem .6rem; border: 1px solid var(--border);
  border-radius: var(--r-full); font-size: var(--fs-xs); color: var(--text-muted);
  cursor: pointer; transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease),
  color var(--t-fast) var(--ease); }
@media (hover: hover) { .cw-reason:hover span { border-color: var(--primary-soft-br); color: var(--primary); } }
.cw-reason input:checked + span { background: var(--primary-soft); border-color: var(--primary); color: var(--primary); font-weight: 700; }
.cw-reason input:focus-visible + span { outline: 2px solid var(--focus); outline-offset: 2px; }

/* The one message a report names, inside the admin moderation modal. */
.msg-row.is-flagged { background: var(--red-50); border-radius: var(--r-md); padding: .5rem; margin-inline: -.5rem; }
.msg-row.is-flagged .msg-bubble { border: 1px solid var(--red-500); }

/* ---------- Success story writing ----------------------------------------
 * The student-facing side of the review workflow: the four-step explainer
 * shown before an internship is completed, and the editor after. */
.story-steps { display: grid; gap: .75rem; grid-template-columns: repeat(auto-fit, minmax(min(11rem, 100%), 1fr)); margin-top: 1rem; }
.story-step { position: relative; display: flex; flex-direction: column; align-items: center; gap: .3rem;
  padding: 1rem .75rem; border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--surface); }
.story-step .ico { display: grid; place-items: center; width: 2.2rem; height: 2.2rem; border-radius: 50%;
  background: var(--primary-soft); color: var(--primary); }
.story-step b { font-size: var(--fs-sm); }
.story-step small { font-size: var(--fs-xs); color: var(--text-muted); text-align: center; line-height: 1.45; }
.story-step-n { position: absolute; top: .5rem; left: .6rem; font-size: var(--fs-xs); font-weight: 800; color: var(--text-subtle); }

.story-quote { font-size: var(--fs-sm); line-height: 1.6; font-style: italic; color: var(--text); margin: 0; }

.rating-row { display: flex; gap: .25rem; }
.rating-star input { position: absolute; opacity: 0; width: 0; height: 0; }
.rating-star span { display: grid; place-items: center; width: 2.2rem; height: 2.2rem; border-radius: var(--r-md);
  color: var(--text-subtle); cursor: pointer; transition: color var(--t-fast) var(--ease), background var(--t-fast) var(--ease); }
@media (hover: hover) { .rating-star:hover span { color: var(--amber-500); background: var(--bg-subtle); } }
.rating-star input:checked + span { color: var(--amber-500); }
.rating-star input:focus-visible + span { outline: 2px solid var(--focus); outline-offset: 2px; }

/* The employer header's photo control, now sitting under the company name
   rather than beside it. A hairline above separates it from the identity
   lines without needing a card of its own. */

/* ---------- Chat: Help view -----------------------------------------------
 * A fixed list of questions the widget answers itself, so most people never
 * need to open a support thread at all. Styled as rows rather than chat
 * bubbles, because a list of questions is a menu, not a conversation. */
.cw-help-entry {
  flex: none; display: flex; align-items: center; gap: .6rem; width: 100%;
  padding: .7rem .8rem; border: 0; border-top: 1px solid var(--border);
  background: var(--bg-subtle); cursor: pointer; text-align: left;
  color: var(--text); font-family: inherit;
  transition: background var(--t-fast) var(--ease);
}
@media (hover: hover) { .cw-help-entry:hover { background: var(--primary-soft); } }
.cw-help-entry > svg:first-child { flex: none; color: var(--primary); }
.cw-help-entry > svg:last-child { flex: none; margin-left: auto; color: var(--text-subtle); }
.cw-help-entry span { display: flex; flex-direction: column; min-width: 0; }
.cw-help-entry b { font-size: var(--fs-sm); line-height: 1.3; }
.cw-help-entry small { font-size: var(--fs-xs); color: var(--text-muted); }

.cw-help-list { padding: .5rem; }
.cw-help-intro { font-size: var(--fs-xs); color: var(--text-muted); line-height: 1.5;
  margin: .2rem .4rem .6rem; }
.cw-help-topic {
  display: flex; align-items: center; gap: .6rem; width: 100%; text-align: left;
  padding: .65rem .7rem; margin-bottom: .3rem; border: 1px solid var(--border);
  border-radius: var(--r-md); background: var(--surface); cursor: pointer;
  font-family: inherit; font-size: var(--fs-sm); color: var(--text);
  transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
@media (hover: hover) { .cw-help-topic:hover { border-color: var(--primary); background: var(--primary-soft); color: var(--primary); } }
.cw-help-topic:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.cw-help-topic span { flex: 1; min-width: 0; }
.cw-help-topic svg { flex: none; color: var(--text-subtle); }

.cw-help-link {
  display: inline-flex; align-items: center; gap: .35rem; margin-top: .2rem;
  padding: .4rem .7rem; border-radius: var(--r-full); background: var(--primary-soft);
  color: var(--primary); font-size: var(--fs-xs); font-weight: 700;
}
@media (hover: hover) { .cw-help-link:hover { text-decoration: none; background: var(--primary); color: var(--on-primary); } }

.cw-help-foot {
  flex: none; display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
  padding: .75rem; border-top: 1px solid var(--border); background: var(--bg-subtle);
  font-size: var(--fs-xs); color: var(--text-muted);
}
.cw-help-foot span { flex: 1; min-width: 6rem; }

/* ---------- Admin analytics chart ---------------------------------------- */

.admin-growth-card { overflow: hidden; box-shadow: var(--shadow-sm); }
.admin-growth-head { display: flex; justify-content: space-between; align-items: flex-start; flex-wrap: wrap; gap: 1.25rem; }

.admin-kpi-row { display: flex; gap: .7rem; flex-wrap: wrap; }
.admin-kpi {
  display: flex; align-items: center; gap: .65rem; padding: .55rem .9rem .55rem .6rem;
  border-radius: var(--r-lg); border: 1px solid var(--border); background: var(--bg-subtle);
  min-width: 9.5rem;
}
.admin-kpi b { font-size: var(--fs-xl); line-height: 1.1; letter-spacing: -.02em; }
.admin-kpi-ico { width: 2.15rem; height: 2.15rem; border-radius: var(--r-md); display: grid; place-items: center; flex: none; }
.admin-kpi-a .admin-kpi-ico { background: var(--primary-soft); color: var(--primary); }
.admin-kpi-b .admin-kpi-ico { background: var(--blue-50); color: var(--blue-500); }

.admin-chart-wrap {
  width: 100%; border: 1px solid var(--border); border-radius: var(--r-lg);
  padding: 1.1rem .6rem .3rem; position: relative;
  background: linear-gradient(180deg, var(--primary-soft) 0%, var(--bg-subtle) 45%, transparent 85%);
}
.admin-chart { width: 100%; height: auto; display: block; overflow: visible; cursor: crosshair; }
/* ---------- Chart tooltip (components/chartTooltip.js) --------------------
 * Hover or tap anywhere over one of our hand-drawn SVG charts to see the
 * exact value at that point - the vertical line marks which x it snapped
 * to, the pill above it carries the real number(s). Shared by the admin
 * "Platform growth" chart and the employer "Performance" chart. */
.chart-hover-line { stroke: var(--text-subtle); stroke-width: 1; stroke-dasharray: 3 3; pointer-events: none; }
.chart-tooltip {
  position: absolute; top: 0; transform: translate(-50%, -100%); margin-top: -.5rem;
  background: var(--text); color: var(--bg); border-radius: var(--r-md);
  padding: .45rem .65rem; font-size: var(--fs-xs); font-weight: 700; white-space: nowrap;
  pointer-events: none; box-shadow: var(--shadow-md); z-index: 5;
}
.chart-tooltip b { display: block; font-size: var(--fs-xs); font-weight: 800; margin-bottom: .2rem; color: var(--bg); }
.chart-tooltip .ct-row { display: flex; align-items: center; gap: .3rem; font-weight: 600; }
.chart-tooltip .admin-chart-swatch { width: .5rem; height: .5rem; }
.admin-chart-grid { stroke: var(--border); stroke-width: 1; stroke-dasharray: 3 4; }
.admin-chart-axis { font-size: 9.5px; fill: var(--text-subtle); font-family: inherit; }
.admin-chart-line { stroke-width: 2.5; stroke-linejoin: round; stroke-linecap: round; }
.admin-chart-line-a { stroke: var(--primary); }
.admin-chart-line-b { stroke: var(--blue-500); }
.admin-chart-dot {
  stroke: var(--surface); stroke-width: 1.5; transition: transform .15s ease;
  transform-box: fill-box; transform-origin: center;
}
.admin-chart-dot:hover { transform: scale(1.7); }
.admin-chart-dot-a { fill: var(--primary); }
.admin-chart-dot-b { fill: var(--blue-500); }
.admin-chart-swatch {
  display: inline-block; width: .6rem; height: .6rem; border-radius: var(--r-full);
  margin-right: .3rem; vertical-align: middle;
}
.admin-chart-swatch-a { background: var(--primary); }
.admin-chart-swatch-b { background: var(--blue-500); }
.admin-chart-empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 2.5rem 1rem; color: var(--text-subtle); text-align: center;
}

.admin-growth-foot {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr)); gap: .75rem;
  margin-top: 1.1rem; padding-top: 1.1rem; border-top: 1px solid var(--border);
}
.admin-mini-stat {
  padding: .7rem .9rem; border-radius: var(--r-md); background: var(--bg-subtle);
  border: 1px solid var(--border);
}
.admin-mini-stat b { display: block; font-size: var(--fs-xl); letter-spacing: -.02em; }
.admin-mini-stat span { font-size: var(--fs-xs); color: var(--text-muted); }
:root[data-theme="dark"] .admin-mini-stat { background: var(--surface-raised); }

.admin-change {
  display: inline-flex; align-items: center; gap: .15rem; font-size: var(--fs-xs);
  font-weight: 700; padding: .1rem .4rem; border-radius: var(--r-full);
}
.admin-change-up { background: var(--green-50); color: var(--green-600); }
.admin-change-down { background: var(--red-50); color: var(--red-500); }
:root[data-theme="dark"] .admin-change-up { color: #4ADE80; }
:root[data-theme="dark"] .admin-change-down { color: #FCA5A5; }
:root[data-theme="dark"] .admin-kpi { background: var(--surface-raised); }

/* ---------- Admin widget grid: donuts + bar list -------------------------- */

.admin-widget-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(15.5rem, 1fr)); gap: 1rem; }
.admin-widget { display: flex; flex-direction: column; gap: .8rem; box-shadow: var(--shadow-sm); }
.admin-widget-body { display: flex; align-items: center; gap: 1.1rem; flex-wrap: wrap; }
.admin-donut { flex: none; }
.admin-donut-total { font-size: 21px; font-weight: 800; fill: var(--text); font-family: inherit; letter-spacing: -.02em; }
.admin-donut-total-label { font-size: 8.5px; fill: var(--text-subtle); font-family: inherit; letter-spacing: .06em; }
.admin-donut-empty {
  border-radius: 50%; border-style: dashed; border-color: var(--border); display: grid;
  place-items: center; color: var(--text-subtle); flex: none;
}
.admin-legend { display: flex; flex-direction: column; gap: .45rem; flex: 1 1 8rem; min-width: 0; }
.admin-legend-row { display: flex; align-items: center; gap: .45rem; font-size: var(--fs-xs); }
.admin-legend-dot { width: .55rem; height: .55rem; border-radius: 50%; flex: none; }
.admin-legend-label { color: var(--text-muted); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.admin-legend-value { font-weight: 700; }

.admin-bar-list { display: flex; flex-direction: column; gap: .6rem; }
.admin-bar-row { display: grid; grid-template-columns: 6.5rem 1fr 1.7rem; align-items: center; gap: .6rem; }
.admin-bar-label { font-size: var(--fs-xs); color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.admin-bar-track { height: .5rem; border-radius: var(--r-full); background: var(--bg-subtle); overflow: hidden; }
.admin-bar-fill { height: 100%; border-radius: var(--r-full); background: var(--primary); }
.admin-bar-value { font-size: var(--fs-xs); font-weight: 700; text-align: right; }



/* "Continue with Google" — same size as the form's main button, Google logo on the left of the text */
.btn-google { --btn-bg: #fff; --btn-fg: #1f1f1f; --btn-br: #dadce0; gap: .75rem; font-weight: 600; }
.btn-google .g-logo { width: 20px; height: 20px; flex: none; }
@media (hover: hover) { .btn-google:hover { --btn-bg: #f8f9fa; --btn-br: #c6c9ce; --btn-fg: #1f1f1f; } }
.btn-google:focus-visible { outline: 3px solid rgba(66, 133, 244, .45); outline-offset: 2px; }

/* ===================================================== About us (/about-us) */
.au-hero { position: relative; overflow: hidden; padding-block: clamp(3rem, 7vw, 5.5rem) clamp(2.5rem, 6vw, 4.5rem);
  background: radial-gradient(60rem 30rem at 85% -10%, var(--teal-50), transparent 60%), radial-gradient(40rem 22rem at -10% 110%, var(--amber-100), transparent 60%); }
.au-hero-grid { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr); gap: clamp(2rem, 5vw, 4rem); align-items: center; }
.au-hero h1 { font-size: clamp(2rem, 4.6vw, 3.2rem); line-height: 1.08; letter-spacing: -.03em; margin-top: .9rem; }
.au-accent { background: linear-gradient(120deg, var(--teal-600), var(--teal-400)); -webkit-background-clip: text; background-clip: text; color: transparent; }
.au-lead { font-size: clamp(1rem, 1.6vw, 1.15rem); color: var(--text-muted); margin-top: 1.1rem; max-width: 36rem; line-height: 1.65; }
.au-hero-actions { display: flex; flex-wrap: wrap; gap: .75rem; margin-top: 1.75rem; }
.au-hero-art { position: relative; min-height: 22rem; }
.au-orb { position: absolute; inset: 12% 10%; border-radius: 50%; background: radial-gradient(circle at 30% 30%, var(--teal-200), var(--teal-500)); opacity: .22; filter: blur(2px); }
.au-float { position: absolute; z-index: 1; display: flex; align-items: center; gap: .8rem; padding: .9rem 1.1rem; min-width: 14rem;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); box-shadow: var(--shadow-lg); animation: au-bob 6s var(--ease) infinite; }
.au-float b { display: block; font-size: var(--fs-sm); }
.au-float small { color: var(--text-muted); font-size: var(--fs-xs); }
.au-float-1 { top: 6%; left: 4%; }
.au-float-2 { top: 40%; right: 0; animation-delay: -2s; }
.au-float-3 { bottom: 6%; left: 14%; animation-delay: -4s; }
.au-float-ico { width: 2.4rem; height: 2.4rem; flex: none; display: grid; place-items: center; border-radius: var(--r-md); background: var(--primary-soft); color: var(--primary); }
.au-float-ico.amber { background: var(--amber-100); color: var(--amber-600); }
@keyframes au-bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-8px); } }
@media (prefers-reduced-motion: reduce) { .au-float { animation: none; } }

.au-section { padding-block: clamp(2.5rem, 6vw, 4.5rem) 0; }
.au-head { text-align: center; max-width: 40rem; margin: 0 auto 2rem; }
.au-head h2 { font-size: clamp(1.6rem, 3.2vw, 2.25rem); letter-spacing: -.02em; margin-top: .6rem; }
.au-head p { color: var(--text-muted); margin-top: .6rem; }

.au-mv { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.25rem; }
.au-mv-card { padding: clamp(1.5rem, 3vw, 2.25rem); border-radius: var(--r-xl); background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow-sm); }
.au-mv-card h2 { font-size: var(--fs-2xl); margin-top: 1rem; }
.au-mv-card p { color: var(--text-muted); margin-top: .6rem; line-height: 1.7; }
.au-mv-ico { width: 3rem; height: 3rem; display: grid; place-items: center; border-radius: var(--r-md); background: var(--primary-soft); color: var(--primary); }
.au-mv-dark { background: linear-gradient(140deg, var(--teal-700), var(--teal-900)); border-color: transparent; color: #fff; }
.au-mv-dark p { color: rgba(255, 255, 255, .82); }
.au-mv-dark .au-mv-ico { background: rgba(255, 255, 255, .14); color: #fff; }

.au-values { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.1rem; }
.au-value { padding: 1.5rem; border-radius: var(--r-lg); background: var(--surface); border: 1px solid var(--border); transition: transform var(--t) var(--ease), box-shadow var(--t) var(--ease), border-color var(--t); }
@media (hover: hover) { .au-value:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); border-color: var(--primary-soft-br); } }
.au-value h3 { font-size: var(--fs-lg); margin-top: .9rem; }
.au-value p { color: var(--text-muted); font-size: var(--fs-sm); margin-top: .45rem; line-height: 1.65; }
.au-value-ico { width: 2.75rem; height: 2.75rem; display: grid; place-items: center; border-radius: var(--r-md); background: var(--primary-soft); color: var(--primary); }

.au-band { margin-top: clamp(2.5rem, 6vw, 4.5rem); padding-block: clamp(2.5rem, 6vw, 4rem); background: var(--bg-subtle); border-block: 1px solid var(--border); }
.au-sides { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.25rem; }
.au-side { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-xl); overflow: hidden; box-shadow: var(--shadow-sm); }
.au-side-head { display: flex; align-items: center; gap: .7rem; padding: 1.1rem 1.5rem; color: #fff; background: linear-gradient(120deg, var(--teal-600), var(--teal-500)); }
.au-side.employers .au-side-head { background: linear-gradient(120deg, var(--ink-800), var(--ink-600)); }
.au-side-head h3 { color: #fff; font-size: var(--fs-lg); }
.au-side ul { list-style: none; margin: 0; padding: 1.4rem 1.5rem 1.6rem; display: grid; gap: 1.15rem; }
.au-side li { display: flex; gap: .85rem; align-items: flex-start; }
.au-side li b { font-size: var(--fs-md); }
.au-side li p { color: var(--text-muted); font-size: var(--fs-sm); margin-top: .25rem; line-height: 1.6; }
.au-tick { width: 2rem; height: 2rem; flex: none; display: grid; place-items: center; border-radius: 50%; background: var(--primary-soft); color: var(--primary); }

.au-steps { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1.1rem; counter-reset: none; }
.au-steps li { position: relative; padding: 1.5rem 1.35rem; border-radius: var(--r-lg); background: var(--surface); border: 1px solid var(--border); }
.au-steps li:not(:last-child)::after { content: ''; position: absolute; top: 2.35rem; right: -1.1rem; width: 1.1rem; height: 2px; background: var(--primary-soft-br); }
.au-step-no { width: 2.4rem; height: 2.4rem; display: grid; place-items: center; border-radius: 50%; background: var(--primary); color: #fff; font-weight: 800; }
.au-steps h3 { font-size: var(--fs-md); margin-top: .9rem; }
.au-steps p { color: var(--text-muted); font-size: var(--fs-sm); margin-top: .4rem; line-height: 1.6; }

.au-quote { margin: 0; text-align: center; padding: clamp(2rem, 5vw, 3rem) clamp(1.25rem, 5vw, 4rem); border-radius: var(--r-xl);
  background: linear-gradient(135deg, var(--teal-50), var(--amber-100)); border: 1px solid var(--primary-soft-br); }
.au-quote-ico { color: var(--primary); display: inline-flex; }
.au-quote blockquote { margin: .75rem auto 0; max-width: 40rem; font-size: clamp(1.15rem, 2.4vw, 1.6rem); font-weight: 700; line-height: 1.4; letter-spacing: -.01em; color: var(--ink-900); }
.au-quote figcaption { margin-top: 1rem; color: var(--ink-600); font-weight: 600; }

.au-contact { display: flex; align-items: center; justify-content: space-between; gap: 1.5rem; flex-wrap: wrap; margin: 1.5rem 0 clamp(2.5rem, 6vw, 4rem);
  padding: 1.5rem 1.75rem; border-radius: var(--r-xl); background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow-sm); }
.au-contact h3 { display: flex; align-items: center; gap: .5rem; font-size: var(--fs-lg); }
.au-contact p { color: var(--text-muted); font-size: var(--fs-sm); margin-top: .35rem; max-width: 30rem; }
.au-contact-links { display: flex; gap: .6rem; flex-wrap: wrap; }
.au-contact-links .btn { gap: .45rem; }

:root[data-theme="dark"] .au-hero { background: radial-gradient(60rem 30rem at 85% -10%, rgba(20, 146, 134, .18), transparent 60%); }
:root[data-theme="dark"] .au-quote { background: var(--surface-raised); border-color: var(--border); }
:root[data-theme="dark"] .au-quote blockquote { color: var(--text); }
:root[data-theme="dark"] .au-quote figcaption { color: var(--text-muted); }

@media (max-width: 960px) {
  .au-hero-grid { grid-template-columns: 1fr; }
  .au-hero-art { min-height: 17rem; max-width: 30rem; width: 100%; margin: 0 auto; }
  .au-values { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .au-steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .au-steps li::after { display: none; }
}
@media (max-width: 640px) {
  .au-mv, .au-sides, .au-values, .au-steps { grid-template-columns: 1fr; }
  .au-hero-actions .btn { flex: 1 1 100%; }
  .au-float { min-width: 0; padding: .7rem .85rem; }
  .au-float-2 { right: 2%; }
  .au-contact { padding: 1.25rem; }
  .au-contact-links .btn { flex: 1 1 100%; justify-content: center; }
}
