/*
 * Phase 6, redesigned. One stylesheet, no framework, no hosted fonts — §10 forbids
 * third-party assets and the CSP enforces it.
 *
 * Light only. The theme toggle and the dark palette are gone: a second scheme was
 * being maintained as an inversion of the first rather than as a designed palette,
 * and every token added for the redesign would have had to be invented twice. If
 * dark mode returns it needs its own palette, not a mirror of this one.
 *
 * Instrument Sans is served from public/fonts/ rather than linked. Not a preference —
 * `default-src 'self'` has no `font-src` escape, so a hosted font is a blocked
 * request and a silently substituted typeface. The variable face is what makes
 * weight 550 available; a static family would round it to 500.
 */

/* Variable 400–700, so intermediate weights are real rather than synthesised. */
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/fonts/instrument-sans-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/fonts/instrument-sans-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Instrument Sans";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/instrument-sans-latin-italic.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

/*
 * The palette.
 *
 * The first eleven names predate the redesign and are referenced throughout this
 * file; they keep their names and take new values, so every existing rule inherits
 * the new palette without being rewritten. The names below them are new.
 *
 * Every text colour meets 4.5:1 against the ground it sits on. `--ink-faint` on
 * white is 4.83:1 and is the floor — nothing small gets lighter than that.
 */
:root {
  color-scheme: light;

  --bg: #f5f6f8;
  --surface: #ffffff;
  /*
   * Darker than the #e3e6eb the design specifies. That value is 1.25:1 against white
   * and this stylesheet holds borders to 1.4:1 — WCAG's non-text floor, checked by
   * accessibility.test.mjs. A card edge nobody can find is not a subtle card.
   */
  --border: #d2d7e0;
  --text: #14161a;
  --muted: #5c6575;
  --accent: #2c55f0;
  --accent-text: #ffffff;
  --error: #8c2f22;
  --ok: #15653a;

  --radius: 8px;
  --gap: 1rem;

  /* Surfaces that are not the card itself: chips, segmented tracks, hairlines. */
  --surface-subtle: #eef1f6;
  --surface-muted: #edeff3;
  --border-input: #d2d7e0;

  /* Ink, from body copy down to provenance lines. */
  --ink-body: #4a5261;
  --ink-faint: #6b7280;

  /* Accent, in the four jobs it does. `--accent-deep` is the fit numeral. */
  --accent-hover: #1e3fc4;
  --accent-deep: #1e3aa8;
  --accent-tint: #e7ecfe;
  --accent-tint-ink: #24409e;

  /* Status tints. Paired so a tint is never used without its readable ink. */
  --success-tint: #dff5e5;
  --success-ink: #15653a;
  --warn-tint: #fdf0ce;
  --warn-ink: #7a5a12;
  --neutral-tint: #e6eaf1;
  --neutral-ink: #414b5c;

  /* The dark privacy band on the landing page, and only there. */
  --on-dark-bg: #14161a;
  --on-dark-body: #a7afbd;
  --on-dark-border: #2a2f38;

  /* Radii, largest to smallest. */
  --radius-card: 14px;
  --radius-nested: 12px;
  --radius-tile: 10px;
  --radius-badge: 6px;
  --radius-pill: 999px;

  /*
   * One shadow in the system, on the landing hero's sample card. Everything else
   * separates with a border — a page of cards that all float reads as none of them
   * mattering more than the others.
   */
  --shadow-hero: 0 20px 50px -30px rgba(16, 18, 22, 0.35);
  --shadow-segment: 0 1px 3px rgba(16, 18, 22, 0.12);

  /* One content column, one left edge. See .page. */
  --content-max: 73.75rem;
  --content-pad: 28px;

  /*
   * The application bar's two measurements, named because its height is a promise
   * rather than an outcome — see .app-bar-inner. The avatar is the tallest thing
   * the bar ever holds, and the bar is sized to hold it whether it is there or not.
   */
  --bar-avatar: 2.375rem;
  --bar-pad-y: 18px;

  --font: "Instrument Sans", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font: 16px/1.55 var(--font);
  -webkit-font-smoothing: antialiased;
}

.shell {
  max-width: 34rem;
  margin: 3rem auto;
  padding: 0 var(--gap);
}

h1 { font-size: 1.6rem; margin: 0 0 0.25rem; }
h2 { font-size: 1.1rem; margin: 0 0 1rem; }
.lede { color: var(--muted); margin: 0 0 2rem; }

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.5rem;
}

label {
  display: block;
  font-weight: 600;
  margin-bottom: 0.35rem;
}

input, select, textarea {
  width: 100%;
  padding: 0.6rem 0.7rem;
  font: inherit;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.help {
  color: var(--muted);
  font-size: 0.9rem;
  margin: 0.4rem 0 1.2rem;
}

button {
  font: inherit;
  font-weight: 600;
  padding: 0.6rem 1.1rem;
  color: var(--accent-text);
  background: var(--accent);
  border: 1px solid transparent;
  border-radius: var(--radius);
  cursor: pointer;
}

button:disabled { opacity: 0.6; cursor: default; }

/*
 * A visible focus ring on everything interactive. Removing it is the single most
 * common accessibility regression, and a keyboard user who cannot see where they are
 * cannot use the page at all.
 */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

/*
 * A submit button that follows a field directly.
 *
 * Vertical rhythm in these forms comes entirely from `.help`'s 1.2rem bottom
 * margin — inputs carry no margin of their own — so a field with nothing to
 * explain has no paragraph after it and therefore no gap at all. On the password
 * pages the button sat flush against the input, two rounded borders touching,
 * which reads as one box overlapping the other.
 *
 * The gap belongs to the button, not to a paragraph that happens to precede it.
 * Both password forms had already tried to say so with a `style` attribute, which
 * the CSP drops (`style-src \'self\'`), so neither gap ever appeared.
 */
.field-submit {
  margin-top: 1.2rem;
}

/*
 * A table wider than its card scrolls inside the card rather than the page.
 *
 * Also previously a dead `style` attribute, so the admin tables simply overflowed.
 */
.table-scroll {
  overflow-x: auto;
}

.help-tight { margin: 0.5rem 0 0; }

.table-empty {
  text-align: center;
  color: var(--muted);
}

.status { margin: 1rem 0 0; min-height: 1.5rem; }
.status[data-kind="error"] { color: var(--error); }
.status[data-kind="sent"] { color: var(--ok); }

/* Respect a stated preference for less motion rather than assuming nobody minds. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* Onboarding form (6.3) */

fieldset {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem 1.1rem 0.4rem;
  margin: 0 0 1.4rem;
}

legend {
  font-weight: 600;
  padding: 0 0.4rem;
}

fieldset.inline {
  margin-top: 0.5rem;
  background: color-mix(in srgb, var(--bg) 60%, transparent);
}

.optional {
  font-weight: 400;
  color: var(--muted);
}

/*
 * A checkbox and its words are one target. Wrapping the input in its label means the
 * whole phrase is clickable, which matters most to whoever has the least steady aim.
 */
.check {
  display: flex;
  align-items: baseline;
  gap: 0.55rem;
  font-weight: 400;
  margin-bottom: 0.5rem;
  cursor: pointer;
}

.check input {
  width: auto;
  /* Comfortably above the 24px minimum target size, without redrawing the control. */
  min-width: 1.15rem;
  min-height: 1.15rem;
}

/* Results dashboard (6.4) */

.shell.wide { max-width: 52rem; }

.row {
  display: flex;
  gap: var(--gap);
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
}

nav a { margin-left: 1rem; }

/* The filter row --------------------------------------------------------------
   On the page ground rather than in a panel of its own. The panel was a card
   containing three controls and nothing else, which gave the filters the same
   visual weight as the results they filter.
*/
.filter-row {
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 20px;
}

.filter-field {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.filter-field label {
  margin: 0;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}

.filter-field select,
.filter-field input {
  width: auto;
  min-width: 11rem;
  padding: 11px 14px;
  border: 1px solid var(--border-input);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  font-size: 15px;
}

.filter-note {
  margin: 0 0 11px auto;
  font-size: 14px;
  color: var(--ink-faint);
}

.filter-note:empty { display: none; }

/* The segmented control -------------------------------------------------------
   A filter, so the pressed segment is `aria-pressed` rather than `aria-current`:
   none of the three is a place.
*/
.segmented {
  display: inline-flex;
  gap: 2px;
  padding: 4px;
  background: var(--surface-subtle);
  border-radius: var(--radius-pill);
}

.segment {
  padding: 7px 18px;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--ink-body);
  font: inherit;
  font-size: 14px;
  cursor: pointer;
}

.segment:hover { color: var(--text); }

.segment[aria-pressed="true"] {
  background: var(--surface);
  color: var(--text);
  font-weight: 550;
  box-shadow: var(--shadow-segment);
}

/* The match list --------------------------------------------------------------
   One panel, rows divided by hairlines, rather than a card per result. Twenty-five
   separate cards on a page is twenty-five borders and twenty-five gaps to scan
   past, and the thing being compared is the rows against each other.
*/
.matches {
  list-style: none;
  margin: 0;
  padding: 0 26px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
}

.match-group {
  padding: 22px 0 10px;
  border-bottom: 1px solid var(--border);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}

.match-group:first-child { padding-top: 20px; }

/* 64px is exactly wide enough for a two-digit score at 27px and the band beneath
   it, so the titles in column two all begin at the same x whatever the numbers do. */
.match-row {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr) auto;
  gap: 22px;
  align-items: start;
  padding: 24px 0;
  border-bottom: 1px solid var(--border);
}

.match-row:last-child { border-bottom: 0; }

.match-score {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.match-score-value {
  font-size: 27px;
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--accent-deep);
}

/* An unjudged posting is not a low-scoring one, so it is not coloured like one. */
.match-score-value.is-unscored {
  color: var(--ink-faint);
  font-weight: 400;
}

.match-score-band {
  font-size: 11px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.match-title {
  margin: 0;
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -0.018em;
  line-height: 1.25;
}

.match-title a { color: var(--text); text-decoration: none; }
.match-title a:hover { color: var(--accent-hover); text-decoration: underline; }

.match-where {
  margin: 4px 0 0;
  font-size: 15px;
  color: var(--ink-body);
}

.match-provenance {
  margin: 2px 0 0;
  font-size: 13px;
  color: var(--ink-faint);
}

.match-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 12px 0 0;
  padding: 0;
  list-style: none;
}

.match-chip {
  padding: 4px 10px;
  background: var(--surface-subtle);
  border-radius: var(--radius);
  font-size: 13px;
  color: var(--ink-body);
}

.match-more {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
  margin-top: 10px;
}

.match-actions {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
}

.match-actions select {
  width: auto;
  min-width: 13rem;
  padding: 9px 12px;
  border: 1px solid var(--border-input);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  font-size: 14px;
}

.match-quick {
  display: flex;
  gap: 14px;
}

/* An action, not a destination — so a button, which is also what makes it
   keyboard-reachable without any work. Triage is the core loop of a daily sweep. */
.link-action {
  padding: 0;
  border: 0;
  background: none;
  color: var(--muted);
  font: inherit;
  font-size: 14px;
  cursor: pointer;
}

.link-action:hover {
  color: var(--accent-hover);
  text-decoration: underline;
}

.result-detail,
.result-note {
  font-size: 14px;
}

.result-detail summary,
.result-note summary {
  color: var(--muted);
  cursor: pointer;
  list-style: none;
}

.result-detail summary::-webkit-details-marker,
.result-note summary::-webkit-details-marker { display: none; }

/* No disclosure triangle. The word is the affordance; a rotating glyph beside it
   was one more thing rendering differently on every platform. */
.result-detail summary::marker,
.result-note summary::marker { content: ""; }

.result-detail summary:hover,
.result-note summary:hover {
  color: var(--accent-hover);
  text-decoration: underline;
}

/* The breakdown's two halves, each under a quiet label so it is clear which
   question the list beneath it answers. */
.breakdown-head {
  margin: 10px 0 0;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}

.breakdown > .breakdown-head:first-child { margin-top: 8px; }

.result-reasons {
  margin: 8px 0 0;
  padding-left: 1.1rem;
  color: var(--ink-body);
}

.result-note textarea {
  width: 100%;
  margin: 0.4rem 0;
}

.pager {
  display: flex;
  gap: var(--gap);
  align-items: center;
  justify-content: center;
  margin: 1.5rem 0;
}

/* Present for screen readers, absent visually. Never display:none, which would take
   it out of the accessibility tree as well and defeat the point. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

@media (max-width: 34rem) {
  .filters { flex-direction: column; gap: 0.8rem; }
  .row { flex-direction: column; align-items: flex-start; gap: 0.3rem; }
}

/* Saved searches (6.5) */

.search-name { font-size: 1.05rem; margin: 0; }
.search-meta { margin: 0.3rem 0 0.4rem; }
.search-summary { margin: 0 0 0.8rem; }

.expert { margin: 1rem 0 0; }
.expert summary { cursor: pointer; color: var(--muted); font-size: 0.9rem; }
.expert input { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }

/*
 * Every problem, listed. A refused search is refused for reasons a person can act
 * on, so they are shown as a list rather than folded into one sentence.
 */
.problems {
  margin: 1rem 0 0;
  padding: 0.8rem 1rem 0.8rem 2rem;
  border: 1px solid var(--error);
  border-radius: var(--radius);
  color: var(--error);
}

.problems li { margin: 0.2rem 0; }

#editor .row { justify-content: flex-start; gap: 0.6rem; }

/* Run history (6.7) */

.run-board { font-size: 1rem; margin: 0; }
.run-text { margin: 0.3rem 0; }
.run-consequence, .run-likely, .run-meta { margin: 0.2rem 0; }

/*
 * Severity as a word first. The colour agrees with the label; it never carries the
 * meaning on its own, so a reader who cannot separate red from green loses nothing.
 */
.badge[data-severity="ok"] { color: var(--ok); }
.badge[data-severity="partial"],
.badge[data-severity="unknown"] { color: var(--muted); }
.badge[data-severity="failed"] { color: var(--error); }

#health h2 { font-size: 1.05rem; margin: 0 0 0.3rem; }
#health[data-severity="degraded"] { border-color: var(--error); }
#health[data-severity="degraded"] h2 { color: var(--error); }

/* Account (6.9) */

/*
 * The destructive section is marked by its border and its heading, and the page says
 * "immediately and cannot be undone" in words above the button. Colour alone would
 * mean nothing to a reader who cannot see it, and this is the one action on the site
 * with no way back.
 */
.card.danger { border-color: var(--error); }
.card.danger h2 { color: var(--error); }
.card.danger strong { color: var(--error); }

#delete { background: var(--error); border-color: var(--error); color: #ffffff; }
#receipt { margin-top: 0.6rem; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }

/* Skip link (6.10) */

/*
 * Off-screen until focused, then placed over the top-left corner. Not `display:none`
 * and not `hidden`: both would take it out of the tab order, and a skip link nobody
 * can tab to is decoration.
 */
.skip-link {
  position: absolute;
  left: -100vw;
  top: 0;
  z-index: 10;
  padding: 0.6rem 1rem;
  background: var(--accent);
  color: var(--accent-text);
  border-radius: 0 0 var(--radius) 0;
}

.skip-link:focus {
  left: 0;
}

/*
 * The jump target keeps its focus ring. It looks unusual — a ring around the whole
 * page body — but it is the only confirmation a keyboard user gets that the skip
 * actually went somewhere, and silence there is indistinguishable from a dead link.
 */

/* Landing Page Hero & Feature Grid */
/* The landing page ------------------------------------------------------------
   No media queries anywhere below. Every section reflows on flex-basis, and the
   step grid wraps two-up before it wraps one-up: a four-item row must never break
   3+1, which is the exact defect the review found on the old Applications tiles.
*/
/*
 * Sticky, like the application bar. It was the only bar on the site that scrolled
 * away, which also made its three anchor links useless the moment you used one —
 * they are the way back up, and they left with the header.
 *
 * Opaque rather than the translucent treatment the app bar uses. This page scrolls
 * through white bands and one near-black one, and a light translucent bar passing
 * over the dark privacy section reads as a rendering fault rather than a choice.
 */
.landing-bar {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}

/*
 * An anchor jump lands under a sticky header unless it is told not to. Set on the
 * three sections the nav points at, and generously — the bar is about 65px and this
 * leaves the heading clear of it rather than flush against it.
 */
#how-it-works,
#privacy,
#faq {
  scroll-margin-top: 5rem;
}

.landing-bar-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1rem;
  max-width: var(--content-max);
  margin: 0 auto;
  padding: 20px var(--content-pad);
}

.landing-nav {
  display: flex;
  align-items: center;
  gap: 26px;
}

.landing-nav a {
  color: var(--ink-body);
  font-size: 15px;
  text-decoration: none;
}

.landing-nav a:hover { color: var(--text); text-decoration: underline; }

/* The page you are on, as in .app-nav: stated, not offered. */
.landing-nav a[aria-current="page"] { color: var(--text); font-weight: 550; }

.landing-signin { color: var(--accent) !important; font-weight: 500; }

.hero {
  max-width: var(--content-max);
  margin: 0 auto;
  padding: 88px var(--content-pad) 72px;
}

/* Two columns that become one by wrapping, not by a breakpoint. The basis values
   are what decide when: 420 + 340 + the gap no longer fits, so they stack. */
.hero-inner {
  display: flex;
  flex-wrap: wrap;
  gap: 56px;
  align-items: center;
}

.hero-copy { flex: 1 1 420px; }
.hero-card { flex: 1 1 340px; }

.hero-eyebrow {
  display: inline-block;
  margin: 0 0 20px;
  padding: 6px 14px;
  background: var(--accent-tint);
  border-radius: var(--radius-pill);
  color: var(--accent-tint-ink);
  font-size: 13px;
  font-weight: 500;
}

.hero-title {
  margin: 0;
  font-size: clamp(34px, 5.2vw, 58px);
  font-weight: 600;
  letter-spacing: -0.04em;
  line-height: 1.04;
}

.hero-lead {
  margin: 20px 0 0;
  max-width: 34em;
  font-size: 19px;
  line-height: 1.55;
  color: var(--ink-body);
}

.hero-actions { margin: 28px 0 0; }

.button-large {
  display: inline-block;
  padding: 14px 26px;
  font-size: 16px;
  text-decoration: none;
}

.button-large:hover { text-decoration: none; color: var(--accent-text); }

.hero-reassurance {
  margin: 14px 0 0;
  font-size: 14px;
  color: var(--ink-faint);
}

/* The only shadow in the system. Everything else separates with a border — a page
   where every card floats reads as one where none of them matters more. */
.hero-card {
  background: var(--surface);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-hero);
  padding: 24px 26px;
}

.hero-card-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--border);
}

.hero-card-time { font-size: 13px; color: var(--ink-faint); }

.hero-match {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 16px;
  align-items: center;
  padding: 16px 0;
  border-bottom: 1px solid var(--surface-muted);
}

.hero-match-title {
  margin: 0;
  font-size: 16px;
  font-weight: 550;
  line-height: 1.3;
}

.hero-match-meta {
  margin: 3px 0 0;
  font-size: 14px;
  color: var(--ink-faint);
}

.hero-match-score { text-align: right; }

.hero-match-score span {
  display: block;
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--accent-deep);
}

.hero-match-score small {
  font-size: 11px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.hero-card-foot {
  margin: 14px 0 0;
  font-size: 13px;
  color: var(--ink-faint);
}

.band {
  background: var(--surface);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  padding: 84px 0;
}

.band-dark {
  background: var(--on-dark-bg);
  color: #ffffff;
  padding: 84px 0;
}

.band-inner {
  max-width: var(--content-max);
  margin: 0 auto;
  padding: 0 var(--content-pad);
}

.band h2,
.band-dark h2,
.explain h2,
.faq h2,
.closing h2 {
  margin: 0;
  font-size: 34px;
  font-weight: 600;
  letter-spacing: -0.025em;
}

.band-lead {
  margin: 12px 0 0;
  font-size: 19px;
  color: var(--ink-body);
}

.band-dark .band-lead { color: var(--on-dark-body); }

/* calc(50% - 16px) with a 240px floor: two up, then one up. Never three and one. */
.steps {
  display: flex;
  flex-wrap: wrap;
  gap: 32px;
  margin-top: 44px;
}

.step {
  flex: 1 1 calc(50% - 16px);
  min-width: 15rem;
  padding-top: 18px;
  border-top: 2px solid var(--border);
}

.band-dark .step { border-top: 1px solid var(--on-dark-border); }

.step-n {
  display: block;
  margin-bottom: 8px;
  font-size: 13px;
  font-weight: 600;
  color: var(--accent);
}

.step h3 {
  margin: 0;
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -0.015em;
}

.step p {
  margin: 8px 0 0;
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink-body);
}

.band-dark .step p { color: var(--on-dark-body); }

.explain { padding: 84px 0; }

.explain-inner {
  display: flex;
  flex-wrap: wrap;
  gap: 56px;
  align-items: center;
  max-width: var(--content-max);
  margin: 0 auto;
  padding: 0 var(--content-pad);
}

.explain-copy { flex: 1 1 420px; }
.explain-card { flex: 1 1 340px; }

.explain-copy p {
  margin: 18px 0 0;
  font-size: 17px;
  line-height: 1.6;
  color: var(--ink-body);
}

.explain-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 26px 28px;
}

.explain-card-title {
  margin: 0;
  font-size: 21px;
  font-weight: 600;
  letter-spacing: -0.02em;
}

.explain-card-meta { margin: 6px 0 0; color: var(--ink-body); }

.explain-card-source {
  margin: 2px 0 0;
  font-size: 13px;
  color: var(--ink-faint);
}

.explain-card-score { margin-top: 18px; }

.explain-card-score span {
  display: block;
  font-size: 34px;
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--accent-deep);
}

.explain-card-score small {
  font-size: 11px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.hairline {
  margin: 20px 0 16px;
  border: 0;
  border-top: 1px solid var(--surface-muted);
}

/* ---------------------------------------------------------------------------
   The landing page's signed-in previews (#tracking).

   Copy beside a miniature of the page, wrapping to one column the same way the
   hero and .explain do — on flex-basis, with no breakpoint. Everything inside a
   .preview is a span: it depicts controls without being any, so nothing in it
   takes focus or pretends to be clickable.
   --------------------------------------------------------------------------- */
.showcase {
  display: flex;
  flex-wrap: wrap;
  gap: 48px;
  align-items: center;
  margin-top: 56px;
}

.showcase-copy { flex: 1 1 22rem; }
.showcase .preview { flex: 1.3 1 24rem; }

.showcase-copy h3 {
  margin: 0;
  font-size: 24px;
  font-weight: 600;
  letter-spacing: -0.02em;
}

.showcase-copy p:not(.step-n) {
  margin: 14px 0 0;
  font-size: 17px;
  line-height: 1.6;
  color: var(--ink-body);
}

.preview {
  margin: 0;
  min-width: 0;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 18px;
}

.preview figcaption {
  margin-top: 12px;
  font-size: 13px;
  color: var(--ink-faint);
}

.preview-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
}

.preview-title {
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.015em;
}

.preview-tabs {
  display: inline-flex;
  padding: 3px;
  background: var(--surface-muted);
  border-radius: var(--radius);
}

.preview-tab {
  padding: 3px 10px;
  border-radius: var(--radius-badge);
  font-size: 13px;
  color: var(--ink-body);
}

.preview-tab.is-on {
  background: var(--surface);
  box-shadow: var(--shadow-segment);
  color: var(--text);
  font-weight: 500;
}

.preview-list {
  margin: 0;
  padding: 0;
  list-style: none;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-nested);
}

.preview-list > li {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 14px;
  align-items: flex-start;
  padding: 14px 16px;
  border-top: 1px solid var(--surface-muted);
}

.preview-list > li:first-child { border-top: 0; }
.preview-app { align-items: center; }

.preview-score {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 3rem;
}

.preview-score strong {
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--accent-deep);
}

.preview-score small {
  margin-top: 3px;
  font-size: 11px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.preview-body {
  display: flex;
  flex-direction: column;
  flex: 1 1 12rem;
  min-width: 0;
}

.preview-job {
  font-size: 15px;
  font-weight: 550;
  line-height: 1.3;
}

.preview-meta {
  margin-top: 2px;
  font-size: 13px;
  color: var(--ink-faint);
}

.preview-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
}

.preview-chips .match-chip { font-size: 12px; padding: 2px 8px; }

/* The status pills borrow the badge tints, whose ink/tint pairs the contrast
   test already checks — no new colour enters the palette here. */
.preview-status {
  padding: 3px 10px;
  border-radius: var(--radius-pill);
  background: var(--neutral-tint);
  color: var(--neutral-ink);
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
}

.preview-status.status-interested { background: var(--accent-tint); color: var(--accent-tint-ink); }
.preview-status.status-applied { background: var(--success-tint); color: var(--success-ink); }
.preview-status.status-interview { background: var(--warn-tint); color: var(--warn-ink); }

.preview-wait {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  min-width: 6rem;
  font-size: 14px;
  font-weight: 600;
  text-align: right;
}

.preview-wait small {
  font-size: 12px;
  font-weight: 500;
}

.preview-wait.is-overdue { color: var(--warn-ink); }

/* When a narrow row wraps, the status and the wait start a new line; keep them
   on the right edge, where they sit on a wide one. On a wide row .preview-body
   has already taken the free space, so this changes nothing there. */
.preview-match .preview-status,
.preview-wait { margin-left: auto; }

.preview-pipeline {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 12px;
}

.preview-tile {
  display: flex;
  flex-direction: column;
  flex: 1 1 5rem;
  padding: 8px 10px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-tile);
  font-size: 12px;
  color: var(--ink-body);
}

.preview-tile strong {
  font-size: 20px;
  font-weight: 600;
  color: var(--text);
}

.preview-tile.is-on { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }

.faq {
  max-width: 51.25rem;
  margin: 0 auto;
  padding: 84px var(--content-pad);
}

.faq-item {
  padding: 24px 0;
  border-bottom: 1px solid var(--border);
}

.faq-item:first-of-type { margin-top: 20px; border-top: 1px solid var(--border); }

.faq-item h3 {
  margin: 0;
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -0.015em;
}

.faq-item p {
  margin: 10px 0 0;
  max-width: 62ch;
  font-size: 16px;
  line-height: 1.6;
  color: var(--ink-body);
}

.closing {
  background: var(--surface);
  border-top: 1px solid var(--border);
  padding: 84px var(--content-pad);
  text-align: center;
}

.closing .band-lead { margin-bottom: 4px; }

/* Sign-in ---------------------------------------------------------------------
   Its own route. It was the whole of the root URL, which meant the site asked a
   stranger for a password before it had said what it does.
*/
.signin-page {
  max-width: 26rem;
  margin: 0 auto;
  padding: 72px var(--content-pad);
}

.signin-card {
  border-radius: var(--radius-card);
  padding: 30px 32px;
}

.signin-card h1 {
  margin: 0 0 20px;
  font-size: 24px;
  font-weight: 600;
  letter-spacing: -0.02em;
}

.signin-submit {
  width: 100%;
  margin-top: 20px;
}

.signin-alt {
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
  text-align: center;
}

/* The application bar ---------------------------------------------------------
   Its height is fixed by construction: nothing inside it is page content, so no
   title can push the navigation down. That was the whole bug — the nav sat about
   60px lower on Applications than on Matches and moved as you switched pages.

   Sticky, over a blurred page ground rather than an opaque one, so a scrolled list
   reads as passing beneath the bar instead of vanishing into a slab the same
   colour as itself.
*/
.app-bar {
  position: sticky;
  top: 0;
  z-index: 20;
  background: rgba(245, 246, 248, 0.92);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border);
}

.app-bar-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  max-width: var(--content-max);
  margin: 0 auto;
  padding: var(--bar-pad-y) var(--content-pad);
  /*
   * The reason the bar is the same height on every page, including the ones with no
   * avatar in it. Stated rather than inherited from whichever child happens to be
   * tallest: runs.html had no user menu and rendered a bar 7px shorter than every
   * other page, and the sign-in page still did until this rule was corrected.
   *
   * The padding is added back deliberately. `box-sizing: border-box` is global here,
   * so a bare `min-height: var(--bar-avatar)` is a floor on the *border* box — 38px
   * of which 36px is already padding, leaving a 2px content floor and guaranteeing
   * nothing. The earlier version of this rule did exactly that and only appeared to
   * work because every signed-in page happens to contain the avatar.
   */
  min-height: calc(var(--bar-avatar) + var(--bar-pad-y) * 2);
}

.wordmark {
  font-size: 20px;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--text);
  text-decoration: none;
  white-space: nowrap;
}

.wordmark:hover {
  color: var(--text);
  text-decoration: none;
}

.app-nav {
  display: flex;
  align-items: center;
  gap: 26px;
}

.app-nav a {
  color: var(--ink-body);
  text-decoration: none;
  font-size: 15px;
  padding-bottom: 3px;
  border-bottom: 2px solid transparent;
}

.app-nav a:hover {
  color: var(--text);
  text-decoration: none;
}

/* 550 is a real weight here: the variable face is loaded across 400–700. */
.app-nav a[aria-current="page"] {
  color: var(--accent);
  font-weight: 550;
  border-bottom-color: var(--accent);
}

/* The content column ----------------------------------------------------------
   One max width and one left edge that every element on the page obeys. Elements
   used to be sized by their own content, so the heading, the filter panel and the
   cards each started at a slightly different x.
*/
.page {
  max-width: var(--content-max);
  margin: 0 auto;
  padding: 0 var(--content-pad) 84px;
}

.page-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1rem;
  padding: 40px 0 24px;
}

.page-head h1 {
  margin: 0;
  font-size: 32px;
  font-weight: 600;
  letter-spacing: -0.025em;
  line-height: 1.15;
}

/* Status, not a definition. What the page is called is already the heading. */
.page-sub {
  margin: 6px 0 0;
  color: var(--ink-faint);
  font-size: 15px;
}

.user-menu-wrapper {
  position: relative;
  display: inline-block;
}

.user-avatar-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--bar-avatar);
  height: var(--bar-avatar);
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
  padding: 0;
  transition: all 0.15s ease;
}

.user-avatar-btn:hover, .user-avatar-btn[aria-expanded="true"] {
  border-color: var(--accent);
  background: var(--bg);
  box-shadow: 0 0 0 2px rgba(44, 85, 240, 0.15);
}

.user-dropdown-card {
  position: absolute;
  top: calc(100% + 0.5rem);
  right: 0;
  width: 15rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 6px 20px rgba(0,0,0,0.12);
  z-index: 1000;
  padding: 0.5rem 0;
}

.user-dropdown-header {
  padding: 0.5rem 1rem;
}

.user-dropdown-label {
  display: block;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.user-dropdown-email {
  display: block;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.user-dropdown-divider {
  height: 1px;
  background: var(--border);
  margin: 0.4rem 0;
}

.user-dropdown-link {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0.55rem 1rem;
  font-size: 0.9rem;
  color: var(--text);
  text-decoration: none;
  background: none;
  border: none;
  cursor: pointer;
  box-sizing: border-box;
  text-align: left;
}

.user-dropdown-link:hover, .user-dropdown-link:focus {
  background: var(--bg);
  color: var(--accent);
}

.user-dropdown-logout {
  color: var(--error);
}
.user-dropdown-logout:hover {
  background: #fce8e6;
  color: var(--error);
}


/* Admin KPI Stat Strip & Audit Tables */
.kpi-strip {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  margin: 0.75rem 0;
}

.kpi-item {
  padding: 0.85rem 0.5rem;
  text-align: center;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  border-right: 1px solid var(--border);
}

.kpi-item:last-child {
  border-right: none;
}

.kpi-label {
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-bottom: 0.25rem;
  white-space: nowrap;
}

.kpi-value {
  font-size: 1.45rem;
  font-weight: 800;
  color: var(--accent);
  line-height: 1.1;
}

@media (max-width: 52rem) {
  .kpi-strip {
    grid-template-columns: repeat(3, 1fr);
  }
  .kpi-item:nth-child(3n) {
    border-right: none;
  }
  .kpi-item:nth-child(-n+3) {
    border-bottom: 1px solid var(--border);
  }
}

@media (max-width: 32rem) {
  .kpi-strip {
    grid-template-columns: repeat(2, 1fr);
  }
  .kpi-item:nth-child(3n) {
    border-right: 1px solid var(--border);
  }
  .kpi-item:nth-child(2n) {
    border-right: none;
  }
  .kpi-item {
    border-bottom: 1px solid var(--border);
  }
  .kpi-item:nth-last-child(-n+2) {
    border-bottom: none;
  }
}

.action-row {
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1rem;
}
.action-btn {
  padding: 0.6rem 1.2rem;
  font-size: 0.95rem;
  cursor: pointer;
}

.feedback-table, .runs-table, .users-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 1rem;
  font-size: 0.9rem;
}
.feedback-table th, .runs-table th, .users-table th,
.feedback-table td, .runs-table td, .users-table td {
  border: 1px solid var(--border);
  padding: 0.6rem 0.75rem;
  text-align: left;
}
.feedback-table th, .runs-table th, .users-table th {
  background: var(--bg);
  font-weight: 600;
}

.tag {
  display: inline-block;
  padding: 0.15rem 0.45rem;
  border-radius: var(--radius);
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
}
.tag-bug { background: #fce8e6; color: #c5221f; }
.tag-feedback { background: #e8f0fe; color: #1a73e8; }
.tag-employer { background: #e6f4ea; color: #137333; }
.tag-open { background: #fef7e0; color: #b06000; }
.tag-resolved { background: #e6f4ea; color: #137333; }

/* The pipeline ----------------------------------------------------------------
   `auto-fit` with an equal minimum, so five tiles are five equal widths whatever
   the numbers in them are. The old boxes were sized by their contents, which is
   why the eighth ended up alone on a second row.
*/
.pipeline {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
  margin-bottom: 12px;
}

.tile {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 16px 18px;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-tile);
  color: var(--text);
  font: inherit;
  cursor: pointer;
}

.tile:hover { border-color: var(--border-input); }

.tile[aria-pressed="true"] {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}

.tile-count {
  font-size: 30px;
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1;
}

.tile-label { font-size: 14px; }

.tile-sub {
  font-size: 12px;
  color: var(--ink-faint);
}

/* Interviewing is the one state worth spotting from across the room. */
.tile[data-status="interview"] {
  background: var(--accent-tint);
  border-color: transparent;
}

.tile[data-status="interview"] .tile-count { color: var(--accent-deep); }

/* An outcome, not a stage: counted, but not competing with what is still live. */
.tile[data-status="rejected"] .tile-count { color: var(--muted); }

.other-states {
  margin-bottom: 20px;
  font-size: 14px;
}

.other-states summary {
  color: var(--muted);
  cursor: pointer;
  list-style: none;
}

.other-states summary::-webkit-details-marker { display: none; }
.other-states summary::marker { content: ""; }
.other-states summary:hover { color: var(--accent-hover); text-decoration: underline; }

.other-states-row {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  padding: 12px 0 0;
}

.other-states-row .link-action[aria-pressed="true"] {
  color: var(--accent);
  font-weight: 550;
}

/* The ledger ------------------------------------------------------------------
   One column definition, used by the header row and by every data row, so the two
   cannot drift apart the way a <table> laid out by content width does.
*/
.ledger {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 0 26px;
}

.ledger-head,
.ledger-row {
  display: grid;
  grid-template-columns: minmax(0, 2.2fr) minmax(0, 1fr) 150px 130px;
  gap: 18px;
  align-items: start;
}

.ledger-head {
  padding: 18px 0 12px;
  border-bottom: 1px solid var(--border);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}

.ledger-right { text-align: right; }

.ledger-rows {
  list-style: none;
  margin: 0;
  padding: 0;
}

.ledger-row {
  padding: 18px 0;
  border-bottom: 1px solid var(--border);
}

.ledger-row:last-child { border-bottom: 0; }

.ledger-title {
  margin: 0;
  font-size: 17px;
  font-weight: 550;
  letter-spacing: -0.015em;
  line-height: 1.3;
}

.ledger-title a { color: var(--text); text-decoration: none; }
.ledger-title a:hover { color: var(--accent-hover); text-decoration: underline; }

.ledger-where {
  margin: 3px 0 0;
  font-size: 14px;
  color: var(--ink-faint);
}

.ledger-applied {
  font-size: 15px;
  color: var(--ink-body);
}

.ledger-status select {
  width: 100%;
  padding: 7px 10px;
  border: 1px solid var(--border-input);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  font-size: 14px;
}

.ledger-status select[data-status="interview"] {
  background: var(--accent-tint);
  border-color: transparent;
  color: var(--accent-tint-ink);
}

.ledger-waiting {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  text-align: right;
}

.ledger-waiting-value {
  font-size: 15px;
  font-weight: 500;
  color: var(--ink-body);
}

/* Accent, not red. Three weeks of silence is worth noticing and is not an error. */
.ledger-waiting-value.is-overdue { color: var(--accent); }
.ledger-waiting-value.is-closed { color: var(--ink-faint); font-weight: 400; }

.ledger-waiting-hint {
  font-size: 12px;
  color: var(--ink-faint);
}

/*
 * An interview whose date has passed. Same accent and the same reasoning as a wait
 * of three weeks: it is a row worth a second look, not a row in an error state.
 */
.ledger-waiting-hint.is-overdue { color: var(--accent); }

/*
 * The editable date, in the Rejected and Interviewing columns.
 *
 * Sized to its content rather than stretched: a date input given a whole column is a
 * wide empty box that reads as a form to fill in, where these are mostly already
 * answered and occasionally corrected. Borderless until it is hovered or focused, so
 * a column of them reads as dates rather than as fifty controls.
 */
.ledger-date-input {
  padding: 3px 6px;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: transparent;
  color: var(--ink-body);
  font: inherit;
  font-size: 14px;
  font-weight: 500;
  text-align: right;
}

.ledger-date-input:hover:not(:disabled) { border-color: var(--border-input); }

.ledger-date-input:focus-visible {
  border-color: var(--border-input);
  background: var(--surface);
}

/*
 * An empty one has to look like somewhere to type, or it looks like nothing at all.
 * The class comes from the page rather than `:placeholder-shown`, which does not
 * match a date input, and `:invalid`, which an empty optional one is not.
 */
.ledger-date-input.is-empty { border-color: var(--border-input); }

.ledger-date-input:disabled { opacity: 0.6; }

/* The row's own disclosure spans all four columns beneath them. */
.ledger-detail {
  grid-column: 1 / -1;
  margin-top: 6px;
}

.result-unswept {
  margin: 4px 0 0;
  font-size: 13px;
  color: var(--ink-faint);
}

.add-application {
  margin-bottom: 20px;
}

.add-application-title {
  margin: 0 0 14px;
  font-size: 17px;
  font-weight: 600;
}

.button-secondary {
  padding: 10px 18px;
  border: 1px solid var(--border-input);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: 15px;
  cursor: pointer;
}

.button-secondary:hover {
  background: var(--bg);
  border-color: var(--muted);
}

/* Searches --------------------------------------------------------------------
   One card per search, and one hierarchy of action inside it: a filled primary,
   two outlined secondaries, and destroy as a text link at the far end. All three
   used to be identically sized filled buttons, with the destructive one both the
   widest target and the rightmost — the most inviting thing on the card was the
   one that could not be undone.
*/
.search-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 14px;
}

.search-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-nested);
  padding: 24px 26px;
}

.search-card-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
}

.search-name {
  margin: 0;
  font-size: 21px;
  font-weight: 600;
  letter-spacing: -0.02em;
}

.pill {
  padding: 4px 12px;
  border-radius: var(--radius-pill);
  font-size: 13px;
  font-weight: 500;
}

.pill[data-state="running"] { background: var(--success-tint); color: var(--success-ink); }
.pill[data-state="paused"] { background: var(--neutral-tint); color: var(--neutral-ink); }

/* Between two hairlines, and wrapping two-up so a long title list does not force
   a fifth column nobody asked for. */
.criteria-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 16px 28px;
  margin: 18px 0;
  padding: 18px 0;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}

.criteria-strip > div {
  flex: 1 1 calc(50% - 14px);
  min-width: 12.5rem;
}

.criteria-strip dt {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}

.criteria-strip dd {
  margin: 4px 0 0;
  font-size: 16px;
  color: var(--text);
}

.search-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
}

/* Pushed to the far end, away from the actions somebody actually came to use. */
.search-delete-slot {
  display: flex;
  gap: 14px;
  margin-left: auto;
}

.link-action.is-destructive { color: var(--error); font-weight: 550; }

.button-primary {
  padding: 10px 18px;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: var(--accent);
  color: var(--accent-text);
  font: inherit;
  font-size: 15px;
  font-weight: 500;
  cursor: pointer;
}

.button-primary:hover { background: var(--accent-hover); }

/* Forms -----------------------------------------------------------------------
   No fieldset borders. The notched 1px box a browser draws around a <legend> was
   the strongest single signal of unfinished work on the site. The grouping stays —
   it is real, and a checkbox set still needs a legend to be announced as a set —
   it is just drawn as a heading in a left column instead of as chrome.
*/
.form-card {
  padding: 30px 34px;
  border-radius: var(--radius-card);
}

.form-card fieldset {
  margin: 0;
  padding: 0;
  border: 0;
}

.form-card legend {
  padding: 0;
  font-size: 14px;
  font-weight: 550;
}

.form-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px;
  padding-bottom: 22px;
  border-bottom: 1px solid var(--border);
}

.eyebrow {
  display: block;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
}

/* Reads as the title but is the field. The name used to be a section called
   "Search Name" containing one field called "Name". */
.title-input {
  width: 100%;
  min-width: 16rem;
  margin-top: 4px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 27px;
  font-weight: 600;
  letter-spacing: -0.025em;
}

.title-input::placeholder { color: var(--ink-faint); }

.title-input:focus {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
  border-radius: 4px;
}

.form-header-name { flex: 1 1 20rem; }

.form-header-title {
  margin: 4px 0 0;
  font-size: 27px;
  font-weight: 600;
  letter-spacing: -0.025em;
}

.form-header-actions {
  display: flex;
  gap: 10px;
}

.form-group {
  display: grid;
  grid-template-columns: 190px minmax(0, 1fr);
  gap: 40px;
  padding: 30px 0;
  border-bottom: 1px solid var(--border);
}

.form-group-head h3 {
  margin: 0;
  font-size: 17px;
  font-weight: 600;
}

.form-group-head p {
  margin: 6px 0 0;
  font-size: 14px;
  color: var(--ink-faint);
}

.form-group-fields {
  display: flex;
  flex-direction: column;
}

.form-group-fields label { margin-top: 20px; }
.form-group-fields > :first-child { margin-top: 0; }
.form-group-fields .help { margin: 6px 0 0; }

.checkset { margin-top: 20px !important; }
.checkset legend { margin-bottom: 8px; }

/* The regex disclosure. A text link rather than a triangle, per the brief: the
   glyph is one more thing rendering differently on every platform, and the words
   already say that something opens. */
.expert summary {
  margin-top: 20px;
  color: var(--accent);
  font-size: 14px;
  cursor: pointer;
  list-style: none;
}

.expert summary::-webkit-details-marker { display: none; }
.expert summary::marker { content: ""; }
.expert summary:hover { color: var(--accent-hover); text-decoration: underline; }

.form-footnote {
  margin: 20px 0 0;
  font-size: 14px;
  color: var(--ink-faint);
}

/* Empty states ----------------------------------------------------------------
   Not in the handoff, and needed by all three pages. An empty list is where a
   person is most likely to be new, and a one-line status saying "no matches yet"
   answers none of what they are actually asking.
*/
.empty-state {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 44px 34px;
  text-align: center;
}

.empty-state h2 {
  margin: 0;
  font-size: 21px;
  font-weight: 600;
  letter-spacing: -0.02em;
}

.empty-state p {
  margin: 12px auto 0;
  max-width: 48ch;
  font-size: 16px;
  line-height: 1.6;
  color: var(--ink-body);
}

.empty-state-alt { margin-top: 20px !important; }

/* Narrow viewports ------------------------------------------------------------
   The one place the design needs breakpoints. Everything else on the site reflows
   on flex-basis, but the two ledgers are fixed-column grids — four named columns
   whose headings sit in a separate row — and a grid like that cannot wrap into
   something readable. Below 760px each row becomes a stack and the column
   headings, which now label nothing, are taken out of the flow.

   760 rather than 700: the four-column ledger runs out of room for a job title
   before the viewport runs out of pixels.
*/
@media (max-width: 47.5rem) {
  .match-row {
    grid-template-columns: 52px minmax(0, 1fr);
    gap: 14px;
  }

  /* The actions move under the body rather than beside it, still in the second
     column so they line up with the title instead of with the score. */
  .match-actions {
    grid-column: 2;
    align-items: flex-start;
    margin-top: 4px;
  }

  .match-actions select { width: 100%; }

  .ledger-head { display: none; }

  .ledger-row {
    grid-template-columns: minmax(0, 1fr);
    gap: 10px;
  }

  /* Stacked, the date needs the label the header row used to carry. */
  .ledger-applied::before {
    content: "Applied ";
    color: var(--ink-faint);
  }

  .ledger-waiting {
    align-items: flex-start;
    text-align: left;
    flex-direction: row;
    gap: 8px;
  }

  /* Left-aligned with everything else once the row stacks, and given its border
     back: with no column header above it, an unadorned date is unexplained. */
  .ledger-date-input {
    text-align: left;
    margin-left: -6px;
    border-color: var(--border-input);
  }

  .ledger-status select { width: 100%; max-width: 16rem; }

  /* The two-column form group stacks; its left column becomes a heading above. */
  .form-group {
    grid-template-columns: minmax(0, 1fr);
    gap: 18px;
  }

  .form-header { align-items: stretch; }
  .form-header-actions { justify-content: flex-end; }

  .criteria-strip > div { flex: 1 1 100%; }

  .search-delete-slot { margin-left: 0; }

  .page-head { padding-top: 28px; }

  /*
   * The nav wraps under the wordmark here rather than at 560. Four labels plus an
   * avatar stop fitting beside the wordmark at about 620px, and between there and
   * 560 the bar was overflowing the viewport by the width of the avatar — which
   * showed up as a horizontal scrollbar on every page, not as a visibly broken bar.
   */
  .app-bar-inner,
  .landing-bar-inner {
    flex-wrap: wrap;
    gap: 10px 16px;
  }

  .app-nav,
  .landing-nav { flex-wrap: wrap; }
}

/* Phones. The app bar keeps its height — that is the point of it — but the nav
   wraps under the wordmark rather than overflowing, and the labels tighten. */
@media (max-width: 35rem) {
  .app-nav { gap: 16px; font-size: 14px; }
  .landing-nav { gap: 16px; }

  .pipeline { grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); }

  .form-card { padding: 22px 20px; }
  .matches, .ledger { padding: 0 18px; }
  .search-card { padding: 20px; }
}

/* Leftovers -------------------------------------------------------------------
   Small rules the redesigned pages need and the pages it has not reached still
   depend on. `.results` and `.result` are the pre-redesign list and card: Matches
   and Applications no longer use them, but runs.html does, and removing them with
   the pages that stopped needing them left its list rendering as bulleted text.
*/
.results {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 14px;
}

.result { margin: 0; }

/* The heading and its status line, as one flex child so the control on the other
   side of the head row cannot be pulled up between them. */
.page-head-titles {
  min-width: 0;
  flex: 1 1 20rem;
}

/* `minmax(0, 1fr)` sets the track, but a grid child still defaults to min-content
   width — without this a long unbroken job title widens the column past its share
   and pushes the actions off the row. */
.match-body,
.ledger-role {
  min-width: 0;
}

.match-title,
.ledger-title,
.ledger-where,
.match-where { overflow-wrap: anywhere; }

/* Pagination -----------------------------------------------------------------
   The page buttons sit between Previous and Next and wrap rather than scroll: a
   result set large enough to need thirty pages is one where the numbers matter
   least, and a row that scrolls sideways on a phone hides the control it holds. */
.pages {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  list-style: none;
  margin: 0;
  padding: 0;
  justify-content: center;
}

.pages button {
  min-width: 2.25rem;
  padding: 0.25rem 0.5rem;
}

/* The page you are on is a statement, not an offer. Marked with aria-current so it
   is announced as such, and styled from that attribute rather than a class so the
   two can never disagree. */
.pages button[aria-current="page"] {
  font-weight: 600;
  border-color: currentColor;
}

.pages .ellipsis {
  padding: 0.25rem 0.25rem;
  opacity: 0.7;
}

.pager-count {
  text-align: center;
  margin-top: 0.5rem;
}

/* Applications ---------------------------------------------------------------
   The tallies answer the question a person opens this page with — "how many have
   I applied to?" — so they are the first thing on it and are counted over the
   whole ledger rather than the page being shown. */
.tallies {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  list-style: none;
  margin: 0 0 1rem;
  padding: 0;
}

/* Each tally is a button, so it inherits focus handling and keyboard operation from
   the platform rather than from anything written here. */
.tally {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 5.5rem;
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--border, currentColor);
  border-radius: 0.5rem;
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
}

.tally:hover {
  border-color: currentColor;
}

/* Styled from aria-pressed rather than a class: the state a screen reader announces
   and the state a sighted person sees are then the same fact, not two that can
   drift. */
.tally[aria-pressed="true"] {
  border-color: currentColor;
  border-width: 2px;
  /* Compensating for the thicker border, so the row does not jog when one is
     selected. */
  padding: calc(0.5rem - 1px) calc(0.75rem - 1px);
  font-weight: 600;
}

.tally-count {
  font-size: 1.5rem;
  font-weight: 600;
  line-height: 1.1;
}

.tally-label {
  font-size: 0.8rem;
  opacity: 0.75;
  text-align: center;
}

/* A definition list rather than a table: these are labelled facts about one
   application, not a grid to be scanned across rows. */
.application-detail {
  margin: 0.5rem 0 0;
}

.application-detail > div {
  display: flex;
  gap: 0.5rem;
  padding: 0.15rem 0;
}

.application-detail dt {
  flex: 0 0 7rem;
  font-weight: 600;
  opacity: 0.8;
}

.application-detail dd {
  margin: 0;
  /* Evidence strings are long and unbroken; letting them overflow would push the
     card wider than the page on a phone. */
  min-width: 0;
  overflow-wrap: anywhere;
}

/* An application to a posting the catalogue never held. Stated rather than left to
   be inferred, because its absence from Matches is correct and looks like a bug. */
.result-unswept {
  margin: 0.25rem 0 0;
  opacity: 0.75;
}

/* The status control on an application row -----------------------------------
   A native select sizes to its longest option, so "Applied" and "No status
   recorded" gave every row a different width and a ragged right edge. Fixed
   width, since the control sits at the end of a flex row opposite the title —
   the results page gets away without this because its select is in a footer,
   where the edge is not visible. */
.application-set-status {
  flex: 0 0 auto;
  width: 11rem;
  padding: 0.25rem 0.5rem;
  font-size: 0.82rem;
  height: auto;
}

/* The title takes what is left, and its long links wrap rather than pushing the
   control off the row. */
.result-header .result-heading-wrap {
  flex: 1 1 auto;
  min-width: 0;
}

.result-header .result-title {
  overflow-wrap: anywhere;
}

/* Stacked on a narrow screen: 11rem of control beside a job title is most of a
   phone, and the two fighting for the same line is what made this look broken. */
@media (max-width: 32rem) {
  .result-header {
    flex-direction: column;
    align-items: stretch;
  }

  .application-set-status {
    width: 100%;
  }
}

/* The stored value for an application with no usable link. Long, unbroken, and
   otherwise able to widen the card past the page. */
.detail-url {
  margin: 0.35rem 0 0;
  font-size: 0.85rem;
  opacity: 0.75;
  overflow-wrap: anywhere;
}

/* Public job search (search.html) */

/*
 * The one page that is neither signed-in nor static, so it borrows from both: the
 * landing bar above it, the filter row and result list from the dashboard, and the
 * rules below for the parts neither already had.
 */

/*
 * The keyword box earns more width than the filters beside it — it is the field
 * people type a whole job title into, and the others take a word.
 *
 * Wider, and deliberately not growing: `flex-grow: 1` here absorbs every spare pixel
 * on the line, which pushed the submit button onto a line of its own at full desktop
 * width. A fixed basis that may shrink keeps the row intact where it fits and wraps
 * it where it does not.
 */
.filter-field-wide { flex: 0 1 20rem; }

/*
 * The narrow fields size to their basis rather than to their placeholder.
 *
 * `.filter-field input` is `width: auto`, so an input sizes to its content and a
 * placeholder reading "Any employer" made two of these 216px against a floor of 176.
 * Those 80 stray pixels were the whole of the overflow that pushed the submit button
 * onto a line of its own: the row wants 1,187px of a 1,124px form, and wrapping the
 * button is how flexbox reports that.
 *
 * Scoped to this form. The dashboard's filter row is the same class and has fewer
 * controls in it, so it has the room and has been laid out against having it.
 */
#search-form .filter-field { flex: 0 1 11rem; }
#search-form .filter-field-wide { flex: 0 1 20rem; }
#search-form .filter-field input,
#search-form .filter-field select { width: 100%; min-width: 0; }
#search-form .filter-field-check { flex: 0 0 auto; }
#search-form .filter-field-check input { width: 1.125rem; }

/*
 * A checkbox names itself by wrapping its label, so this one field runs along the
 * line rather than stacking a caption above a control. The padding replaces the
 * height the other fields get from their captions, which is what keeps this one on
 * the same baseline as the inputs beside it.
 */
.filter-field-check {
  align-self: center;
  padding-top: 18px;
}

.filter-field-check label {
  display: flex;
  align-items: center;
  gap: 8px;
  /* Not the uppercase caption the stacked fields use: this text is the control's
     name, read inline, and letter-spaced small caps are hard work at reading size. */
  font-size: 15px;
  font-weight: 400;
  letter-spacing: normal;
  text-transform: none;
  color: var(--text);
}

.filter-field-check input {
  width: 1.125rem;
  height: 1.125rem;
  min-width: 0;
  margin: 0;
  accent-color: var(--accent);
}

#search-submit { align-self: center; margin-top: 18px; }

/*
 * A search row, which is a match row with the two columns removed that need an
 * account: the fit score, and the status control. What is left is what the catalog
 * itself knows.
 */
.browse-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 22px;
  align-items: start;
  padding: 22px 0;
  border-bottom: 1px solid var(--border);
}

.browse-row:last-child { border-bottom: 0; }

.browse-row-side {
  display: flex;
  align-items: center;
  gap: 8px;
}

/*
 * Tinted rather than outlined, and paired with its own ink token — the palette holds
 * every tint together with a colour readable on it, so a badge is never a guess
 * about contrast.
 */
.remote-badge {
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  background: var(--accent-tint);
  color: var(--accent-tint-ink);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  white-space: nowrap;
}

/*
 * What an account is for, under the results rather than over them.
 *
 * Placement is the argument: the search above this band is complete and needs
 * nothing from it, so the band is an offer rather than a wall. A visitor who wants
 * only to look has already been served by the time they reach it.
 */
.signup-band {
  margin-top: 34px;
  padding: 38px 34px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  text-align: center;
}

.signup-band h2 {
  margin: 0;
  font-size: 1.5rem;
  letter-spacing: -0.02em;
}

.signup-points {
  display: flex;
  flex-wrap: wrap;
  gap: 22px;
  justify-content: center;
  margin: 26px 0 0;
  padding: 0;
  list-style: none;
  text-align: left;
}

/* Wrapping two-up before one-up — never a track count that can leave one of three
   items alone on a row, which is the flaw the landing page was fixed for. */
.signup-points li {
  flex: 1 1 15rem;
  max-width: 21rem;
  padding: 18px 20px;
  background: var(--surface-subtle);
  border-radius: var(--radius-nested);
}

.signup-points h3 {
  margin: 0;
  font-size: 1rem;
}

.signup-points p {
  margin: 6px 0 0;
  font-size: 14px;
  color: var(--ink-body);
}

@media (max-width: 34rem) {
  /* The submit button stops being one control among several on a line and becomes
     the thing you press, so it takes the width rather than sitting orphaned. */
  #search-submit {
    width: 100%;
    margin-top: 6px;
  }

  .filter-field-check { padding-top: 6px; }

  .signup-band { padding: 28px 20px; }
}

/*
 * Two actions in the hero, since searching stopped requiring an account.
 *
 * A flex row rather than two inline-blocks: inline-block would space them by the
 * whitespace between the tags, which is a gap nobody chose and which disappears when
 * the markup is reformatted. `wrap` because at phone width two 16px buttons do not
 * fit on one line, and the second one dropping is better than either shrinking.
 */
/*
 * `inline-flex`, and the choice is not cosmetic.
 *
 * `display: flex` made this a block-level flex container, and a flex container
 * ignores the `text-align: center` it inherits — its items are placed by
 * `justify-content`, which defaults to the start. Three of the four places this
 * class is used sit inside centred sections (the landing page's closing band, the
 * search page's sign-up band), and all three had their button jump to the left edge.
 * The hero is the only left-aligned one, so hard-coding `justify-content: center`
 * would have moved the break rather than fixed it.
 *
 * An inline-level box is laid out by the text alignment of whatever contains it and
 * still arranges its own children as a flex row — which is exactly the pair of
 * behaviours wanted, in one property.
 */
.hero-actions {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
}

/*
 * `.button-large:hover` sets the text to --accent-text, which is white — correct for
 * the filled button it was written for, and invisible on the outlined one, whose
 * background is --surface. The pairing only became possible when a second action
 * appeared beside the first, so this is the first time it could be wrong.
 */
.button-secondary.button-large {
  padding: 14px 26px;
  font-size: 16px;
}

.button-secondary.button-large:hover {
  color: var(--text);
  background: var(--bg);
}

/* Profile: resume and scoring terms -------------------------------------------
   Two cards above the background form. The resume card is upload, current file and
   the paste fallback; the scoring card is the weighted terms fit reads, laid out as
   tables because each row is a term with two or three settings a person compares
   down the column. */

.profile-section { margin: 0 0 1.5rem; }
.profile-section h2 { margin-bottom: 0.4rem; }

.resume-current {
  margin: 0 0 1.2rem;
  padding: 0.9rem 1rem;
  background: var(--surface-subtle);
  border-radius: var(--radius);
}
.resume-file { margin: 0 0 0.6rem; overflow-wrap: anywhere; }
.resume-meta { color: var(--muted); font-size: 0.9rem; margin-left: 0.4rem; }
.resume-actions { display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: center; margin: 0; }
.resume-actions .button-secondary { padding: 0.45rem 0.9rem; font-size: 0.9rem; }
.resume-text {
  margin: 0.9rem 0 0;
  max-height: 22rem;
  overflow: auto;
  padding: 0.8rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: 0.85rem;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.resume-paste { margin: 0 0 0.5rem; }
.resume-paste summary { cursor: pointer; color: var(--accent); font-weight: 600; margin-bottom: 0.6rem; }
.resume-paste textarea { margin-bottom: 0.6rem; }

.scoring-empty { color: var(--muted); }
.scoring-suggestion {
  margin: 0 0 1.2rem;
  padding: 0.8rem 1rem;
  background: var(--accent-tint);
  color: var(--accent-tint-ink);
  border-radius: var(--radius);
}
.scoring-suggestion p { margin: 0 0 0.6rem; }

.term-heading { font-size: 1rem; margin: 1.4rem 0 0.5rem; }
.term-table { width: 100%; border-collapse: collapse; font-size: 0.95rem; }
.term-table th {
  text-align: left;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--muted);
  padding: 0 0.5rem 0.4rem 0;
  border-bottom: 1px solid var(--border);
}
.term-table td { padding: 0.35rem 0.5rem 0.35rem 0; border-bottom: 1px solid var(--surface-muted); vertical-align: middle; }
.term-table td:first-child { overflow-wrap: anywhere; }
.term-table select { width: auto; padding: 0.3rem 0.4rem; }
.term-table input[type="checkbox"] { width: auto; margin: 0; }
.term-table tr[data-avoid="true"] td:first-child { color: var(--error); }
.term-remove {
  padding: 0.25rem 0.5rem;
  color: var(--muted);
  background: transparent;
  border: 1px solid transparent;
  font-weight: 400;
}
.term-remove:hover { color: var(--error); border-color: var(--border); }
.term-add { margin: 0.8rem 0 0; }
.term-add label { font-size: 0.9rem; }
.term-add-row { display: flex; gap: 0.5rem; }
.term-add-row input { flex: 1; min-width: 0; }
