/* 2F: app flow, in the local tool's look (tool/public/style.css). Colour carries meaning only
   (grade bands, verdicts, tags); text always says it too. app-a11y.test.js checks the 4.5:1
   pairs listed next.
   contrast-pairs: --ok on --ok-bg; --risk-ink on --risk-bg; --blocker on --blocker-bg; --unknown on --unknown-bg; --manual-ink on --manual-bg; --on-band on --ok; --on-band on --risk; --on-band on --blocker; --on-band on --grade-good; --grade-mid-ink on --grade-mid; --on-band on --grade-low; --blocker on --panel; --risk-ink on --panel; --on-band on --unknown; --on-band on --danger */
:root {
  --ok: #1f7a45; --ok-bg: #e6f4ec;
  --risk: #9a6608; --risk-bg: #fdf3df; --risk-ink: #8f5f07;
  --blocker: #b3261e; --blocker-bg: #fdecea;
  --unknown: #5a626c; --unknown-bg: #eceff3;
  --manual: #b8570b; --manual-bg: #fdeedd; --manual-ink: #a24c09;
  /* The small list badge: flat. The local tool's #1f9a55 is 3.6:1 under white, so this is darker. */
  --grade-good: #1a8049; --grade-mid: #f5c400; --grade-mid-ink: #4a3500; --grade-low: #d7372b;
  /* White type on the meaning colours (verdict pills, grade bands); the brand accent carries
     paper type (--on-accent). */
  --on-band: #ffffff;
}
.visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* ------------------------------------------------------------------ top bar */
.top a { color: var(--on-bar); }
.top nav { display: flex; flex-wrap: wrap; gap: 2px; margin-right: auto; }
.top nav a {
  display: inline-flex; align-items: center; min-height: 32px; padding: 4px 10px; border-radius: var(--r-control);
  font-size: var(--t-sm); font-weight: 500; text-decoration: none;
}
.top nav a:hover { background: var(--on-bar-tint); }
.top nav a[aria-current="page"] { background: var(--on-bar-tint-strong); box-shadow: inset 0 -2px 0 var(--on-bar); font-weight: 600; }
.top .credits {
  display: inline-flex; align-items: center; min-height: 28px; padding: 2px 10px; border-radius: var(--r-pill);
  border: 1px solid var(--on-bar-edge); font-size: var(--t-xs); font-weight: 600; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.top .buy, .top button.quiet {
  display: inline-flex; align-items: center; min-height: 32px; margin: 0; padding: 4px 12px; border-radius: var(--r-pill);
  border: 1px solid var(--on-bar-edge); background: transparent; color: var(--on-bar);
  font: inherit; font-size: var(--t-xs); font-weight: 600; text-decoration: none; white-space: nowrap; box-shadow: none;
}
.top .buy:hover, .top button.quiet:not(:disabled):hover { background: var(--on-bar-tint); border-color: var(--on-bar); }
/* The account menu (header.js accountMenu): a 44px person icon at the right of the bar. The
   negative block margin keeps the 44px target without making the bar taller than its 32px
   controls did. The list opens under it, right-aligned, on the page's own panel colours. */
.top .account-menu { position: relative; margin: -6px -6px -6px 0; }
.top button.icon-btn {
  display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; min-height: 44px;
  margin: 0; padding: 0; border: 0; border-radius: var(--r-pill); background: transparent; color: var(--on-bar); box-shadow: none;
}
.top button.icon-btn:not(:disabled):hover, .top button.icon-btn[aria-expanded="true"] { background: var(--on-bar-tint); }
/* Inside the circle, so the ring stays clear of the 56px bar's edge. */
.top button.icon-btn:focus-visible { outline-offset: -3px; }
.top .account-icon { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
.top .account-panel {
  position: absolute; right: 0; top: calc(100% + 4px); z-index: 20; min-width: 200px; padding: 4px;
  background: var(--panel); color: var(--ink); border: 1px solid var(--line); border-radius: var(--r-control);
  box-shadow: var(--shadow-pop);
}
.top .account-list [role="menuitem"] {
  display: flex; align-items: center; width: 100%; min-height: 44px; margin: 0; padding: 0 12px; border: 0; border-radius: var(--r-control);
  background: transparent; color: var(--ink); box-shadow: none; font: inherit; font-size: var(--t-sm); font-weight: 500;
  text-align: left; text-decoration: none; cursor: pointer;
}
.top .account-list [role="menuitem"]:hover { background: var(--panel-2); }
.top .account-list [role="menuitem"]:focus-visible { outline: 3px solid var(--focus); outline-offset: -3px; background: var(--panel-2); }
/* The credits count (header.js accountMenu): information, not an action, so a plain line above
   the items. It is the only count on a phone, where the bar has no room for one. */
.top .account-credits {
  margin: 0 0 4px; padding: 8px 12px; border-bottom: 1px solid var(--line);
  color: var(--ink-dim); font-size: var(--t-xs); font-weight: 600; line-height: 1.4; white-space: nowrap;
}
/* The build stamp (the footer's, read by header.js): information, not an action, so quiet. */
.top .account-stamp {
  margin: 4px 0 0; padding: 8px 12px 6px; border-top: 1px solid var(--line);
  color: var(--ink-dim); font-size: var(--t-xs); line-height: 1.4; font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* Pinned on a desktop so the way back to the list is always one click away. Not on a phone,
   where the wrapped bar would take too much of the screen; scroll-padding keeps a focused
   control from sliding under it. */
@media (min-width: 641px) {
  header.top { position: sticky; top: 0; z-index: 10; }
  html { scroll-padding-top: 120px; }
}
/* How much of the window's top the pinned bars cover, for everything that parks under them
   (the resume editor's bar, the review panel, the job bar below). --top-h is the top bar:
   56px from 641px up (measured 2026-10-05 at 641, 660, 680, 1280 and 1440; it no longer
   wraps), and 0 on a phone, where it scrolls away. On a job screen the compact job bar adds
   --job-bar-h. */
:root { --top-h: 56px; --job-bar-h: 48px; --sticky-h: var(--top-h); --re-sticky-top: var(--sticky-h); }
/* The job bar counts only where it can ever show: it is drawn by a scroll-driven animation, so a
   browser without them never shows it and nothing should park below an empty band. The resume
   editor's bar sits flush under it (no gap, owner feedback 2026-10-05). */
@supports (animation-timeline: view()) {
  html:has(.job-sticky) { --sticky-h: calc(var(--top-h) + var(--job-bar-h)); scroll-padding-top: calc(var(--sticky-h) + 16px); }
}
@media (max-width: 640px) {
  :root { --top-h: 0px; }
}
@media (max-width: 640px) {
  /* One row, 56px like a desktop: the mark, the nav, the account button. The credits count and
     Buy credits are in the account menu (header.js), so the bar leaves them out here. */
  .top { gap: 8px; }
  .top nav { flex-wrap: nowrap; }
  .top nav a { min-height: 44px; padding: 4px 8px; }
  .top .credits, .top .buy { display: none; }
}
/* The narrowest phones keep that one row by setting the name and the nav a little tighter
   (measured 2026-10-16 in Chrome at 360 and 320 with overlay scrollbars). */
@media (max-width: 400px) {
  .top { gap: 6px; }
  .top .brand { font-size: 16px; gap: 6px; }
  .top .brand::before { width: 30px; height: 21px; }
  .top nav a { padding: 4px 6px; }
}
@media (max-width: 359px) {
  .top { gap: 4px; }
  .top .brand { font-size: 14px; gap: 4px; }
  .top .brand::before { width: 26px; height: 18px; }
  .top nav a { min-width: 44px; justify-content: center; padding: 4px; }
}

/* ------------------------------------------------------------------ layout
   One content width everywhere (main, up to 1360px, app.css --page-max). A form screen is a white card, 640px, centred. */
.view.narrow, main > .setup, main > .unlock, main > .restore, main > .settings, main > section:not([class]) {
  max-width: 640px; margin: 0 auto;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-card);
  /* The one card on these screens, so the one raised one. */
  box-shadow: var(--shadow-card); padding: 20px 22px;
}
/* Settings' two sections (settings.js settingsView), divided by a rule. */
.settings .settings-group + .settings-group { margin-top: 24px; padding-top: 4px; border-top: 1px solid var(--line); }
.view.narrow .panel, .settings .panel { box-shadow: none; background: var(--panel-2); margin-top: 16px; }
.view.narrow > :last-child, .setup > :last-child, .unlock > :last-child, .restore > :last-child, .settings > :last-child { margin-bottom: 0; }
/* The master import, file first (views/resume.js renderImport, 2026-10-07): the picker, a quiet
   Paste the text instead, and a chosen file's review with its page drawn. 44px targets. */
.import-view button { min-height: 44px; }
/* A file picker drawn as a drop zone (settings.js fileDropZone: the import screen, the local
   import, the restore view). The real input is visually hidden but still the control, so the
   zone shows its focus; .is-over while a file is dragged over it. */
.drop-zone {
  position: relative; margin: 14px 0; padding: 24px; text-align: center;
  border: 1px dashed var(--line-strong); border-radius: var(--radius); background: var(--panel);
}
.drop-zone.is-over { background: var(--accent-soft); border-color: var(--accent); }
.drop-zone:has(input:focus-visible) { outline: 3px solid var(--focus); outline-offset: 2px; }
.drop-zone .field { margin: 0; }
.drop-zone label { margin: 0 0 4px; }
.drop-zone .hint { margin: 0 0 12px; }
.drop-zone button.secondary { margin: 0; }
/* The hidden input keeps no size of its own (the base field rules give it width and height). */
.drop-zone input[type="file"].visually-hidden { width: 1px; min-height: 0; height: 1px; padding: 0; border: 0; }
.import-choose .drop-zone { margin-bottom: 8px; }
.import-review { margin-top: 16px; }
.import-file-name { font-weight: 600; margin: 0 0 4px; overflow-wrap: anywhere; }
.import-review .resume-preview { margin: 12px 0; }
.import-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.import-paste { margin-top: 16px; }

.field { margin: 14px 0; }
.field label { margin: 0 0 4px; }
.field-check { display: flex; align-items: center; gap: 10px; }
.field-check label { margin: 0; font-weight: 500; }
.field-check input { width: 20px; height: 20px; flex: none; }
.field-check .hint, .field-check .field-error { flex-basis: 100%; }
.field-check { flex-wrap: wrap; }
.hint { color: var(--ink-dim); font-size: var(--t-xs); margin: 2px 0 6px; }
.field-error { color: var(--blocker); font-weight: 600; font-size: var(--t-sm); margin: 4px 0 0; }
.empty { color: var(--ink-dim); }

.view button, .view a.button { margin: 4px 8px 4px 0; }
.view a.button {
  display: inline-flex; align-items: center; min-height: 40px; padding: 8px 18px; border-radius: var(--r-pill);
  border: 1px solid var(--line-strong); background: var(--panel); color: var(--ink); font-weight: 500;
  text-decoration: none;
}
.view a.button:hover { background: var(--panel-2); border-color: var(--ink-faint); }
.view a.button.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.view a.button.primary:hover { background: var(--accent-strong); border-color: var(--accent-strong); }
@media (max-width: 767px) { .view a.button { min-height: 44px; } }
/* quiet: the local tool's ghost button. */
button.quiet { background: transparent; border-color: transparent; color: var(--accent); box-shadow: none; }
button.quiet:not(:disabled):hover { background: var(--hover); border-color: transparent; }
/* A quiet button that starts its row, or ends a stack, sits on the column's edge like the text
   around it (design system, 2026-10-26: one shared rule, so no screen needs its own override).
   The import picker's Paste the text instead follows the drop zone, so it is matched as a
   child. :where keeps it at a button's own weight, so a screen can still place one. */
:where(.actions, .next-actions, .import-choose, .import-paste, .unlock-foot, .first-fix-actions, .card-actions, .rv-card-links, .paste-choice) > button.quiet:first-child,
:where(section, .panel, form, fieldset, details, li, .field, .card, .rl-card, .mc-card) > button.quiet:last-child,
.import-choose > .drop-zone + button.quiet { padding-left: 0; padding-right: 0; }
/* A hint under a row of buttons keeps a little air from them. */
/* A note about the buttons above it reads as a paragraph after them (design system 2026-10-26). */
:is(.actions, .next-actions, .import-actions) + :is(.hint, .muted) { margin-top: 12px; }
/* 44px targets on a phone or a small tablet, on every screen in main (Settings, onboarding and
   restore are not .view) and for fold summaries; the design review measured 24 to 37px. */
@media (max-width: 767px) {
  main button:not(.icon-btn):not(.padtool), main a.button, main summary, .top button:not(.icon-btn) { min-height: 44px; }
  main summary { display: flex; align-items: center; }
  main .job-status-mark > summary { display: inline-flex; }
}
/* Unlock screen (2026-10-15): a narrow centred card in the shape of a password manager's
   unlock. Head centred, the passkey one full-width button, "or" rule, the passphrase field
   with Unlock on the same row, then quiet links in a footer. */
main > .unlock { max-width: 420px; padding: 32px 28px 20px; }
.unlock-head { text-align: center; margin-bottom: 24px; }
.unlock-head h1 { margin: 12px 0 6px; }
.unlock-head p { margin: 0; text-wrap: balance; }
@media (min-width: 768px) { main > .unlock { margin-top: 6vh; } }
.unlock .unlock-primary { width: 100%; min-height: 44px; margin: 0; font-size: var(--t-sm); }
.unlock-or { display: flex; align-items: center; gap: 12px; margin: 20px 0; color: var(--ink-dim); font-size: var(--t-xs); }
.unlock-or::before, .unlock-or::after { content: ""; flex: 1; border-top: 1px solid var(--line); }
.unlock-pp { margin: 0; }
.unlock-pp label { margin: 0 0 6px; }
.unlock-row { display: flex; gap: 8px; align-items: stretch; }
.unlock-row input { flex: 1; min-width: 0; margin: 0; min-height: 44px; }
.unlock-row button { margin: 0; min-height: 44px; flex: none; }
.unlock-pp .hint { margin: 6px 0 0; text-wrap: pretty; }
/* Both messages: the error under the form and the "Waiting for your passkey" status right
   under the passkey button (owner, 2026-10-19: with no gap it read as a UI bug). */
.unlock .message { margin: 12px 0 0; }
.unlock-foot { margin-top: 24px; padding-top: 16px; border-top: 1px solid var(--line); text-align: center; font-size: var(--t-sm); }
.unlock-foot > * { margin: 0 0 8px; }
.unlock-foot button.link { margin: 0; }
.unlock-lost[open] { text-align: left; }
.unlock-lost p { margin: 8px 0; }
.unlock .signed-in { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 4px 12px; color: var(--ink-dim); margin: 8px 0 0; }
.warn { background: var(--risk-bg); color: var(--risk-ink); padding: 8px 12px; border-radius: var(--r-control); border-left: 5px solid var(--risk); }
dialog.ai-dialog {
  max-width: 32rem; background: var(--panel); color: var(--ink); border: 1px solid var(--line);
  border-radius: var(--r-card); padding: 20px 22px; box-shadow: var(--shadow-pop);
}
dialog.ai-dialog::backdrop { background: rgba(33, 28, 22, 0.4); }
dialog.ai-dialog h2 { margin-top: 0; }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; scroll-behavior: auto !important; }
}
/* Signup: birth month and year side by side, stacked on a narrow phone. */
.dob-row { display: flex; gap: 12px; }
.dob-row .field { flex: 1 1 0; min-width: 0; }
@media (max-width: 399px) { .dob-row { flex-direction: column; gap: 0; } }
pre.master-text, pre.posting-text {
  white-space: pre-wrap; overflow-wrap: anywhere; max-height: 28rem; overflow: auto; padding: 12px 14px;
  border: 1px solid var(--line); border-radius: var(--r-control); background: var(--panel-2); color: var(--ink);
  font: var(--t-xs)/1.55 var(--font-mono);
}
.nudge { border: 1px solid var(--accent); background: var(--accent-soft); color: var(--ink); border-radius: var(--r-control); padding: 10px 14px; margin: 12px 0; }

/* ------------------------------------------------------------------ job list */
.chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 16px 0 12px; }
.view button.chip {
  min-height: 32px; margin: 0; padding: 3px 12px; border-radius: var(--r-pill); font-size: var(--t-xs);
  border: 1px solid var(--line); background: transparent; color: var(--ink-dim); box-shadow: none;
}
.view button.chip:not(:disabled):hover { background: var(--panel); border-color: var(--line-strong); }
/* Pressed or selected is ONE look everywhere (design system, 2026-10-26): the accent tint with
   the accent edge and accent text, never a fill, so the page keeps exactly one filled button.
   The job list's bucket chips read the same (their old solid fill is gone). */
button.chip[aria-pressed="true"], .view button.chip[aria-pressed="true"],
button[aria-pressed="true"]:is(.secondary, .chip):not(.quiet) { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); font-weight: 600; }
.chips + .field { max-width: 260px; margin: 0 0 14px; }
.chips + .field label { font-size: var(--t-xs); color: var(--ink-dim); }
/* The job list (redesign, 2026-10-21; owner: "confusing, cramped, and I'm unsure what things are
   / what to look at"). One column, then from 1100px a grid of cards at least 420px wide. A card:
   a header row (40px logo, "Company · Place", one status pill at the right), the role as the
   title (the link, stretched over the whole card by its ::after), the blurbs, a ruled row of
   LABELED stats (Resume grade, Fit, Pay), then a muted footer line. No Archive or More on the
   card (they live on the job page). Every line wraps; only the title is clamped to two lines,
   its full text still in the DOM. */
.job-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; }
@media (min-width: 1100px) { .job-list { grid-template-columns: repeat(auto-fill, minmax(420px, 1fr)); gap: 16px; } }
.job-list-head { display: none; }
.job-card {
  --card-logo: 40px;
  position: relative; display: grid; grid-template-columns: var(--card-logo) minmax(0, 1fr); align-content: start; gap: 10px 12px; min-width: 0; padding: 20px;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-card);
  box-shadow: var(--shadow-rest, 0 1px 2px rgba(33, 28, 22, 0.05), 0 2px 6px rgba(33, 28, 22, 0.04));
  transition: transform var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}
.job-card:hover, .job-card:focus-within {
  transform: translateY(-2px);
  box-shadow: var(--shadow-hover, 0 2px 4px rgba(33, 28, 22, 0.06), 0 12px 28px rgba(33, 28, 22, 0.12));
}
@media (prefers-reduced-motion: reduce) { .job-card:hover, .job-card:focus-within { transform: none; } }
/* The focus ring is drawn on the card, since the link's hit area is the whole card. */
.job-card:has(.card-main:focus-visible) { outline: 3px solid var(--focus); outline-offset: 2px; }
.job-card .card-main:focus-visible { outline: none; }
.job-card > .card-head, .job-card > .card-main, .job-card > .card-blurbs, .job-card > .card-stats, .job-card > .card-foot { grid-column: 1 / -1; }
.job-card .card-head { display: flex; align-items: center; gap: 12px; min-width: 0; }
.job-card .card-head > .logo { flex: 0 0 var(--card-logo); }
.job-card .company { flex: 1 1 auto; min-width: 0; font-size: var(--t-xs); line-height: 1.35; color: var(--ink-dim); overflow-wrap: anywhere; }
.job-card .card-main {
  /* The whole title, wrapped: never clamped (no clipped text, repo rule). */
  display: block;
  font-size: var(--t-md); font-weight: 600; line-height: var(--lh-md); color: var(--ink); text-decoration: none; overflow-wrap: anywhere;
}
.job-card .card-main::after { content: ''; position: absolute; inset: 0; border-radius: inherit; }
.job-card .card-main:hover { color: var(--ink); }
.job-card .card-blurbs { margin: -4px 0 0; font-size: 14px; line-height: 1.4; color: var(--ink-dim); overflow-wrap: anywhere; }
.job-card .blurb { color: var(--ink-dim); }
/* The stats: a small label over its value, three columns sized to their content. */
.job-card .card-stats { display: grid; grid-template-columns: max-content max-content minmax(0, 1fr); align-items: start; gap: 8px 28px; margin: 2px 0 0; padding: 12px 0 0; border-top: 1px solid var(--line); }
.job-card .stat { display: grid; align-content: start; gap: 4px; min-width: 0; }
.job-card .stat-label { margin: 0; font-size: 12px; font-weight: 500; line-height: 1.3; color: var(--ink-dim); }
.job-card .stat-value { margin: 0; display: flex; align-items: center; min-height: 26px; font-size: var(--t-sm); font-weight: 600; line-height: 1.35; color: var(--ink); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.job-card .stat-value .stat-none { font-size: 14px; font-weight: 400; color: var(--ink-dim); }
.job-card .stat-value .grade-letter, .job-card .stat-value .grade-progress { font-size: var(--t-xs); }
.job-card .stat-value .grade-held-card { font-size: var(--t-sm); font-weight: 500; color: var(--ink-dim); }
.job-card .stat-value .grade-progress { flex-wrap: nowrap; }
.job-card .stat-value .grade-letter { flex: none; white-space: nowrap; }
/* Review first: the one tag shape (views/jobs.js adds .tag .tag-neutral); it never wraps. */
.job-card .stat-value .grade-progress .gp-pending.tag { flex: none; max-width: none; border-style: solid; font-style: normal; white-space: nowrap; }
.job-card .stat-value .grade-held-card.tag { max-width: none; font-size: var(--t-eyebrow); font-weight: 600; color: var(--ink-dim); white-space: nowrap; }
.job-card .card-fit { font-variant-numeric: tabular-nums; white-space: nowrap; }
.job-card .card-foot { margin: 0; font-size: var(--t-xs); line-height: 1.4; color: var(--ink-dim); overflow-wrap: anywhere; }
/* The one status pill at the header's right: neutral outlined, Closed in red. */
.job-card .card-status-group { flex: 0 0 auto; margin-left: auto; display: inline-flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px; }
.job-card .card-status { flex: 0 0 auto; display: inline-block; font-size: var(--t-xs); line-height: 1.5; padding: 1px 10px; border-radius: var(--r-pill); white-space: nowrap; }
.job-card .card-status.sub, .job-card .card-status.app-stage { color: var(--ink-dim); border: 1px solid var(--line); }
.job-card .card-status.app-stage.is-interviewing, .job-card .card-status.app-stage.is-offer { color: var(--ink); border-color: var(--line-strong); font-weight: 500; }
/* A submitted job is done with, so it recedes (Rejected too, never red); archived recedes further.
   They recede by background and border, never opacity, so their text keeps 4.5:1 (WCAG 1.4.3). */
.job-card.recede { background: var(--panel-2); }
.job-card.archived { border-style: dashed; background: var(--panel-2); }
/* Is the posting still open: only Closed is coloured, on the card and in the job header. */
.job-card .tag-closed { font-weight: 600; color: var(--danger-strong); background: var(--danger-soft); border-color: var(--danger); }
/* Phone: Resume grade on its own row, Fit and Pay sharing the row below. */
@media (max-width: 639px) {
  .job-card { padding: 16px; }
  .job-card .card-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 12px; row-gap: 12px; }
  .job-card .card-stats > .stat-grade { grid-column: 1 / -1; }
}
/* The jobs title row: Add a job (a link drawn as the primary button) and More (a menu button)
   are the same height: the same line height, padding and minimum, 44px on a phone. */
.view .jobs-title-row .jobs-title-actions { align-items: center; }
.view .jobs-title-row .jobs-title-actions a.button, .view .jobs-title-row .jobs-title-actions .menu-wrap > button {
  box-sizing: border-box; min-height: 40px; padding-block: 8px; line-height: 1.3; }
@media (max-width: 767px) {
  .view .jobs-title-row .jobs-title-actions a.button, .view .jobs-title-row .jobs-title-actions .menu-wrap > button { min-height: 44px; }
}
/* Grid or List (2026-10-20): the toggle sits at the end of the controls row from 1100px (under
   it the grid is one column anyway, so the toggle and the list rules are off). List (2026-10-21)
   is one row per job in aligned columns under ONE header row: [logo, eyebrow and role] [Resume
   grade] [Fit] [Pay] [Status] [Posted]. The head and the rows share one template, so the columns
   line up exactly. The card's wrappers are display: contents, so their pieces become cells; the
   stat labels are visually hidden (the head names the columns), never display: none, so a screen
   reader still hears them. The blurbs are left out of a row; the requirements met and skills to
   confirm sit under the role. */
.jobs-layout { display: none; }
@media (min-width: 1100px) {
  .jobs-layout { display: inline-flex; gap: 4px; }
  .view .jobs-layout button.chip { margin: 0; }
  .view .jobs-layout button.chip[aria-pressed="true"] { background: var(--accent-soft); border-color: var(--accent); color: var(--accent-strong); }
  .jobs-layout-face { display: inline-flex; align-items: center; gap: 6px; }
  /* No Status column (owner, 2026-10-21: most jobs have no status, so it sat empty): a status
     pill, when there is one, rides under the role. */
  .job-list.is-list, .job-list-head { --list-cols: 40px minmax(0, 2.4fr) 150px 70px 170px 110px; }
  .job-list.is-list { grid-template-columns: minmax(0, 1fr); gap: 0; border: 1px solid var(--line); border-radius: var(--r-card); background: var(--panel); overflow: hidden; }
  .job-list-head {
    display: grid; grid-template-columns: var(--list-cols); column-gap: 16px; padding: 0 21px 8px;
    font-size: 12px; font-weight: 500; line-height: 1.3; color: var(--ink-dim);
  }
  .job-list-head > span:first-child { grid-column: 1 / 3; }
  .job-list.is-list .job-card {
    grid-template-columns: var(--list-cols); grid-template-rows: auto auto auto auto; align-items: center; column-gap: 16px; row-gap: 2px;
    padding: 14px 20px; border: 0; border-radius: 0; box-shadow: none; transform: none; transition: background-color var(--dur-fast) var(--ease-out);
  }
  .job-list.is-list .job-card + .job-card { border-top: 1px solid var(--line); }
  .job-list.is-list .job-card:hover, .job-list.is-list .job-card:focus-within { background: var(--panel-2); transform: none; box-shadow: none; }
  .job-list.is-list .job-card.archived { border-top-style: dashed; }
  .job-list.is-list .job-card:has(.card-main:focus-visible) { outline-offset: -3px; }
  .job-list.is-list .job-card > .card-head, .job-list.is-list .job-card > .card-stats, .job-list.is-list .job-card > .card-foot { display: contents; }
  .job-list.is-list .card-head > .logo { grid-column: 1; grid-row: 1 / 5; align-self: center; }
  .job-list.is-list .company { grid-column: 2; grid-row: 1; align-self: end; }
  .job-list.is-list .job-card > .card-main { grid-column: 2; grid-row: 2; }
  .job-list.is-list .job-card > .card-blurbs { display: none; }
  .job-list.is-list .stat { grid-row: 1 / 5; }
  .job-list.is-list .stat-grade { grid-column: 3; }
  .job-list.is-list .stat-fit { grid-column: 4; }
  .job-list.is-list .stat-pay { grid-column: 5; }
  .job-list.is-list .stat-label { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
  .job-list.is-list .card-status-group { grid-column: 2; grid-row: 3; justify-self: start; justify-content: flex-start; margin: 2px 0 0; }
  .job-list.is-list .card-foot > .cf-sep { display: none; }
  .job-list.is-list .card-foot > .cf-date { grid-column: 6; grid-row: 1 / 5; }
  .job-list.is-list .card-foot > .cf-more { grid-column: 2; grid-row: 4; }
}
.job-meta .posting-closed { color: var(--danger-strong); font-weight: 600; }
.job-meta .posting-note { color: var(--ink-dim); font-style: italic; }

/* The grade letter. On a list card: a small tilted flat chip. On the job: the big badge. */
.grade-letter {
  display: inline-flex; align-items: center; justify-content: center; min-width: 26px; padding: 1px 6px;
  border-radius: var(--r-control); font-weight: 700; line-height: 1.5; color: var(--on-band); transform: none;
  font-variant-numeric: tabular-nums;
}
.band-good { background: var(--grade-good); color: var(--on-band); }
.band-mid { background: var(--grade-mid); color: var(--grade-mid-ink); }
.band-low { background: var(--grade-low); color: var(--on-band); }
.band-none { background: var(--unknown-bg); color: var(--unknown); }
/* Grade progress (2026-10-20): the core resume's letter greyed (--ink-dim on --panel-2, listed in
   app.css's pairs), an arrow, then the tailored letter in its band colour, or an empty dashed
   slot before tailoring, or the held words. On the job page each letter has a caption under it. */
.grade-progress { display: inline-flex; align-items: center; gap: 6px; vertical-align: middle; }
.grade-progress .grade-letter.gp-core { background: var(--panel-2); color: var(--ink-dim); box-shadow: inset 0 0 0 1px var(--line-strong); }
.grade-progress .gp-arrow { color: var(--ink-dim); font-weight: 600; line-height: 1; }
.grade-progress .gp-slot { display: inline-block; min-width: 26px; height: 1.5em; border: 1.5px dashed var(--ink-faint); border-radius: var(--r-control); }
.grade-progress .gp-held { max-width: 6rem; text-align: left; }
/* Three looks for the tailored side (2026-10-20): not tailored yet (the dashed slot plus words),
   pending (quiet dotted words: the review is open, or the finished resume is being graded), and
   final (the solid letter, with a ring so it reads as settled). Text in --ink-dim on --panel or
   --bg, both listed in app.css's pairs. */
.grade-progress .gp-empty { display: inline-flex; align-items: center; gap: 6px; }
.gp-slot-words { font-size: var(--t-xs); line-height: 1.3; color: var(--ink-dim); white-space: nowrap; }
.gp-pending { display: inline-block; max-width: 11rem; padding: 2px 8px; border: 1.5px dotted var(--line-strong); border-radius: var(--r-control);
  font-size: var(--t-xs); font-style: italic; font-weight: 500; line-height: 1.3; color: var(--ink-dim); text-align: left; }
.grade-progress .grade-letter.gp-final { box-shadow: 0 0 0 2px var(--panel), 0 0 0 3.5px var(--ink); }
.grade-progress.has-captions { align-items: flex-start; gap: 8px; }
.grade-progress.has-captions .gp-arrow { align-self: center; margin-top: -1.2em; }
.gp-cell { display: inline-flex; flex-direction: column; align-items: center; gap: 4px; }
.gp-caption { font-size: var(--t-xs); line-height: 1.3; color: var(--ink-dim); white-space: nowrap; }
.view.job .grade-progress .grade-letter { min-width: 34px; font-size: var(--t-md); }
.view.job .grade-progress .gp-slot { min-width: 34px; height: calc(var(--t-md) * 1.5 + 2px); }
.view.job .grade-progress .gp-held { display: inline-flex; align-items: center; min-height: calc(var(--t-md) * 1.5 + 2px); }
.view.job .grade-progress .gp-pending { display: inline-flex; align-items: center; min-height: calc(var(--t-md) * 1.5 + 2px);
  padding: 0; border: 0; font-style: normal; font-weight: 400; }
.grade-head { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 16px; margin-bottom: 12px; }
.grade-head .field { margin: 0; flex: 1 1 220px; max-width: 320px; }
.grade-badge { display: inline-flex; flex-direction: column-reverse; align-items: center; gap: 8px; }
.grade-basis { font-size: var(--t-xs); line-height: 1.3; color: var(--ink-dim); text-align: center; max-width: 9rem; }
.grade-compare, .grade-aa, .grade-held-why { flex: 1 1 100%; color: var(--ink-dim); font-size: var(--t-xs); }
/* Held while Fix before export items are open (or nothing but contact details to grade): words
   in place of the letter, never a number. */
.grade-held-text { font-size: var(--t-md); font-weight: 600; color: var(--ink); }
/* A list card's held grade: a few words in the letter's place, wrapping rather than clipping. */
.grade-held-card { max-width: 7rem; font-size: var(--t-xs); font-weight: 600; line-height: 1.3; color: var(--ink); text-align: center; }
.grade-score { margin: 0 0 12px; font-size: var(--t-sm); color: var(--ink-dim); font-variant-numeric: tabular-nums; }
.grade-head .platform {
  display: inline-flex; align-items: center; padding: 2px 10px; border: 1px solid var(--line);
  border-radius: 999px; font-size: var(--t-xs); color: var(--ink-dim); background: var(--panel-2);
}
.grade-letter.big {
  flex: none; min-width: 68px; height: 68px; padding: 0 12px; border-radius: var(--r-control);
  font-size: var(--t-xl); line-height: 1; letter-spacing: var(--ls-xl); color: var(--on-band);
  background: var(--unknown);
}
.grade-letter.big.band-good { background: var(--grade-good); }
.grade-letter.big.band-mid { background: var(--grade-mid); color: var(--grade-mid-ink); }
.grade-letter.big.band-low { background: var(--grade-low); }
.stage-note { color: var(--ink-dim); font-size: var(--t-xs); font-style: italic; }

/* Status labels: ONE shape (design system, 2026-10-26). .tag and the verdict .pill are the same
   component: 20px tall, 11px uppercase eyebrow type, a tinted fill with a 1px edge in the
   meaning colour, the pill radius, never wrapping. Meaning modifiers only: tag-block (must fix,
   red), tag-warn (worth a look, amber), tag-ok (green), tag-accent (info, blue), tag-neutral
   (grey, also the bare .tag). The older names stay as aliases so no view breaks: tag-auto,
   tag-run (ok); tag-approve, tag-suggested (accent); tag-check, tag-manual, tag-untraceable,
   tag-wording (warn); tag-dropped (block); and the verdict pills pill-ok / covered, pill-risk /
   stretch, pill-blocker / gap, pill-unknown. A tag follows a real title on its row. */
.tag, .pill {
  display: inline-flex; align-items: center; height: 20px; padding: 0 8px; box-sizing: border-box; vertical-align: middle;
  border: 1px solid var(--unknown); border-radius: var(--r-pill); background: var(--unknown-bg); color: var(--unknown);
  font-size: var(--t-eyebrow); font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; line-height: 1; white-space: nowrap;
}
.tag-neutral, .pill-unknown { border-color: var(--unknown); background: var(--unknown-bg); color: var(--unknown); }
.tag-ok, .tag-auto, .tag-run, .pill-ok, .pill-covered { border-color: var(--ok); background: var(--ok-bg); color: var(--ok); }
.tag-warn, .tag-check, .tag-manual, .tag-untraceable, .tag-wording, .rl-card .tag-wording, .pill-risk, .pill-stretch { border-color: var(--risk); background: var(--risk-bg); color: var(--risk-ink); }
.tag-block, .tag-dropped, .pill-blocker, .pill-gap { border-color: var(--blocker); background: var(--blocker-bg); color: var(--blocker); }
.tag-accent, .tag-approve, .tag-suggested { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
/* A "covered" whose quote the grade could not find in the resume. */
table.coverage .unverified { display: block; margin-top: 4px; color: var(--risk); font-size: var(--t-xs); }
/* The gap answers under the evidence on a gap or stretch row. */
table.coverage .gap-answer { margin-top: 8px; }
table.coverage .gap-answer p { margin: 4px 0; }
table.coverage .gap-answer code { overflow-wrap: anywhere; white-space: normal; }
ol.recs { margin: 0; padding-left: 22px; font-size: var(--t-sm); line-height: 1.5; }
ol.recs li { overflow-wrap: anywhere; margin: 4px 0; }
ol.recs button.quiet { min-height: 28px; margin: 0 0 0 2px; padding: 2px 8px; font-size: var(--t-xs); }
ul.legend {
  list-style: none; margin: 12px 0 0; padding: 10px 12px; border-radius: var(--r-control); background: var(--panel-2);
  font-size: var(--t-xs); color: var(--ink-dim); line-height: 1.5;
}
ul.legend li { margin: 3px 0; overflow-wrap: anywhere; }
ul.legend .tag { margin-right: 6px; }

/* Folds: ONE disclosure (design system, 2026-10-26; views/ui.js fold() builds it). No box, a
   rule above, the browser's marker hidden on ANY details.fold, a CSS chevron before a 15px
   accent summary at weight 500. fold-inline is the 13px one-line variant. */
details.fold { border-top: 1px solid var(--line); padding: 2px 0; margin: 0; }
details.fold > summary {
  cursor: pointer; font-size: var(--t-sm); font-weight: 500; color: var(--accent); list-style: none; display: flex; align-items: baseline; gap: 10px;
  overflow-wrap: anywhere; border-radius: var(--r-control); padding: 10px 8px; margin: 0 -8px;
  transition: background-color var(--dur-fast) var(--ease-out);
}
details.fold > summary:hover { background: var(--panel-2); }
details.fold > summary::-webkit-details-marker, details.fold > summary::marker { display: none; content: ""; }
details.fold > summary::before {
  content: ""; flex: none; width: 7px; height: 7px;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: translateY(-2px) rotate(-45deg); transition: transform var(--dur-fast) var(--ease-out);
}
details.fold[open] > summary::before { transform: translateY(-4px) rotate(45deg); }
details.fold[open] { padding-bottom: 14px; }
details.fold[open] > summary { margin-bottom: 8px; }
details.fold > summary:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
/* A one-line fold inside a row or card (design audit 2026-10-21: the job page drew its small
   disclosures five ways): the same chevron, no rule above, the summary a quiet accent line. The
   posting fold (#posting) and the grade row's How it's graded read the same. */
details.fold.fold-inline, .view.job .grade-summary > details.fold { border-top: 0; padding: 0; flex: none; max-width: 100%; }
details.fold.fold-inline > summary, .view.job .grade-summary > details.fold > summary {
  width: fit-content; max-width: 100%; margin: 0; padding: 6px 0; color: var(--accent); font-size: var(--t-xs); font-weight: 500;
}
details.fold.fold-inline[open] > summary, .view.job .grade-summary > details.fold[open] > summary { margin-bottom: 4px; }
/* A whole panel as one fold (Application questions): its h2 is the summary line, the count
   beside it in plain weight. */
details.section-fold { border-top: 0; padding: 0; }
details.section-fold > summary { align-items: center; color: var(--ink); }
details.section-fold > summary h2 { margin: 0; }
details.section-fold[open] > summary { margin-bottom: 12px; }
.fold-count { font-weight: 400; color: var(--ink-dim); }

/* Knockouts: the one documented automatic rejection, so the loudest rows on the page. */
.ko-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.ko {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; padding: 12px 14px;
  border-radius: var(--r-control); border-left: 5px solid var(--line); background: var(--panel-2);
}
.ko > span:last-child { color: var(--ink-dim); font-size: var(--t-xs); }
.ko:has(> .pill-ok) { border-left-color: var(--ok); }
.ko:has(> .pill-risk) { border-left-color: var(--risk); }
.ko:has(> .pill-unknown) { border-left-color: var(--unknown); }
.ko:has(> .pill-blocker) { border-left-color: var(--blocker); background: var(--blocker-bg); }
.ko:has(> .pill-blocker) > b { color: var(--blocker); }
.run-failed { background: var(--blocker-bg); color: var(--blocker); padding: 8px 12px; border-radius: var(--r-control); border-left: 5px solid var(--blocker); }
.run-refused { margin: 6px 0 0; padding-left: 22px; overflow-wrap: anywhere; }
.run-refused li { margin: 2px 0; }

/* The job header: the meta line (where, posted, pay, captured, the posting link), what the
   company does and what the job is, Role Callouts, then the Apply button with the run bar under
   it. Previous and next job left the header on 2026-10-06 (owner feedback). */
.job-meta { color: var(--ink-dim); font-size: var(--t-sm); margin: 4px 0 6px; overflow-wrap: anywhere; font-variant-numeric: tabular-nums; }
/* The Fit Score line under the meta line (2026-10-07): neutral, its parts in a closed fold. The
   cap line is plain text; the knockout list already carries the colour. */
.job-fit { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; margin: 4px 0 0; font-size: var(--t-xs); }
.job-fit-score { font-weight: 600; color: var(--ink); }
.fit-parts { margin: 4px 0; padding-left: 1.2em; }
.role-blurb { margin: 12px 0 0; color: var(--ink); line-height: 1.5; }
.role-blurb .whatco { font-weight: 600; }
.view a.button.apply-btn { display: inline-flex; align-items: center; padding: 10px 18px; border-radius: var(--r-pill); font-weight: 500; text-decoration: none; }

/* Knockouts: the all-clear line when only screening questions bring the panel up, and each
   screening question with its required tag and first options. */
.all-clear { display: flex; gap: 9px; align-items: baseline; margin: 0; line-height: 1.5; color: var(--ink-dim); font-size: var(--t-sm); }
.all-clear .pill { flex: 0 0 auto; }
.screeners li { margin: 4px 0; overflow-wrap: anywhere; }
.scr-req { margin-left: 8px; font-size: var(--t-eyebrow); font-weight: 500; letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent); }
.scr-opts { display: block; color: var(--ink-dim); font-size: var(--t-xs); }

/* The Scratch Pad: a formatting toolbar over a contenteditable box. Indent on a plain line is
   a data-indent level (1 to 4), never an inline style, which the CSP drops. */
.padtools { display: flex; flex-wrap: wrap; gap: 4px; padding: 6px; border: 1px solid var(--line); border-bottom: none; border-radius: var(--r-control) var(--r-control) 0 0; background: var(--panel-2); }
.view button.padtool { display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 34px; min-height: 0; padding: 0; background: transparent; border: 1px solid transparent; color: var(--ink-dim); }
.view button.padtool:hover { background: var(--panel); border-color: var(--line); color: var(--ink); }
.padtool svg { display: block; }
.padtool-insertUnorderedList, .padtool-outdent { margin-left: 8px; }
.padbox { min-height: 180px; max-height: 60vh; overflow-y: auto; padding: 12px 14px; border: 1px solid var(--ink-faint); border-radius: 0 0 var(--r-control) var(--r-control); background: var(--panel); color: var(--ink); line-height: 1.5; overflow-wrap: anywhere; }
.padbox:focus { outline: none; border-color: var(--accent); box-shadow: var(--ring); }
.padbox:empty::before { content: attr(data-placeholder); color: var(--ink-dim); }
.padbox ul, .padbox ol { margin: 2px 0; padding-left: 24px; }
.padbox [data-indent="1"] { margin-left: 24px; }
.padbox [data-indent="2"] { margin-left: 48px; }
.padbox [data-indent="3"] { margin-left: 72px; }
.padbox [data-indent="4"] { margin-left: 96px; }
.notes-row { display: flex; align-items: center; gap: 12px; margin-top: 10px; }
.posting-preview { display: grid; grid-template-columns: max-content 1fr; gap: 4px 12px; }
.view table { border-collapse: collapse; width: 100%; font-size: var(--t-sm); }
.view th { text-align: left; color: var(--ink-dim); font-weight: 600; font-size: var(--t-xs); }
.view th, .view td { text-align: left; vertical-align: top; padding: 6px 8px; border-bottom: 1px solid var(--line); overflow-wrap: anywhere; }
@media (max-width: 600px) {
  .view table, .view thead, .view tbody, .view tr, .view th, .view td { display: block; }
  .view thead { position: absolute; left: -9999px; }
  .view tr { padding: 8px 0; border-bottom: 1px solid var(--line); }
  .view td { border: none; padding: 2px 0; }
}
.resume-preview { overflow-wrap: anywhere; }
.reqtype { font-size: var(--t-eyebrow); font-weight: 500; letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent); }
.needs-ok { margin: 16px 0; }
.needs-ok > ul { list-style: none; padding: 0; display: grid; gap: 8px; }
.flag { padding: 8px 12px; border: 1px solid var(--line); border-radius: var(--r-control); background: var(--panel); }
.flag p { margin: 4px 0; }
.flag-question { font-weight: 600; }
.flag-where { list-style: none; padding: 0; margin: 6px 0; display: grid; gap: 6px; }
.flag-section { display: block; font-size: var(--t-xs); font-weight: 700; color: var(--ink-dim); }
.flag-sentence { display: block; overflow-wrap: anywhere; }
.flag-sentence mark { background: var(--manual-bg); color: var(--manual-ink); font-weight: 700; padding: 0 1px; border-radius: 3px; }
.flag-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px; }
.flag-preview { display: block; white-space: pre-wrap; overflow-wrap: anywhere; font-size: var(--t-xs); padding: 6px 8px; border-radius: var(--r-control); background: var(--panel-2); }
.flag-approve { margin-top: 6px; }
.ask, .your-changes { margin: 16px 0; }
/* Above the resume pages: what the run changed against the master, and the Show changes switch. */
.rl-summary { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.rl-counts { display: grid; gap: 2px; flex: 1 1 320px; min-width: 0; }
.rl-summary-check { color: var(--manual-ink); font-weight: 600; }
.ask-proposal { padding: 10px 14px; border: 1px solid var(--line); border-radius: var(--r-control); background: var(--panel-2); margin: 8px 0; overflow-wrap: anywhere; }
.ask-proposal .edit p, .ask-question { margin: 4px 0; }
.your-changes > ul { list-style: none; padding: 0; display: grid; gap: 6px; }
.your-changes .change { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 4px 12px; padding: 6px 12px; border: 1px solid var(--line); border-radius: var(--r-control); background: var(--panel); overflow-wrap: anywhere; }
.chat-log { list-style: none; padding: 0; display: grid; gap: 10px; }
.turn { padding: 10px 14px; border-radius: var(--r-card); border: 1px solid var(--line); background: var(--panel-2); overflow-wrap: anywhere; white-space: pre-wrap; }
.turn.me { background: var(--accent-soft); border-color: var(--line); color: var(--ink); }
.turn .who { display: block; font-weight: 700; font-size: var(--t-xs); color: var(--ink-dim); }
.turn .refusal { font-style: italic; }
.counter { color: var(--ink-dim); font-size: var(--t-xs); font-variant-numeric: tabular-nums; }
.counter.over { color: var(--blocker); font-weight: 700; }
.answers .field textarea { min-height: 8rem; }
.credit-prompt { font-weight: 600; }
.export { margin: 16px 0; }
.blocked { font-weight: 600; }
/* The print root is filled only while printing. On screen it sits off-screen at one page's
   width, laid out, because js/views/paper.js measures the page breaks from the layout. */
@media screen {
  #print-root:not([hidden]) { position: absolute; left: -10000px; top: 0; width: 8.5in; padding: 0; }
}
/* Paper: one sheet per page, no margin of the page's own (the sheet carries it), so what
   prints is exactly the preview. A page break goes BETWEEN sheets only (before every sheet
   but the first), never after the last, so nothing can add an empty trailing page. In print
   a sheet is as tall as its words, not a drawn 8.5 x 11 box: the plan already keeps each
   sheet within a page, and a box of exactly 11in that rounds a hair over printed a blank page
   after every sheet, while one that ran long split and stranded its overflow. A sheet stays
   whole (no break inside), and if one ever is too long anyway it continues with its margins
   (box-decoration-break) rather than clipping. The other break rules are that same fallback:
   a heading, role line or context line never ends a page, a role line never splits. */
@media print {
  body > *:not(#print-root) { display: none !important; }
  #print-root, #print-root[hidden] { display: block !important; position: static; width: auto; border: none; padding: 0; max-width: none; box-shadow: none; border-radius: 0; background: none; }
  @page { size: letter; margin: 0; }
  #print-root .sheet { box-shadow: none; margin: 0; aspect-ratio: auto; height: auto; max-height: none;
    break-inside: avoid; break-after: auto; -webkit-box-decoration-break: clone; box-decoration-break: clone; }
  #print-root .sheet + .sheet { margin: 0; break-before: page; }
  #print-root h1, #print-root h2, #print-root .contact, #print-root .rolehead, #print-root .context { break-after: avoid; }
  #print-root .rolehead, #print-root li { break-inside: avoid; }
}
/* A date input's keyboard focus sits in its inner date segments, so the box itself never
   matches :focus-visible; draw the same ring when focus is anywhere inside it. */
.field input[type="date"]:focus-within { outline: none; border-color: var(--accent); box-shadow: var(--ring); }
/* #/credits, laid out like a checkout (2026-10-02): a header with the balance on the right,
   a row of pack cards (the chosen one outlined in the accent), an order summary, a coupon
   code fold, then the pay row. */
.buy-head { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 8px 16px; }
.buy-head h1 { margin-bottom: 4px; }
.buy-lead { margin: 0; color: var(--ink-dim); }
.credits-now { font-weight: 600; margin: 4px 0 12px; font-variant-numeric: tabular-nums; }
.packs { list-style: none; padding: 0; margin: 20px 0 14px; display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 10px; }.packs > li { display: flex; }
button.pack-card { flex: 1; display: block; text-align: left; padding: 12px 14px; min-height: 96px; border: 1px solid var(--line); border-radius: var(--r-card);
  background: var(--panel); color: var(--ink); box-shadow: none; font-weight: 400;
  /* Content from the top, so every price sits at the same height with or without a Save badge. */
  display: flex; flex-direction: column; justify-content: flex-start; }
button.pack-card:hover { border-color: var(--line-strong); background: var(--panel); }
button.pack-card[aria-pressed="true"] { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); background: var(--accent-soft); }
.pack-face { display: grid; gap: 4px; align-content: start; }
/* Your purchases: a plain text link under the terms, never a pill beside the purchase. */
.buy-mine { margin: 16px 0 0; font-size: var(--t-sm); }
.pack-title { font-weight: 600; font-size: var(--t-md); }
.pack-price { font-size: var(--t-lg); font-weight: 600; letter-spacing: -0.01em; font-variant-numeric: tabular-nums; }
.pack-save, .pack-each { justify-self: start; font-size: var(--t-xs); padding: 2px 8px; border-radius: var(--r-control); background: var(--panel-2); color: var(--ink-dim); white-space: nowrap; }
button.pack-card[aria-pressed="true"] .pack-save { background: var(--accent); color: var(--on-accent); }
.buy-summary { border: 1px solid var(--line); border-radius: var(--r-card); padding: 6px 16px; background: var(--panel); }
.buy-summary-rows { display: grid; grid-template-columns: 1fr auto; gap: 0 16px; margin: 0; font-size: var(--t-sm); }
.buy-summary-rows dt, .buy-summary-rows dd { margin: 0; padding: 8px 0; }
.buy-summary-rows dt { color: var(--ink-dim); }
.buy-summary-rows dd { text-align: right; font-variant-numeric: tabular-nums; }
.buy-summary-total { border-top: 1px solid var(--line); margin-top: 2px; }
.buy-summary-total dt { color: var(--ink); font-weight: 600; }
.buy-summary-total dd { font-weight: 700; font-size: var(--t-md); }
.code-fold { margin-top: 10px; }
.code-form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px 10px; }
.code-form .field { flex: 1 1 200px; margin: 0; }
.buy-pay { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px 16px; margin-top: 14px; }
.buy-pay .hint { margin: 0; }
.buy-pay-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-left: auto; }
.buy-terms { margin-top: 18px; font-size: var(--t-xs); color: var(--ink-dim); }
.buy-terms p { margin: 0 0 8px; }
@media (max-width: 480px) {
  .packs { gap: 8px; }
  button.pack-card { padding: 10px; min-height: 0; }
  .pack-title { font-size: var(--t-sm); white-space: nowrap; }
  .pack-price { font-size: var(--t-lg); }
  .pack-save, .pack-each { font-size: var(--t-eyebrow); padding: 2px 6px; }
  .pack-each { display: none; }
}
/* Every outcome on #/credits/done and the cancel page (owner pick C, 2026-10-05): a coloured rule
   across the top of the card and a status pill over the headline. Green is the paid receipt, red
   is money that did not become credits, grey is nothing wrong yet. The rule is decoration; the
   pill's words carry the meaning, each in a declared contrast pair. */
.view.narrow.done-card { border-top: 6px solid var(--ink-faint); padding-top: 16px; }
.view.narrow.done-card.is-ok { border-top-color: var(--ok); }
.view.narrow.done-card.is-danger { border-top-color: var(--danger); }
/* The status label is the shared .tag (tag-ok, tag-block, tag-neutral); only its place here. */
.done-pill { margin: 0 0 8px; }
/* The purchases table on #/credits/receipts and #/billing (2026-10-05): a bordered panel,
   right-aligned tabular amounts, and a small status tag (paid in the --ok pair). */
.receipts-wrap { margin: 14px 0 10px; border: 1px solid var(--line); border-radius: var(--r-card); background: var(--panel); overflow-x: auto; }
table.receipts { width: 100%; border-collapse: collapse; font-size: var(--t-sm); }
table.receipts th { text-align: left; font-size: var(--t-eyebrow); font-weight: 500; letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent);
  padding: 10px 14px; border-bottom: 1px solid var(--line); background: var(--panel-2); }
table.receipts td { padding: 11px 14px; border-bottom: 1px solid var(--line); vertical-align: middle; }
table.receipts tbody tr:last-child td { border-bottom: 0; }
table.receipts .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
table.receipts .nowrap, table.receipts .receipt-link { white-space: nowrap; }
.receipt-status { display: inline-block; font-size: var(--t-xs); font-weight: 600; padding: 2px 8px; border-radius: var(--r-control); background: var(--panel-2); color: var(--ink-dim); }
.receipt-status.is-ok { background: var(--ok-bg); color: var(--ok); }
.receipt-status.is-warn { background: var(--risk-bg); color: var(--risk-ink); }
.receipts-empty { color: var(--ink-dim); }
.receipts-foot { margin-top: 8px; }
.receipts-foot .hint { margin: 0 0 4px; }
/* Under 600px the generic .view table rule stacks every cell; a purchase reads better as two
   lines instead: date and amount, then the pack and its status. */
@media (max-width: 600px) {
  .view table.receipts tbody tr { display: grid; grid-template-columns: 1fr auto; gap: 6px 12px; align-items: center;
    padding: 12px 14px; border-bottom: 1px solid var(--line); }
  .view table.receipts tbody tr:last-child { border-bottom: 0; }
  .view table.receipts td { padding: 0; border: 0; }
  .view table.receipts td:nth-child(3) { order: 2; text-align: right; font-weight: 600; }
  .view table.receipts td:nth-child(2) { order: 3; color: var(--ink-dim); }
  .view table.receipts td:nth-child(4) { order: 4; text-align: right; }
  .view table.receipts td.receipt-link { order: 5; grid-column: 1 / -1; }
  .view table.receipts td.receipt-link:empty { display: none; }
}
.done-rows { margin: 12px 0; display: grid; grid-template-columns: auto 1fr; gap: 4px 16px; font-size: var(--t-xs); }
.done-rows dt { color: var(--ink-dim); }
.done-rows dd { margin: 0; font-variant-numeric: tabular-nums; }
.top .buy { font-weight: 600; }
/* The posting on the add-a-job confirm step: readable, bounded, and apart from the button. */
/* Only a scroll area (design system 2026-10-26: the Add a job panel is the one surface), with a
   rule above and below so the scrolling text has an edge. */
.posting-body { max-height: 22rem; overflow: auto; margin: 0 0 16px; padding: 12px 0; border-block: 1px solid var(--line); }
.posting-body p { margin: 0 0 10px; }
/* The two legal links on the first screen: spaced apart so they do not read as one link. */
p.links { display: flex; flex-wrap: wrap; gap: 4px 20px; }
/* Adding a job by paste: one large box for a whole page, and the cut-off choice's two buttons. */
.paste-page textarea { min-height: 18rem; }
.paste-choice { display: flex; flex-wrap: wrap; gap: 8px 12px; margin: 12px 0 16px; }
/* The full posting found on the company's own site, in place of the paste. */
.found-note { margin: 0 0 16px; padding: 12px 16px; background: var(--accent-soft); color: var(--ink); border-radius: var(--r-control); }
.found-note p { margin: 0 0 8px; }
/* The segmented control (js/views/ui.js segmented), ONE look everywhere (design system
   2026-10-26: Add a job, Settings' Adding LinkedIn jobs, the review's scope switch). Each segment
   is a pill label around a visually hidden radio (relative, to keep that radio inside it), its
   words in one .segment-text span. The picked one is a pale accent tint with accent text and a
   check, never the solid fill: on any screen the only filled control is a primary button. The
   check is a .seg-check glyph where the view adds one (the review scope), else drawn by
   ::before. The focus ring is drawn on the segment whose radio has keyboard focus; 44px under
   768px.
   contrast-pairs: --accent-strong on --accent-soft; --accent on --panel */
.view fieldset.segmented { border: 0; border-radius: 0; padding: 0; margin: 0 0 16px; min-width: 0; }
.segmented legend { padding: 0; margin: 0 0 6px; font-weight: 600; }
.segments { display: flex; flex-wrap: wrap; gap: 6px; }
.segment { position: relative; display: inline-flex; align-items: center; justify-content: center; gap: 6px; min-height: 40px; padding: 6px 14px;
  border: 1px solid var(--line-strong); border-radius: var(--r-pill); background: var(--panel);
  text-align: center; font-size: var(--t-sm); font-weight: 600; line-height: 1.25; color: var(--accent); cursor: pointer; }
.segment-text { min-width: 0; overflow-wrap: break-word; }
.segment:hover { background: var(--accent-soft); }
.segment.is-selected, .segment:has(input:checked) { background: var(--accent-soft); border-color: var(--accent); color: var(--accent-strong); }
.segment .seg-check { display: none; width: 14px; height: 14px; stroke-width: 2.4; }
.segment.is-selected .seg-check, .segment:has(input:checked) .seg-check { display: inline-block; }
.segment::before { content: ''; display: none; flex: none; width: 9px; height: 5px; margin: 0 1px 3px;
  border-left: 2px solid currentColor; border-bottom: 2px solid currentColor; transform: rotate(-45deg); }
.segment.is-selected::before, .segment:has(input:checked)::before { display: inline-block; }
.segment:has(.seg-check)::before, .segment.is-selected:has(.seg-check)::before { display: none; }
.segment:has(input:focus-visible) { outline: 3px solid var(--focus); outline-offset: 2px; }
@media (max-width: 767px) { .segment { min-height: 44px; } }
/* The 'type' option's fields, and the confirm step's company, role and location fields. */
.quick-find { margin: 0 0 8px; }
.confirm-details { margin: 0 0 16px; }
/* Add a job (views/addjob.js), cleaned up 2026-10-06. The paste box is a working size, the
   two-way choice sits at its natural width, and the other ways in (the bookmarklet, the paste)
   sit apart under a rule, quieter than the link field. */
.add-job .paste-page textarea { min-height: 12rem; }
.add-job form > button[type="submit"] { margin-top: 4px; }
.add-alt { margin: 20px 0 4px; padding-top: 16px; border-top: 1px solid var(--line); }
/* The confirm step's one action on its own row, and the LinkedIn or Indeed link's steps. */
.add-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin: 12px 0 4px; }
.add-actions > a.button, .add-actions > button { margin: 0; }
.board-steps { margin: 8px 0 12px; padding-left: 22px; line-height: 1.5; }
.board-steps li { margin: 0 0 6px; }
@media (max-width: 767px) { .needs-bookmark { display: none; } }
.add-alt .add-alt-title { font-size: var(--t-sm); margin: 0 0 8px; }
.add-alt > .paste-choice { margin: 4px 0 0; }
/* Every Add a job step opens with one lead in the body size and ink; .hint is only for a line
   under a field. */
.add-job .add-lead { margin: 0 0 16px; font-size: var(--t-sm); line-height: 1.5; color: var(--ink); }
.add-job .paste-refusal .add-lead { margin: 0; }
.add-alt .page-grab-how { margin: 0 0 8px; font-size: var(--t-sm); color: var(--ink-dim); }
.add-alt .page-grab-status:empty { display: none; }
/* Phones cannot run a bookmark, so the button is not offered there; the paste stays. */
@media (max-width: 767px) { .page-grab { display: none; } }
/* The confirm step's job header: the job page's logo, company and role, and location line, as
   a flat section on the panel. The run card on the add flow is flat too (one surface). */
.add-job .run-progress { padding: 0; border: 0; background: none; box-shadow: none; }
.add-head { display: flex; align-items: flex-start; gap: 12px; margin: 4px 0 16px; }
.add-head .logo { flex-basis: 40px; width: 40px; height: 40px; }
.add-head .logo .mono { font-size: var(--t-md); }
.add-head-logo { display: flex; flex: none; }
.add-head-text { flex: 1 1 auto; min-width: 0; }
.add-head .add-head-title { margin: 0; font-size: var(--t-md); line-height: 1.3; overflow-wrap: anywhere; }
.add-head .add-head-meta { margin: 2px 0 0; }
.add-head > button.quiet { flex: none; margin: 0; }
@media (max-width: 480px) {
  .add-head { flex-wrap: wrap; }
  .add-head > button.quiet { flex-basis: 100%; padding-left: 0; text-align: left; }
}
/* Archive this job: a red outline, so it reads as the one step that takes a job off the list.
   Its text pairs are declared with the tokens in app.css. */
button.danger-outline { background: var(--panel); border-color: var(--danger); color: var(--danger); }
button.danger-outline:not(:disabled):hover { background: var(--danger-soft); border-color: var(--danger-strong); color: var(--danger-strong); }

/* ------------------------------------------------------------------ run progress
   A running add, score or tailor (views/progress.js, redesigned 2026-10-21, owner: "you need
   better visualization of it loading"): the step it is on in large type with a spinner (the
   reading face on a tailor run), "Step 2 of 4" and a clock, a bar of one segment per step (done
   solid, the current one with a sheen sliding across it, a transform only), then every step with
   a check, a small spinner or a hollow ring. The universal reduced-motion rule above stops the
   sheen and the spinners; the states stay clear without them.
   contrast-pairs: --ink on --panel; --ink-dim on --panel; --accent on --panel */
.run-progress { margin: 4px 0 12px; padding: 16px 18px; border: 1px solid var(--line); border-radius: var(--r-card); background: var(--panel); box-shadow: var(--shadow-rest); }
.run-now { display: flex; align-items: center; gap: 12px; font-weight: 600; }
.run-now-text { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; font-size: var(--t-md); line-height: 1.3; color: var(--ink); }
.run-spinner {
  flex: none; width: 22px; height: 22px; border-radius: 50%;
  border: 3px solid var(--accent-soft); border-top-color: var(--accent);
  animation: run-spin 0.9s linear infinite;
}
@keyframes run-spin { to { transform: rotate(360deg); } }
.run-meta { flex: none; display: flex; align-items: baseline; gap: 10px; }
.run-count { color: var(--ink-dim); font-size: var(--t-xs); font-weight: 500; }
.elapsed { flex: none; color: var(--ink-dim); font-size: var(--t-xs); font-weight: 500; font-variant-numeric: tabular-nums; }
.run-meter { display: flex; gap: 4px; margin: 14px 0 0; }
.run-meter-seg { position: relative; flex: 1 1 0; height: 6px; border-radius: 999px; overflow: hidden; background: var(--line); }
.run-meter-seg.is-done { background: var(--accent); }
.run-meter-seg.is-current { background: var(--accent-soft); }
.run-meter-seg.is-current::after {
  content: ""; position: absolute; top: 0; left: 0; width: 45%; height: 100%; border-radius: inherit;
  background: var(--accent); transform: translateX(-100%); animation: run-sheen 1.4s ease-in-out infinite;
}
@keyframes run-sheen { from { transform: translateX(-100%); } to { transform: translateX(225%); } }
/* The tailor run's bar (views/progress.js, 2026-10-27): one fill eased on elapsed time and moved
   by phase, drawn by a scaleX class bucket (run-track-p-<even 0..100>, no style writes). It
   transitions linearly over the one-second tick; the universal reduced-motion rule makes it jump.
   contrast-pairs: --ink-dim on --panel; --ink on --panel */
.run-track { margin: 14px 0 0; height: 6px; border-radius: 999px; overflow: hidden; background: var(--line); }
.run-track-fill { display: block; width: 100%; height: 100%; background: var(--accent); transform-origin: left center; transform: scaleX(0); transition: transform 1000ms linear; }
.run-track-p-0 { transform: scaleX(0); }
.run-track-p-2 { transform: scaleX(0.02); }
.run-track-p-4 { transform: scaleX(0.04); }
.run-track-p-6 { transform: scaleX(0.06); }
.run-track-p-8 { transform: scaleX(0.08); }
.run-track-p-10 { transform: scaleX(0.1); }
.run-track-p-12 { transform: scaleX(0.12); }
.run-track-p-14 { transform: scaleX(0.14); }
.run-track-p-16 { transform: scaleX(0.16); }
.run-track-p-18 { transform: scaleX(0.18); }
.run-track-p-20 { transform: scaleX(0.2); }
.run-track-p-22 { transform: scaleX(0.22); }
.run-track-p-24 { transform: scaleX(0.24); }
.run-track-p-26 { transform: scaleX(0.26); }
.run-track-p-28 { transform: scaleX(0.28); }
.run-track-p-30 { transform: scaleX(0.3); }
.run-track-p-32 { transform: scaleX(0.32); }
.run-track-p-34 { transform: scaleX(0.34); }
.run-track-p-36 { transform: scaleX(0.36); }
.run-track-p-38 { transform: scaleX(0.38); }
.run-track-p-40 { transform: scaleX(0.4); }
.run-track-p-42 { transform: scaleX(0.42); }
.run-track-p-44 { transform: scaleX(0.44); }
.run-track-p-46 { transform: scaleX(0.46); }
.run-track-p-48 { transform: scaleX(0.48); }
.run-track-p-50 { transform: scaleX(0.5); }
.run-track-p-52 { transform: scaleX(0.52); }
.run-track-p-54 { transform: scaleX(0.54); }
.run-track-p-56 { transform: scaleX(0.56); }
.run-track-p-58 { transform: scaleX(0.58); }
.run-track-p-60 { transform: scaleX(0.6); }
.run-track-p-62 { transform: scaleX(0.62); }
.run-track-p-64 { transform: scaleX(0.64); }
.run-track-p-66 { transform: scaleX(0.66); }
.run-track-p-68 { transform: scaleX(0.68); }
.run-track-p-70 { transform: scaleX(0.7); }
.run-track-p-72 { transform: scaleX(0.72); }
.run-track-p-74 { transform: scaleX(0.74); }
.run-track-p-76 { transform: scaleX(0.76); }
.run-track-p-78 { transform: scaleX(0.78); }
.run-track-p-80 { transform: scaleX(0.8); }
.run-track-p-82 { transform: scaleX(0.82); }
.run-track-p-84 { transform: scaleX(0.84); }
.run-track-p-86 { transform: scaleX(0.86); }
.run-track-p-88 { transform: scaleX(0.88); }
.run-track-p-90 { transform: scaleX(0.9); }
.run-track-p-92 { transform: scaleX(0.92); }
.run-track-p-94 { transform: scaleX(0.94); }
.run-track-p-96 { transform: scaleX(0.96); }
.run-track-p-98 { transform: scaleX(0.98); }
.run-track-p-100 { transform: scaleX(1); }
.run-slow { margin: 4px 0 0; color: var(--ink); font-size: var(--t-xs); }
.run-steps { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 8px; font-size: var(--t-sm); }
.run-step { display: flex; align-items: center; gap: 10px; color: var(--ink-dim); }
.run-mark { flex: none; width: 16px; height: 16px; box-sizing: border-box; }
.run-step .run-mark-done { color: var(--accent); stroke-width: 2.4; }
.run-mark-current { border-radius: 50%; border: 2px solid var(--accent-soft); border-top-color: var(--accent); animation: run-spin 0.9s linear infinite; }
.run-mark-todo { border-radius: 50%; border: 2px solid var(--line-strong); }
.run-step.is-done { color: var(--ink); }
.run-step.is-current { color: var(--ink); font-weight: 600; }
@media (max-width: 480px) {
  .run-now { flex-wrap: wrap; }
  .run-meta { flex-basis: 100%; }
}

/* ------------------------------------------------------------------ job page */
/* Tailor my resume with its credit note centred under it, and room below the pair. */
.tailor-go { display: inline-flex; flex-direction: column; align-items: center; gap: 6px; margin: 4px 0 14px; }
.view .tailor-go > button { margin: 0; }
.tailor-go .hint { text-align: center; margin: 0; }
/* The company monogram, the local tool's .logo without the image layer (views/logo.js). */
.logo {
  display: inline-flex; align-items: center; justify-content: center; flex: 0 0 34px; width: 34px; height: 34px;
  border-radius: var(--r-control); background: var(--panel-2); border: 1px solid var(--line);
}
.logo .mono { font-size: var(--t-sm); font-weight: 650; color: var(--ink-dim); letter-spacing: 0.02em; line-height: 1; }
.job-title { display: flex; align-items: flex-start; gap: 12px; }
.job-title .logo { margin-top: 1px; }
.job-title h1 { min-width: 0; overflow-wrap: anywhere; }
/* The header's More menu (views/ui.js menuButton): a button at the title's right, its list
   dropping below it like the account menu's. The job page draws it quiet (app-parity.css). */
.job-title h1 { flex: 1 1 auto; }
.menu-wrap { position: relative; flex: none; }
/* Every menu trigger is ONE look (design system, 2026-10-26): a secondary button at the standard
   40px (44px under 768px), a "More" one leading with three dots, any other ending in a small CSS
   chevron (the same one doc-menu.js draws). */
.menu-wrap > button { display: inline-flex; align-items: center; gap: 6px; min-height: 40px; margin: 0; }
@media (max-width: 767px) { .menu-wrap > button { min-height: 44px; } }
.menu-caret { flex: none; width: 0; height: 0; border-left: 4px solid transparent; border-right: 4px solid transparent; border-top: 5px solid currentColor; color: var(--ink-dim); }
.menu-list {
  position: absolute; right: 0; top: calc(100% + 4px); z-index: 20; min-width: 190px; padding: 4px;
  background: var(--panel); color: var(--ink); border: 1px solid var(--line); border-radius: var(--r-control);
  box-shadow: var(--shadow-pop);
}
/* A pointer open focuses the menu itself, never an item: no ring on the list box. */
.menu-list:focus { outline: none; }
.menu-list [role="menuitem"] {
  display: flex; align-items: center; width: 100%; min-height: 44px; margin: 0; padding: 0 12px; border: 0; border-radius: var(--r-control);
  background: transparent; color: var(--ink); box-shadow: none; font: inherit; font-size: var(--t-sm); font-weight: 500;
  text-align: left; cursor: pointer;
}
.menu-list [role="menuitem"]:hover { background: var(--panel-2); }
.menu-list [role="menuitem"]:focus-visible { outline: 3px solid var(--focus); outline-offset: -3px; background: var(--panel-2); }
.menu-list [role="menuitem"].is-danger { color: var(--danger); border-top: 1px solid var(--line); border-radius: 0 0 var(--r-control) var(--r-control); }
.menu-list [role="menuitem"][aria-disabled="true"] { color: var(--ink-faint); cursor: not-allowed; }
.job-card .logo { flex-basis: var(--card-logo); width: var(--card-logo); height: var(--card-logo); }
.job-card .logo .mono { font-size: calc(var(--card-logo) * 0.45); }

/* File and format checks: each row in its verdict's colour, with the result in the pill. */
ul.checks { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 6px; }
.check-row {
  display: flex; align-items: baseline; gap: 10px; padding: 7px 12px; font-size: var(--t-sm); overflow-wrap: anywhere;
  border-radius: var(--r-control); border-left: 4px solid var(--line); background: var(--panel-2);
}
.check-row .pill { flex: none; min-width: 5.5em; text-align: center; justify-content: center; }
.check-row.check-pass { border-left-color: var(--ok); }
.check-row.check-warn { border-left-color: var(--risk); background: var(--risk-bg); }
.check-row.check-fail { border-left-color: var(--blocker); background: var(--blocker-bg); }
.check-row.check-na { border-left-color: var(--unknown); }

/* ------------------------------------------------------------------ chat
   A reply's Markdown subset (views/chat.js replyNodes) and the bubble shown while one is on
   its way. The dots pulse in turn; the universal reduced-motion rule holds them still. */
.turn .reply > :first-child { margin-top: 0; }
.turn .reply > :last-child { margin-bottom: 0; }
.turn .reply p, .turn .reply ul, .turn .reply ol { margin: 0 0 8px; }
.turn .reply ul, .turn .reply ol { padding-left: 22px; white-space: normal; }
.turn .reply li { margin: 2px 0; }
.turn .reply code { font: var(--t-xs)/1.4 var(--font-mono); background: var(--panel); border: 1px solid var(--line); border-radius: 4px; padding: 0 4px; }
.chat-pending-line { display: flex; align-items: center; gap: 10px; margin: 0; }
.chat-pending-text { color: var(--ink-dim); font-weight: 600; }
.chat-dots { display: inline-flex; gap: 4px; }
.chat-dots span {
  width: 6px; height: 6px; border-radius: 50%; background: var(--ink-dim); opacity: 0.35;
  animation: chat-pulse 1.2s ease-in-out infinite;
}
.chat-dots span:nth-child(2) { animation-delay: 0.2s; }
.chat-dots span:nth-child(3) { animation-delay: 0.4s; }
@keyframes chat-pulse { 0%, 60%, 100% { opacity: 0.35; } 30% { opacity: 1; } }

/* A real company logo (views/logo.js): the image fills the tile on a white ground, since most
   logos are drawn for a light page. */
.logo.has-img { background: #fff; overflow: hidden; }
.logo img { display: block; width: 100%; height: 100%; object-fit: contain; }
.logo-edit { margin-top: 8px; max-width: 28rem; }

/* ------------------------------------------------------------ review rail
   The tailored resume and its review panel (views/job-resume.js reviewFrame, views/rail.js).
   The Docs-style editor (2026-10-05, owner decision): on a desktop or a tablet the resume
   section holds the editor (resume-editor.css): one bar, the pages, and the panel
   docked in the editor's aside slot from 1100px unless he collapsed it (rail-beside).
   Collapsed, nothing covers the page; a desktop from 1000 to 1099, a collapsed panel opened
   on purpose and a tablet use a right drawer (rail-collapsed, review-tablet). Phone: full-width
   pages, a sticky bottom bar and a full-height sheet. Since 2026-10-05 (owner feedback, equal
   section widths) it is exactly as wide as every other section: main's column,
   min(var(--page-max), 100% - 32px), no breakout. state/layout.js sectionInner is the room
   inside it: that column less its padding and border (34px); SECTION_CHROME_PX (66px) is the
   two gutters plus those, below the cap. */
.view.job #resume:has(.review-editor) {
  width: 100%; max-width: none; box-sizing: border-box; margin-left: 0;
  padding: 16px;
}
.review-desktop { position: relative; }
.review-main { min-width: 0; }
.review-editor .re { margin-bottom: 0; }
.review-editor .re-bar { border-top: 1px solid var(--line); }
.rail { display: flex; flex-direction: column; border: 1px solid var(--line); border-radius: var(--r-card); background: var(--panel); min-width: 0; }
/* Docked: the MARGIN (the review panel's second pass, 2026-10-05). A column beside the pages
   as tall as they are, scrolling with them, so each card (js/margin-cards.js .mc-card) sits
   level with its line; never sticky, never over the pages.
   Its height is the PAGES' height, never the cards' (2026-10-06, owner feedback: "the
   suggestions are still creating extra pages and it's way way way too long"). Measured at
   1440x900 with 11 cards on a one-page resume, the cards stacked to 2300px beside a 1214px
   sheet and the section ran 1100px of empty desk past the last page. So the aside takes no
   height of its own (its dock is absolute) and stretches to the row the pages set; the rare
   card run that still outgrows the pages scrolls inside the margin instead of lengthening
   the page. The width is the rail's own 320px, since an absolute dock gives the column none. */
.rail-dock[hidden] { display: none; }
.review-editor .re-aside:has(.rail-margin) { position: relative; top: auto; max-height: none; overflow: visible; align-self: stretch; width: 320px; background: var(--panel-2); }
.review-editor .re-aside:has(.rail-margin) > .rail-dock { position: absolute; inset: 0; overflow-x: hidden; overflow-y: auto; }
/* Inside that scroller the selected card leans out 8px, not 16px, so its ring is not clipped. */
.review-editor .rail-margin .mc-card.is-active { transform: translateX(-8px); }
.rail-dock .rail { box-sizing: border-box; width: 320px; min-height: 100%; padding: 18px 0 40px;
  border-width: 0 0 0 1px; border-color: var(--line); border-radius: 0; background: transparent; }
.rail-margin .mc-layer { font-size: var(--t-xs); }
.rail-margin .rl-card { padding: 0; border: 0; border-radius: 0; background: none; box-shadow: none; }
.rail-margin .rl-card.is-active { box-shadow: none; }
.rail-margin .rl-card p { font-size: var(--t-xs); line-height: 1.4; }
.rail-margin .mc-card > .nudge { margin: 0; }
/* The bar's own parts on the job page (views/job-resume.js docBar) and the master page. */
.doc-start { display: flex; align-items: center; gap: 12px; min-width: 0; }
/* The bar's title over its status (design review 2026-10-20: the title beside the status made the
   bar wrap to two rows at 1100px). "Resume" on top, "Saved · 1 page" under it, about as wide as
   the stacked status was. */
/* The Resume page's bar is the same: its name over the status (design system 2026-10-26). */
.doc-start:has(> .doc-title), .doc-start:has(> .doc-name) { flex-direction: column; align-items: flex-start; gap: 0; }
.doc-start .doc-title { font-weight: 600; font-size: var(--t-sm); line-height: 1.25; color: var(--ink); white-space: nowrap; }
.doc-start .re-meta { flex-direction: row; align-items: baseline; gap: 6px; }
.doc-start .re-meta > * + *::before { content: "\00B7"; margin-right: 6px; color: var(--ink-dim); }
.doc-name { display: grid; min-width: 0; line-height: var(--lh-md); }
.re-bar .doc-title { margin: 0; font-size: var(--t-sm); font-weight: 600; letter-spacing: 0; color: var(--ink); }
/* The master page's title is its h1, so it is the display face: a step larger than the bar's text. */
.re-bar h1.doc-title { font-size: var(--t-lg); line-height: var(--lh-lg); font-weight: 500; letter-spacing: var(--ls-lg); }
@media (max-width: 640px) { .re-bar h1.doc-title { font-size: var(--t-md); line-height: var(--lh-md); } }
.re-bar .doc-sub { font-size: var(--t-xs); color: var(--ink-dim); overflow-wrap: anywhere; }
.re-bar .doc-sub[hidden] { display: none; }
.doc-end { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
/* Ask AI: a quiet tool, outlined grey like Download (2026-10-15, owner: "it being blue makes it
   seem like the core CTA but it shouldn't be"). */
.view .re button.doc-ask { display: inline-flex; align-items: center; gap: 6px; min-height: 36px; margin: 0; padding: 0 14px 0 12px;
  border: 1px solid var(--line-strong); border-radius: 999px; background: var(--panel); color: var(--ink);
  font-weight: 500; box-shadow: none; }
/* The resume section's header (2026-10-16, views/job-resume.js resumeHead): its h2, one line on
   what the document is and what its bars mean, then the changes left with Review them, outlined in
   the accent and never filled (the job page's one filled button is its next-step card). Every
   line wraps; nothing clips. */
.resume-head { display: grid; gap: 6px; margin: 0 0 14px; min-width: 0; }
.resume-head h2 { margin: 0; font-size: var(--t-lg); line-height: var(--lh-lg); letter-spacing: var(--ls-lg); overflow-wrap: anywhere; }
@media (max-width: 640px) { .resume-head h2 { font-size: var(--t-md); line-height: var(--lh-md); letter-spacing: 0; } }
.resume-head .resume-lead { margin: 0; font-size: var(--t-sm); line-height: 1.45; color: var(--ink-dim); max-width: 70ch; }
.resume-head .resume-state { margin: 2px 0 0; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; }
.resume-head .resume-count { font-weight: 600; color: var(--ink); }
/* Review them is a plain secondary button (design system 2026-10-26); only its margin here. */
.view .resume-head button.resume-review { margin: 0; }
/* Show keywords (views/job-resume.js docBar): a toggle pill, outlined like Download; pressed
   reads as filled-in tint, and aria-pressed says it too. */
.view .re button.doc-kw { min-height: 36px; margin: 0; padding: 0 14px; border: 1px solid var(--line-strong); border-radius: 999px;
  background: var(--panel); color: var(--ink); font-weight: 500; box-shadow: none; }
.view .re button.doc-kw:hover { background: var(--panel-2); }
.view .re button.doc-kw[aria-pressed="true"] { border-color: var(--accent-strong); background: var(--accent-soft); color: var(--accent-strong); }
.view .re button.doc-kw:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: 2px; }
.view .re button.doc-kw[hidden] { display: none; }
.view .re button.doc-ask:hover { background: var(--panel-2); }
.view .re button.doc-ask[aria-pressed="true"] { border-color: var(--accent-strong); background: var(--accent-soft); color: var(--accent-strong); }
.view .re button.doc-ask:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: 2px; }
.doc-ask .rl-sparkle { fill: currentColor; stroke: none; flex: none; }
/* More looks the same on both editor bars (the job page's and the Resume page's re-more). */
.dm.doc-suggestions .dm-trigger, .dm.re-more .dm-trigger { padding: 0 12px 0 16px; border: 1px solid var(--line-strong); border-radius: var(--r-pill); }
.doc-suggestions .dm-menu, .re-more .dm-menu { min-width: 240px; }
/* Download on the job page is outlined: the page's one filled button is its next step. */
.dm.doc-download:not(.dm-is-primary) .dm-trigger { padding: 0 12px 0 16px; border: 1px solid var(--line-strong); border-radius: var(--r-pill); }
/* The master page (views/resume.js renderMaster): the same bar and pages, the same width as the
   job page's sections (main's column, owner ask 2026-10-06), starting right under the top bar;
   its title is in the bar. */
.view.master-view { width: 100%; max-width: none; box-sizing: border-box; }
.master-view .re { margin-bottom: 16px; border: 1px solid var(--line); }
.master-view > .panel, .master-view > .nudge { box-sizing: border-box; }
@media (min-width: 641px) { .view.master-view { margin-top: -24px; } }
/* Collapsed and opened on purpose (a clicked mark), or too narrow to dock: a drawer on the
   right, hidden until opened. */
.review-desktop.rail-collapsed .rail { position: fixed; top: 0; right: 0; bottom: 0; max-height: none; width: min(400px, 92vw); z-index: 40; border-radius: 0;
  box-shadow: var(--shadow-pop); }
.rail-head-buttons { display: flex; gap: 4px; }
.review-tablet .rail { position: fixed; top: 0; right: 0; bottom: 0; width: min(400px, 92vw); z-index: 40; border-radius: 0;
  box-shadow: var(--shadow-pop); }
.review-phone .rail { position: fixed; inset: 0; z-index: 40; border-radius: 0; }
/* The status row above the pages: on a phone Show keywords and Download, and the keyword
   legend when they are shown. Its old review-line sentence is no longer drawn (the next-step
   card says where the resume stands); its tone rules below are left over. */
.review-status { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin: 0 0 8px; }
.review-status > button { margin: 0; }
/* Since the job page flow (2026-10-05) the row has no sentence or action of its own: on a
   desktop or tablet with the keywords off it is empty, and takes no room. */
.review-status:empty { display: none; }
.review-line { margin: 0; font-weight: 600; min-width: 0; overflow-wrap: anywhere; }
.review-line.is-block { color: var(--blocker); }
.review-line.is-check { color: var(--risk-ink); }
.review-line.is-ok { color: var(--ok); }
.review-line.is-changed { color: var(--unknown); }
.review-status-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-left: auto; }
.review-status-tools button { margin: 0; }
/* Open in Google Docs: one line under the tools (views/job-resume.js gdocsLine). */
.gdocs-status { flex-basis: 100%; margin: 0; }
.gdocs-status button { margin: 0 0 0 4px; }
/* The Resume tab's copy of that line sits above its tab panels (views/resume.js). */
.master-gdocs:empty { display: none; }
.master-gdocs { margin: 0 0 12px; }
/* The Download menus (job page and Resume tab): each item reads on one line, "Open in Google
   Docs" and its "New Doc" hint included (they wrapped at the default 220px). */
.doc-download .dm-menu { min-width: 272px; max-width: calc(100vw - 32px); }
.doc-download .dm-item-label, .doc-download .dm-hint { white-space: nowrap; }
details.fold[data-fold="whatchanged"] { margin: 0 0 10px; }
.ai-note-line { margin: 4px 0 6px; }
/* The card anatomy (design system 2026-10-26), for every review, margin, part panel and end card:
   the title (what and why) with any .tag after it on the same row, ONE why line in the small
   muted type, the evidence, the action row, then the links row (Edit this line · Skip). */
.rl-card-head, .rl-card .rl-card-head, .rv-card-head { margin: 0; display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-start; gap: 4px 8px; }
.card-title { min-width: 0; font-weight: 600; color: var(--ink); overflow-wrap: anywhere; }
.card-why, .rl-card p.card-why, .walk-text.card-why { margin: 4px 0 0; font-size: var(--t-xs); font-weight: 400; line-height: 1.45; color: var(--ink-dim); overflow-wrap: anywhere; }
.rl-fix { display: grid; gap: 6px; margin-top: 6px; }
.rl-fix .field { margin: 0; }
.rl-fix > .rv-card-links { margin-top: 0; }
/* A labelled evidence block inside a card (a not_in_resume card's rewrite): small type, never a
   heading. */
.walk-ev { display: grid; gap: 4px; min-width: 0; }
.walk-ev-label { margin: 0; font-size: var(--t-xs); color: var(--ink-dim); }
.walk-ev-title { font-weight: 600; color: var(--ink); }
.walk-ev .card-why { margin: 0; }
/* Ask for changes, at the top of the margin (or the drawer and sheet). */
.ask-box .ask-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.ask-box h3 { margin: 0; font-size: var(--t-sm); }
.ask-box .ask-lead { margin: 4px 0 8px; color: var(--ink-dim); }
.ask-box .field { margin: 0 0 8px; }
.ask-starters { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 8px; }
/* The starters are visibly smaller than Suggest changes (design system 2026-10-26). */
.view .ask-starters button.chip { margin: 0; min-height: 24px; padding: 1px 8px; font-size: var(--t-xs); font-weight: 400; }
.review-phone .ask-starters button.chip { min-height: 44px; }
/* Suggest changes is the box's lead, left aligned, then the note on its cost. */
.ask-foot { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
.ask-foot .ask-note { margin: 0; }
.ask-foot .flag-buttons { margin: 0; }
.ask-foot button { margin: 0; }
.ask-earlier { margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--line); }
.ask-earlier summary { margin: 0 0 4px; font-size: var(--t-xs); font-weight: 600; cursor: pointer; }
.ask-earlier ul { margin: 0; padding: 0; list-style: none; display: grid; gap: 4px; }
.ask-request { font-style: italic; }
/* The one close control (design system 2026-10-26): the Ask box, the part panel and the walk's
   end card share it, an X in a small round icon button named Close. */
.view :is(.ask-box, .pp-head, .walk-head) button.icon-btn { display: inline-grid; place-items: center; min-height: 32px; min-width: 32px; margin: 0; padding: 4px;
  border: 0; border-radius: var(--r-pill); background: transparent; color: var(--ink-dim); box-shadow: none; }
.view :is(.ask-box, .pp-head, .walk-head) button.icon-btn:not(:disabled):hover { background: var(--panel-2); color: var(--ink); }
:is(.ask-box, .pp-head, .walk-head) button.icon-btn svg { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
@media (max-width: 640px) { .view :is(.ask-box, .pp-head, .walk-head) button.icon-btn { min-height: 44px; min-width: 44px; } }
.rl-review .rl-group-head h3 { margin: 0; }
/* The drawer and sheet: the same cards as one list. */
.rl-list { display: flex; flex-direction: column; gap: 8px; }
.rl-list > .ask-box { padding-bottom: 8px; border-bottom: 1px solid var(--line); }
.rail-title { margin: 0; font-size: var(--t-sm); }
.rl-history > button { margin: 0 0 8px; }
/* Edit it yourself: the one line, editable on the page. Fixed colours: the sheet is paper. */
.resume-preview .is-line-editing { outline: calc(1.5 * var(--pt)) solid var(--accent); outline-offset: 2px; border-radius: 2px; background: var(--accent-soft); cursor: text; }
.rail-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 8px 12px; border-bottom: 1px solid var(--line); }
.rail-head button { margin: 0; }
.view button.tab { min-height: 36px; margin: 0; padding: 6px 10px; border: 0; border-bottom: 3px solid transparent; border-radius: 0;
  background: none; color: var(--ink-dim); font-weight: 600; }
.view button.tab:not(:disabled):hover { color: var(--ink); background: var(--panel-2); }
.view button.tab.is-selected { color: var(--accent); border-bottom-color: var(--accent); }
.rail-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 10px 12px 14px; overflow-wrap: anywhere;
  /* The containing block for the cards' visually-hidden spans (position: absolute). Without it
     they resolve against the sticky .rail, escape this scroller's clip and sit at their place
     in the full card list, thousands of pixels down: the page scrolled far past the footer. */
  position: relative; }
.rail-body h3 { font-size: var(--t-sm); margin: 14px 0 6px; }
.rail-body > :first-child > h3:first-child, .rail-body > h3:first-child { margin-top: 4px; }
.rail .ask { margin: 0 0 8px; }
.rail-toggle { display: flex; gap: 6px; }
/* z-index 8, like the editor bar and the review head: the bar sticks to the foot only inside its
   section, so past the section's end it scrolls up with it and must pass UNDER the job bar (9)
   and the top bar (10), never over the job title (design review 2026-10-26). */
.review-bar { position: sticky; bottom: 0; z-index: 8; display: flex; gap: 8px; margin: 12px 0 0; padding: 8px 0;
  background: var(--panel); border-top: 1px solid var(--line); }
.view .review-bar button { flex: 1 1 0; min-height: 44px; margin: 0; }
/* Phone (design audit 2026-10-21): the pages end clear of the sticky bar. The pages column gets
   the bar's height (44px buttons, 8px padding twice, the 1px rule) below it, and the bar lifts
   into that room, so at the end of the pages the bar sits over blank desk, never a line. */
.review-phone > .review-main { padding-bottom: 61px; }
.review-phone > .review-bar { margin-top: -61px; }
/* Phone pages read as text, not a shrunk Letter page (design audit 2026-10-21: the to-scale
   sheet put the resume at about 5px). Under 640px the job page's pages reflow: 1pt is 1.4px, so
   the body is 14px, the sheets lose the Letter shape and stack as one white column, and the left
   padding keeps the changed-line bars inside the sheet. The breaks no longer match the printed
   pages here; every export still uses the printed layout (js/views/paper.js plans again from
   these sizes, and each sheet stays within its capacity, so it settles). */
@media (max-width: 639px) {
  .view.job .review-phone .resume-preview .sheet, .view.job .review-pages .resume-preview .sheet {
    --in: 50px; --pt: 1.4px; aspect-ratio: auto; padding: 0 14px 0 40px; box-shadow: none; }
  .view.job .review-phone .resume-preview .paper-ruler + .sheet, .view.job .review-pages .resume-preview .paper-ruler + .sheet { padding-top: 20px; }
  .view.job .review-phone .resume-preview .sheet:last-child, .view.job .review-pages .resume-preview .sheet:last-child { padding-bottom: 20px; }
  .view.job .review-phone .resume-preview .sheet + .sheet, .view.job .review-pages .resume-preview .sheet + .sheet { margin-top: 0; }
}
.review-phone .rail button { min-height: 44px; }
.review-phone .view button.tab, .review-phone button.tab { min-height: 44px; }
/* The cards. A suggestion is dashed like its marks; a run change is solid; a kept one quiet. */
.rl-cards { list-style: none; padding: 0; margin: 6px 0 12px; display: grid; gap: 8px; }
.rl-card { padding: 8px 10px; border: 1px solid var(--line); border-radius: var(--r-control); background: var(--panel); cursor: pointer; }
.rl-card:focus { outline: none; }
.rl-card.is-active { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
.rl-card-pending { border-style: dashed; border-color: var(--accent); }
.rl-card.is-stale { border-color: var(--line-strong); background: var(--panel-2); }
.rl-card.is-kept { background: var(--panel-2); }
.rl-card.is-check { border-color: var(--manual); }
.rl-card-rejected { cursor: default; }
.rl-card p { margin: 3px 0; }
.rl-card-head { font-size: var(--t-xs); color: var(--ink-dim); }
.rl-card-source { font-weight: 600; color: var(--ink); }
.rl-card-before { color: var(--ink-dim); text-decoration: line-through; }
.rl-card-after { color: var(--ink); }
.rl-card .flag-buttons button { margin: 0; }
.tag-kept { margin-left: 4px; }
.rl-group { margin: 4px 0 8px; }
.rl-group-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 4px 8px; }
.rl-group-head h4 { margin: 6px 0 0; font-size: var(--t-eyebrow); font-weight: 500; letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent); }
.rl-group-head button { margin: 0; }
.sent-note button { margin: 0 0 0 4px; }
.chat-alone .chat-panel { margin: 0; }
/* Pending suggestions on the pages: dashed, blue, so they read as offered, not made. Clicking
   any mark selects its card; the selected card's marks get an outline. Kept run changes go
   quiet. Fixed colours: the sheet is white paper whatever the theme. */
.resume-preview ins.rl-pending { text-decoration: underline dashed var(--accent); text-decoration-thickness: calc(1 * var(--pt));
  text-underline-offset: calc(1.5 * var(--pt)); color: var(--accent-strong); background: var(--accent-soft); }
.resume-preview del.rl-pending { text-decoration: line-through dashed var(--accent); color: var(--accent-strong); }
.resume-preview [data-rl] { cursor: pointer; }
.resume-preview .is-active { outline: calc(1.5 * var(--pt)) solid #f5c400; outline-offset: 1px; border-radius: 2px; }
.resume-preview ins.rl-ins.is-kept { background: none; }
/* Kept, so quieter: grey words, the red strike stays. Never opacity, which took the words under
   4.5:1 (WCAG 1.4.3). */
.resume-preview del.rl-del.is-kept { color: #5a626c; }
/* The rail reads at the app's compact UI size, not the page's body size, so three or four
   cards fit on a desktop screen: 14px text, 12px labels, compact buttons. A phone keeps its
   44px targets (above). A selected card scrolls to its own top edge. */
.rail { font-size: var(--t-xs); line-height: 1.4; }
.rail .hint, .rail .field .hint { font-size: var(--t-xs); }
.rail-body h3 { font-size: var(--t-sm); }
.rail .field label { font-size: var(--t-xs); }
.rail .field textarea { font-size: var(--t-xs); }
.rl-card p { font-size: var(--t-xs); line-height: 1.4; }
.rl-card .rl-card-head { font-size: var(--t-xs); }
.rl-card .tag { font-size: var(--t-eyebrow); }
.review-desktop .rail button:not(.tab), .review-tablet .rail button:not(.tab) { min-height: 28px; padding: 3px 10px; font-size: var(--t-xs); }
.view .review-desktop button.tab, .view .review-tablet button.tab { font-size: var(--t-sm); }
.rl-card { scroll-margin: 8px 0; }

/* Phase 3 of the redline review: Needs your OK as the first group of the rail's Changes tab. */
.rail-body .needs-ok { margin: 10px 0 4px; }
.rail-body .needs-ok:focus { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--r-control); }
.export-explain { margin: 4px 0 8px; }

/* Phase 4, the final review: the chip and Review beside the export buttons, and the Review
   group in the rail. Colour says the state (green reviewed, amber to check, red blocks); the
   words always say it too. */
.view button.review-chip.is-ok { border-color: var(--ok); background: var(--ok-bg); color: var(--ok); font-weight: 600; }
.view button.review-chip.is-check { border-color: var(--risk); background: var(--risk-bg); color: var(--risk-ink); font-weight: 600; }
.view button.review-chip.is-block { border-color: var(--blocker); background: var(--blocker-bg); color: var(--blocker); font-weight: 600; }
.view button.review-chip.is-changed { border-color: var(--line-strong); background: var(--unknown-bg); color: var(--unknown); font-weight: 600; }
.export .blocked { color: var(--blocker); }
.rail-body .rl-review { margin: 10px 0 4px; }
.rail-body .rl-review:focus { outline: none; }
/* Phase 5: the proofread's line in the Review group; a failure reads amber, never red (it does
   not block export). */
.rl-review .rl-proofread { font-weight: 600; }
.rl-review .rl-proofread.is-failed { color: var(--risk-ink); }
/* Final check is a group header row, not a card (2026-10-07): its counts in words beside the
   title, its lead and proofread as plain group text, and the finding cards that follow it
   indented with a left rule so they read as its own. */
.rl-group.rl-review { padding: 2px 0; }
.rl-group.rl-review:focus { outline: none; }
.rl-group-count { font-weight: 400; font-size: var(--t-xs); color: var(--ink-dim); }
.rl-group-text { margin: 2px 0 0; font-size: var(--t-xs); color: var(--ink-dim); }
.rl-review ~ .rl-finding,
.mc-card:has(> .rl-review) ~ .mc-card > .rl-finding { margin-left: 10px; border-left-width: 3px; }
.rl-finding.is-block { border-color: var(--blocker); }
.rl-finding.is-check { border-color: var(--risk); }
.rl-finding .rl-card-before { text-decoration: none; font-style: italic; }
.resume-preview .is-jumped { outline: calc(1.5 * var(--pt)) solid #f5c400; outline-offset: 2px; border-radius: 2px; }

/* Wording flags (2026-10-02, js/wording-marks.js): a dotted amber underline on the words the
   proofread points at. A bottom border, not a text-decoration, so it never fights a redline
   underline on the same words. Fixed colours: the sheet is white paper. */
.resume-preview .rl-wording { border-bottom: calc(1.5 * var(--pt)) dotted #b26a00; padding-bottom: calc(0.5 * var(--pt)); }
.rl-card-wording { border-color: #e2b46b; }
.rl-card-quote { font-style: italic; }
.rl-card-note { color: var(--ink); }
.review-notes { font-weight: 400; color: var(--ink-dim); }
.ask-hint { margin: 2px 0 6px; }

/* ------------------------------------------------------------ the job bar
   Owner feedback 2026-10-05: "a sticky head that keeps the logo and title but make them the
   right size when sticky". Once the job's title row has scrolled under the top bar, a compact
   bar (views/job.js headerSection: the logo at 28px and "Company: Role" at 15px) takes its place
   just under the top bar, full width like it, the text lined up with the page. A visual repeat
   of the h1, so aria-hidden and click-through. No script: a scroll-driven animation on the title
   row's view timeline shows it, so no repaint can lose it; a browser without scroll-driven
   animations simply never shows it. Fixed, so it takes no space and never reaches the footer. */
.job-head { timeline-scope: --aa-job-title; }
.job-title { view-timeline: --aa-job-title block; view-timeline-inset: var(--top-h) 0px; }
.job-sticky { position: fixed; top: var(--top-h); left: 0; right: 0; z-index: 9;
  display: flex; align-items: center; gap: 10px; min-height: 48px; padding: 6px var(--edge);
  background: var(--panel); border-bottom: 1px solid var(--line);
  pointer-events: none; visibility: hidden; opacity: 0; }
.job-sticky .logo { flex: 0 0 28px; width: 28px; height: 28px; margin: 0; }
.job-sticky .logo .mono { font-size: var(--t-xs); }
/* A long title wraps rather than truncating (never clipped text), so the bar may be taller than
   48px. js/job-bar.js measures it (ResizeObserver) and puts a job-bar-h-<px> class on <html>,
   its height rounded down to 4px (the CSP forbids style writes); --job-bar-h follows, and with
   it --sticky-h and the editor's bar parked flush below. The bar's own min-height stays a
   literal so a shrinking title can shrink it. */
.job-sticky-title { min-width: 0; font-size: var(--t-sm); font-weight: 650; line-height: 1.3; overflow-wrap: anywhere; }
html.job-bar-h-48 { --job-bar-h: 48px; } html.job-bar-h-52 { --job-bar-h: 52px; } html.job-bar-h-56 { --job-bar-h: 56px; }
html.job-bar-h-60 { --job-bar-h: 60px; } html.job-bar-h-64 { --job-bar-h: 64px; } html.job-bar-h-68 { --job-bar-h: 68px; }
html.job-bar-h-72 { --job-bar-h: 72px; } html.job-bar-h-76 { --job-bar-h: 76px; } html.job-bar-h-80 { --job-bar-h: 80px; }
html.job-bar-h-84 { --job-bar-h: 84px; } html.job-bar-h-88 { --job-bar-h: 88px; } html.job-bar-h-92 { --job-bar-h: 92px; }
html.job-bar-h-96 { --job-bar-h: 96px; } html.job-bar-h-100 { --job-bar-h: 100px; } html.job-bar-h-104 { --job-bar-h: 104px; }
html.job-bar-h-108 { --job-bar-h: 108px; } html.job-bar-h-112 { --job-bar-h: 112px; } html.job-bar-h-116 { --job-bar-h: 116px; }
html.job-bar-h-120 { --job-bar-h: 120px; } html.job-bar-h-124 { --job-bar-h: 124px; } html.job-bar-h-128 { --job-bar-h: 128px; }
html.job-bar-h-132 { --job-bar-h: 132px; } html.job-bar-h-136 { --job-bar-h: 136px; } html.job-bar-h-140 { --job-bar-h: 140px; }
html.job-bar-h-144 { --job-bar-h: 144px; } html.job-bar-h-148 { --job-bar-h: 148px; } html.job-bar-h-152 { --job-bar-h: 152px; }
html.job-bar-h-156 { --job-bar-h: 156px; } html.job-bar-h-160 { --job-bar-h: 160px; }
@supports (animation-timeline: view()) {
  .job-sticky { animation: aa-job-sticky linear both; animation-timeline: --aa-job-title; animation-range: exit-crossing 50% exit-crossing 100%; }
}
@keyframes aa-job-sticky {
  from { visibility: hidden; opacity: 0; }
  to { visibility: visible; opacity: 1; }
}
/* The reduced-motion rule above stops every animation. This one is a fade scrubbed by the
   scroll position, nothing moves, so it stays on (or the bar would never show there). */
@media (prefers-reduced-motion: reduce) {
  @supports (animation-timeline: view()) {
    .job-sticky { animation: aa-job-sticky linear both !important; animation-timeline: --aa-job-title !important;
      animation-range: exit-crossing 50% exit-crossing 100% !important; }
  }
}
@media print { .job-sticky { display: none !important; } }

/* The Cover letter section (views/job-letter.js): the offered letter in a quiet box, the
   letter editor (letter mode of js/resume-editor.js), and the actions in one row that wraps
   on a phone. */
#cover-letter .letter-offer { max-width: 70ch; border: 1px solid var(--line); border-radius: var(--r-card); padding: 12px 16px; margin-bottom: 16px; }
/* The letter's sheet is one Letter page wide at Fit (8.5in, as the resume's sheet reads), never
   the whole column: a 30cm sheet made a short letter 1,467px tall. Other zooms are unchanged. */
#cover-letter .re-main.re-z-fit { --re-w: min(100cqw - 48px, 8.5in); }
@media (max-width: 640px) { #cover-letter .re-main.re-z-fit { --re-w: min(100cqw - 16px, 8.5in); } }
#cover-letter .letter-para { margin: 0 0 12px; }
#cover-letter .letter-read { margin-bottom: 8px; }
#cover-letter .letter-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 10px; }
#cover-letter .letter-meta { margin-top: 8px; }
#cover-letter .letter-change { margin-top: 16px; }
#cover-letter .letter-change .field { margin-bottom: 8px; }
#cover-letter .letter-failed { margin-bottom: 16px; }
#cover-letter .letter-working { margin-top: 10px; }
/* A request button while a request is in flight: aria-disabled, not disabled, so it keeps focus
   across the repaint (views/job-letter.js requestButton). Drawn like a disabled button. */
#cover-letter button[aria-disabled="true"] { opacity: 0.6; cursor: not-allowed; }
#cover-letter button.secondary[aria-disabled="true"]:hover { background: var(--panel); border-color: var(--line); }

/* The accessibility floor (WCAG 2.2 AA audit, 2026-10-05; tool/public/style.css keeps the same
   rules). 2.5.8 Target Size: a fold's summary and the top-bar name are at least 24px tall.
   2.4.11 Focus Not Obscured: the phone's sticky review bar (rendered only under 768px) never
   covers the control that has focus, because the page scrolls focus clear of it. */
details > summary { min-height: 24px; }
.top .brand { min-height: 24px; }
html:has(.review-bar) { scroll-padding-bottom: 80px; }

/* Review my master (views/master-review.js): the cards beside the master editor's pages, in the
   job page margin's own column style, or a list under the bar on a narrower screen. */
.master-view .re-aside:has(.rail-margin) { position: static; max-height: none; overflow: visible; align-self: stretch; background: var(--panel-2); }
.master-view .rail-margin { box-sizing: border-box; width: 340px; min-height: 100%; padding: 18px 0 40px;
  border-width: 0 0 0 1px; border-color: var(--line); border-radius: 0; background: transparent; }
.mr-summary .mr-intro { margin: 0 0 6px; font-weight: 600; }
.master-review-list { display: grid; gap: 8px; padding: 12px 16px; background: var(--panel-2); }
.master-review-list .rl-card { padding: 12px 14px; border: 1px solid var(--line); border-radius: var(--r-card); background: var(--panel); }
.mr-card .mr-kind { margin: 0 0 4px; font-weight: 600; font-size: var(--t-xs); color: var(--ink-dim); }
.mr-card .mr-label { color: var(--muted); }
.mr-card p, .mr-card li, .mr-summary p { overflow-wrap: anywhere; }
.mr-lines { margin: 4px 0; padding-left: 18px; }
.mr-done { list-style: none; margin: 6px 0 0; padding: 0; }

/* The line workshop (views/part-panel.js, 2026-10-06): one mode. A line the tailoring changed
   carries a thin bar in the left margin (re-changed; softer once kept, re-kept), a line that
   holds export a red one (re-holds), and the selected part an outline (is-part). The bar is a
   positioned ::before, so no line moves and the pages paginate exactly as they print. The same
   classes on the phone's clean pages. Fixed colours: the sheet is white paper. */
.re-block.re-changed, .re-block.re-kept, .re-block.re-holds,
.resume-preview .re-changed, .resume-preview .re-kept, .resume-preview .re-holds { position: relative; }
.re-block.re-changed::before, .re-block.re-kept::before, .re-block.re-holds::before,
.resume-preview .re-changed::before, .resume-preview .re-kept::before, .resume-preview .re-holds::before {
  content: ""; position: absolute; top: 0; bottom: 0; left: calc(-0.32 * var(--in)); width: calc(2.5 * var(--pt));
  border-radius: calc(1.5 * var(--pt)); background: var(--accent); pointer-events: none; user-select: none; }
.re-block.re-kept::before, .resume-preview .re-kept::before { background: var(--line-strong); }
.re-block.re-holds::before, .resume-preview .re-holds::before { background: #b3261e; width: calc(3.5 * var(--pt)); }
.re-bullet.re-changed::before, .re-bullet.re-kept::before, .re-bullet.re-holds::before,
.resume-preview li.re-changed::before, .resume-preview li.re-kept::before, .resume-preview li.re-holds::before {
  left: calc(-0.32 * var(--in) - 16 * var(--pt)); }
.re-block.is-part, .resume-preview .is-part { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 2px; }
.re-block.is-jumped { outline: 2px solid #f5c400; outline-offset: 2px; border-radius: 2px; }
.review-phone .resume-preview li, .review-phone .resume-preview p, .review-phone .resume-preview h3 { cursor: pointer; }
/* Marks drawn without touching the page (js/text-highlights.js, the CSS Custom Highlight API):
   the posting's keywords, the wording notes and the lines a suggestion would change. */
::highlight(kw-have) { background-color: var(--kw-have-bg, #ece3fb); color: var(--kw-have-ink, #4c1d95); }
::highlight(kw-add) { background-color: var(--kw-add-bg, #ffd8b5); color: var(--kw-add-ink, #7c2d12); text-decoration: underline dotted; text-decoration-color: var(--kw-add-edge, #c2410c); text-decoration-thickness: 2px; }
::highlight(aa-wording) { text-decoration: underline dotted #b26a00; text-decoration-thickness: 1.5px; }
::highlight(aa-pending) { background-color: var(--accent-soft); text-decoration: underline dashed var(--accent); }
/* Editing (2026-10-26, owner: "edits should appear like Google Docs suggestions"): the words a
   change still to decide put in, underlined in the review's new-wording green; the words it took
   out are in its card's redline, since they are not in the text. */
::highlight(aa-insert) { background-color: #e6f4ea; text-decoration: underline solid #1f7a45; text-decoration-thickness: 2px; text-underline-offset: 2px; }
/* The part's panel: one card beside the part (the margin) or alone in the drawer or sheet.
   Every control at least 44px tall on a phone; long words wrap, nothing is clipped. */
.part-panel { display: grid; gap: 10px; min-width: 0; overflow-wrap: anywhere; cursor: default; }
.part-panel:focus { outline: none; }
.part-panel:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: 2px; }
.pp-head { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; }
.pp-head .pp-kind { margin: 0; flex: 1 1 auto; }
.pp-head > button:last-child { margin-left: auto; }
.part-panel p { margin: 0; }
.pp-line { font-style: italic; color: var(--ink-dim); }
.pp-change, .pp-dropped, .pp-chat, .part-panel .walk-stop { display: grid; gap: 6px; padding-top: 8px; border-top: 1px solid var(--line); }
.pp-master { padding: 6px 8px; border-radius: var(--r-control); background: var(--panel-2); }
.pp-master-text { font-size: var(--t-xs); }
.pp-dropped-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.pp-items { display: grid; gap: 8px; }
.pp-items > .rl-card { border: 1px solid var(--line); border-radius: var(--r-control); padding: 8px; }
.pp-chat-title { margin: 0; font-size: var(--t-xs); }
.pp-chat .field { margin: 0; }
.pp-chat .field textarea { width: 100%; box-sizing: border-box; min-height: 44px; }
.pp-chat-log { display: grid; gap: 4px; }
.pp-chat-request { font-style: italic; }
.pp-cost, .pp-result { font-size: var(--t-xs); }
.pp-nav { display: flex; align-items: center; gap: 8px; padding-top: 8px; border-top: 1px solid var(--line); }
.pp-hint { margin: 0 12px; }
@media (max-width: 767px) {
  .part-panel button, .part-panel textarea { min-height: 44px; }
}
.walk-card { display: grid; gap: 10px; min-width: 0; overflow-wrap: anywhere; cursor: default; }
.walk-card:focus { outline: none; }
.walk-card:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: 2px; }
.walk-head { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; }
.walk-head .walk-pos, .walk-head .walk-title { margin: 0; font-weight: 600; font-size: var(--t-xs); color: var(--ink-dim); }
.walk-head > button:last-child { margin-left: auto; }
.walk-text { margin: 0; font-weight: 600; }
/* What a keyword means in this posting, one quiet line under its question (core/keyword-sense.mjs). */
.walk-meaning { display: block; margin-top: 4px; font-weight: 400; color: var(--ink-dim); font-size: var(--t-xs); }
.walk-line { margin: 0; }
.walk-line-label { margin: 0; font-size: var(--t-xs); }
.walk-line-text { margin: 2px 0 0; }
.walk-line.is-after .walk-line-text { color: var(--accent-strong); }
.walk-copies, .walk-rewrites { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.walk-copy, .walk-rewrite { display: grid; gap: 6px; padding-top: 8px; border-top: 1px solid var(--line); }
.walk-fill { display: grid; gap: 8px; }
.walk-fill .field { margin: 0; }
.walk-fill .field input, .walk-fill .field textarea { width: 100%; box-sizing: border-box; min-height: 44px; }
.walk-preview { padding: 8px 10px; border-radius: var(--r-control); background: var(--panel-2); }
.walk-preview p { margin: 0; }
.walk-preview .walk-preview-line { margin-top: 2px; }
/* The scope switch (2026-10-20, owner: "a button in a box that's not centered"): its label on the
   left, the two choices as equal pills on the same line, centred on it; no box around the pills.
   Where the card is narrow (the review bar, a phone) the pills wrap under the label. The selected
   one is a pale accent tint with accent text and a check (design review 2026-10-20: the solid
   fill read as the card's lead button, which stays the one filled button); keyboard and the focus
   ring are the segmented control's own.
   contrast-pairs: --accent-strong on --accent-soft; --accent on --panel */
.walk-scope { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; min-width: 0; }
.walk-scope .walk-scope-label { font-size: var(--t-xs); font-weight: 600; color: var(--ink-dim); }
.view .walk-scope fieldset.segmented, .walk-scope fieldset.segmented { flex: 0 1 auto; margin: 0; padding: 0; border: 0; min-width: 0; }
/* The scope switch keeps the shared segmented look (above), two equal pills, a size smaller. */
.walk-scope .segments { display: grid; grid-template-columns: 1fr 1fr; }
.walk-scope .segment { min-height: 36px; font-size: var(--t-xs); }
@media (max-width: 767px) { .walk-scope .segment { min-height: 44px; } }
.walk-conflict { display: grid; gap: 6px; padding: 8px 10px; border: 1px solid var(--line); border-radius: var(--r-control); }
.walk-conflict p { margin: 0; }
.walk-done p { margin: 0; }
.walk-drafts { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; }
.walk-drafts p { margin: 0; }
.walk-nav { display: flex; flex-wrap: wrap; gap: 8px; padding-top: 8px; border-top: 1px solid var(--line); }
.view .rail .walk-card button:not(.tab), .view .walk-card button { min-height: 44px; margin: 0; padding: 6px 12px; font-size: var(--t-xs); white-space: normal; }
/* An outlined lead (the part panel demotes the filled one, the end card's Done, and the review
   card's lead while the next-step card shows its filled primary, views/job.js outlineCardLeads);
   a filled lead keeps its filled colours. */
.view .walk-card button.walk-lead:not(.primary) { border-color: var(--accent-strong); color: var(--accent-strong); font-weight: 700; }
.view .rv-card .flag-buttons button.walk-lead:not(.primary) { border-color: var(--accent); color: var(--accent); font-weight: 600; }
.view .walk-card .flag-buttons { display: flex; flex-wrap: wrap; gap: 8px; }

/* ==== Job page declutter (2026-10-06) and design refresh phase 2 (2026-10-16; views/job.js
   headerSection, stepsSection, nextStepSection, companySection). Scoped under .view.job so it
   outranks the earlier app-parity.css rules it replaces (that file loads after this one).
   Phase 2, owner feedback ("plain, drab and lifeless"; every surface was the same white box with a
   1px border, so nothing led): the header is borderless, the four steps are one quiet line inside
   it, the next-step card is the page's ONE raised surface (24px padding, a 24px title, the primary
   button inside), and Important callouts and About the company are borderless sections under the
   card with an 18px heading and 32px between them. Measured at 1440x900: the primary button is on
   screen without scrolling. ==== */
/* The eyebrow line (the company, where, how it is worked, the pay) over the role, the h1. Both
   wrap, never clip. */
.view.job .job-head .job-title { align-items: flex-start; gap: 14px; }
/* The header's logo tile is as tall as the eyebrow line and the h1 beside it (15px x 1.4, its 4px
   margin, 32px x 1.1: about 60.2px; on a phone the 24px x 1.2 h1 makes it about 53.8px), top-aligned
   with the eyebrow (owner, 2026-10-16: "a bit bigger on the job page"). The pinned bar keeps 28px. */
.view.job .job-head .job-title { --head-logo: calc(var(--t-sm) * 1.4 + 4px + var(--t-xl) * var(--lh-xl)); }
@media (max-width: 640px) { .view.job .job-head .job-title { --head-logo: calc(var(--t-sm) * 1.4 + 4px + var(--t-lg) * var(--lh-lg)); } }
.view.job .job-head .job-title .logo { margin-top: 0; flex-basis: var(--head-logo); width: var(--head-logo); height: var(--head-logo); }
.view.job .job-head .job-title .logo .mono { font-size: calc(var(--head-logo) * 0.45); }
.view.job .job-head .job-title-text { flex: 1 1 260px; min-width: 0; }
.view.job .job-head .job-title-text h1 { margin: 0; font-size: var(--t-xl); line-height: var(--lh-xl); letter-spacing: var(--ls-xl); overflow-wrap: anywhere; }
.view.job .job-head .job-meta { margin: 0 0 4px; font-size: var(--t-sm); line-height: 1.4; color: var(--ink-dim); overflow-wrap: anywhere; }
.view.job .job-head .job-company { font-weight: 600; color: var(--ink); overflow-wrap: anywhere; }
@media (max-width: 640px) { .view.job .job-head .job-title-text h1 { font-size: var(--t-lg); line-height: var(--lh-lg); } }
/* The meta line's facts (how the job is worked, the pay), a step darker than the rest. */
.view.job .job-meta .job-fact { color: var(--ink); font-weight: 600; }
/* What the job is, one line under the h1. */
.view.job .job-head .whatrole { margin: 10px 0 0; max-width: 75ch; line-height: 1.5; color: var(--ink-dim); font-weight: 400; }
/* The stepper as one quiet line in the header (phase 2; no card): small numbered marks joined by
   a short line, done steps a check, the current one filled and its words bold in the accent
   colour. The line before a step is that step's ::before, coloured once the step is reached. */
.view.job .flow-steps { margin: 16px 0 0; padding: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 0;
  background: transparent; border: 0; border-radius: 0; font-size: var(--t-sm); color: var(--ink-dim); }
.view.job .flow-step { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; min-width: 0; padding: 2px 0; border-bottom: 0; }
.view.job .flow-step + .flow-step::before { content: ""; flex: 0 0 20px; min-width: 20px; height: 2px; margin: 0 10px; border-radius: 2px; background: var(--line-strong); }
.view.job .flow-step.is-done::before, .view.job .flow-step.is-current::before { background: var(--accent); }
.view.job .flow-step-mark { flex: none; display: inline-grid; place-items: center; width: 24px; height: 24px; border-radius: 999px;
  border: 2px solid var(--line-strong); background: var(--panel); color: var(--ink-dim); font-size: var(--t-xs); font-weight: 700; font-variant-numeric: tabular-nums; }
.view.job .flow-step-label { white-space: nowrap; }
.view.job .flow-step.is-done { color: var(--ink); }
.view.job .flow-step.is-done .flow-step-mark { border-color: var(--ok); background: var(--ok-bg); color: var(--ok); }
.view.job .flow-step.is-current { color: var(--accent); font-weight: 700; }
.view.job .flow-step.is-current .flow-step-mark { border-color: var(--accent); background: var(--accent); color: var(--on-accent); }
@media (max-width: 520px) {
  .view.job .flow-steps { font-size: var(--t-xs); }
  .view.job .flow-step { gap: 6px; }
  .view.job .flow-step + .flow-step::before { flex-basis: 10px; min-width: 10px; margin: 0 6px; }
  .view.job .flow-step-mark { width: 22px; height: 22px; font-size: 11px; }
}
.view.job .job-head .job-fit { margin: 10px 0 0; }
.view.job .job-head .job-status { margin: 16px 0 0; }
/* The next-step card: the page's one raised surface, with phase 1's card shadow. */
.view.job .next-step { margin: 0 0 24px; padding: 24px; border-color: transparent;
  box-shadow: var(--shadow-card); }
.view.job .next-step > h2 { margin: 0 0 6px; font-size: var(--t-lg); line-height: var(--lh-lg); letter-spacing: var(--ls-lg); }
.view.job .next-step .next-sub { margin: 0 0 16px; font-size: var(--t-sm); }
/* Every other panel on the job page sits flat, so only the card lifts. */
.view.job .panel:not(.next-step) { box-shadow: none; }
/* Important callouts and About the company: borderless sections on the page background under the
   card, 32px apart, with an 18px heading. */
/* The cover letter sits in the same container as the resume (owner, 2026-10-26: "the cover letter
   section needs to be in a container just like the resume section"): the .panel box, padded like
   #resume with its editor. Before apply stays a flat section. */
.view.job #before-apply { margin: 32px 0; padding: 0; background: transparent; border: 0; border-radius: 0; box-shadow: none; }
.view.job #cover-letter { margin: 32px 0 16px; padding: 16px; }
.view.job #before-apply > h2 { margin: 0 0 12px; font-size: var(--t-md); line-height: var(--lh-md); }
/* Check before you apply (2026-10-21): a lead line, then groups with their own small heading;
   each risk row is its label and verdict over two plain lines. */
.view.job #before-apply .ba-lead { margin: -4px 0 16px; max-width: 70ch; }
.view.job #before-apply .ba-group { margin: 0 0 20px; }
.view.job #before-apply .ba-group-h { margin: 0 0 8px; font-size: var(--t-sm); font-weight: 600; color: var(--ink); }
.view.job #before-apply .ba-count { font-weight: 400; color: var(--ink-dim); }
.view.job #before-apply .before-list { gap: 12px; max-width: 75ch; }
.view.job #before-apply .ba-body { display: grid; gap: 2px; line-height: 1.5; }
.view.job #before-apply .ba-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; }
.view.job #before-apply .ba-line { font-size: var(--t-sm); color: var(--ink-dim); }
/* Risks as cards (2026-10-21, owner: the plain list "looks oddly empty"). */
.view.job #before-apply .ba-group-risks .before-list { max-width: none; grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr)); gap: 12px; }
.view.job #before-apply .ba-card { display: block; padding: 14px 16px; background: var(--panel); border: 1px solid var(--line); border-left: 4px solid var(--unknown); border-radius: var(--r-card); box-shadow: var(--shadow-rest); }
.view.job #before-apply .ba-card.ba-risk { border-left-color: var(--risk); }
.view.job #before-apply .ba-card.ba-blocker { border-left-color: var(--blocker); }
.view.job #before-apply .ba-card .ba-body { gap: 8px; }
.view.job #before-apply .ba-card .ba-head { align-items: center; gap: 8px; }
.view.job #before-apply .ba-card .ba-head .dot { display: none; }
.view.job #before-apply .ba-card .ba-head b { font-size: var(--t-md); }
.view.job #before-apply .ba-card .ba-line { display: grid; gap: 1px; }
.view.job #before-apply .ba-card .ba-k { font-size: var(--t-xs); color: var(--ink-dim); }
.view.job #before-apply .ba-card .ba-v { color: var(--ink); }
.view.job #before-apply button.ba-more { margin: 8px 0 0; }
.view.job #before-apply .screener .scr-q { font-weight: 500; color: var(--ink); }
.view.job #before-apply .screener .scr-req { margin-left: 0; }
.view.job #before-apply .screener .scr-opts { display: inline; font-size: var(--t-sm); }
/* The top of the job page in two columns from 1100px (owner, 2026-10-21: the top part did not
   use the width, and Check before you apply and About this role sat oddly between the next-step
   card and the posting): the header and the next-step card on the left, Check before you apply
   beside them on the right, ruled off; everything after spans the page. Grid placement only, so
   the reading order stays header, card, Check before you apply. */
@media (min-width: 1100px) {
  .view.job:has(> #before-apply) { display: grid; grid-template-columns: minmax(0, 1fr) minmax(340px, 400px); column-gap: 40px; align-items: start; }
  .view.job:has(> #before-apply) > * { grid-column: 1 / -1; min-width: 0; }
  .view.job:has(> #before-apply) > .job-head,
  .view.job:has(> #before-apply) > #manage,
  .view.job:has(> #before-apply) > .next-step { grid-column: 1; }
  .view.job > #before-apply { grid-column: 2; grid-row: 1 / span 3; margin: 0; padding-left: 32px; border-left: 1px solid var(--line); border-radius: 0; }
  .view.job > #before-apply .ba-group-risks .before-list { grid-template-columns: minmax(0, 1fr); }
}
/* Compact in the side column, so it stays about the header and card's height: each risk is its label and
   verdict over one line, "Posting: ... · You: ...". */
.view.job > #before-apply > h2 { margin: 0 0 4px; }
.view.job > #before-apply .ba-lead { margin: 0 0 12px; }
.view.job > #before-apply .ba-group { margin: 0 0 14px; }
.view.job > #before-apply .ba-group:last-child { margin-bottom: 0; }
.view.job > #before-apply .ba-group-risks .before-list { gap: 8px; }
.view.job > #before-apply .ba-card { padding: 8px 12px; box-shadow: none; }
.view.job > #before-apply .ba-card .ba-body { gap: 2px; }
.view.job > #before-apply .ba-card .ba-head b { font-size: var(--t-sm); }
.view.job > #before-apply .ba-card .ba-line { display: block; font-size: var(--t-xs); line-height: 1.45; }
.view.job > #before-apply .ba-card .ba-v { color: var(--ink-dim); }
.view.job > #before-apply .before-list { gap: 6px; font-size: var(--t-sm); }
/* About the company inside the header since 2026-10-21 (owner: "I would assume it'd be part of
   the header part that talks about the company and role"). */
.view.job .job-head .job-about { margin: 12px 0 0; max-width: 75ch; }
.view.job .job-head .job-about-h { margin: 0 0 4px; }
.view.job .job-head .job-about .blurb-text { margin: 0 0 6px; line-height: 1.55; color: var(--ink); }
.view.job .job-head .job-about .job-ratings { margin: 0; }
/* The to-do rows inside the card: a rule above, no box of their own. */
.view.job .next-step .flow-todo { margin: 16px 0 0; padding: 12px 0 0; border-top: 1px solid var(--line); }
@media (max-width: 640px) {
  /* The four steps fit one line on a phone: no connectors, a 12px gap. */
  .view.job .flow-steps { gap: 6px 12px; }
  .view.job .flow-step + .flow-step::before { display: none; }
  /* The header's More stays on the title's row rather than taking a row of its own. */
  .view.job .job-head .job-title { flex-wrap: nowrap; }
  .view.job .job-head .job-title-text { flex: 1 1 0; }
  .view.job .job-head .job-title-actions { flex: none; margin-left: 0; }
  .view.job .next-step { padding: 20px; }
  .view.job .next-step > h2 { font-size: 21px; }
  .view.job #before-apply { margin: 28px 0; }
}
/* The next-step card: the one raised card on the job page. */
.next-step { box-shadow: var(--shadow-card); }
/* The grade in the next-step card after tailoring: the letter, one line saying what it measures,
   and a link down to the full section, which sits under the resume. */
.view.job .grade-summary { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin: 14px 0 0; padding: 12px 0 0; border-top: 1px solid var(--line); }
.view.job .grade-summary .grade-letter { flex: none; min-width: 34px; font-size: var(--t-md); }
.view.job .grade-summary-text { flex: 1 1 260px; margin: 0; font-size: var(--t-xs); color: var(--ink-dim); }
.view.job .grade-summary-text b { color: var(--ink); }
/* Grade progress (design review 2026-10-20): a tailored letter lower than the core resume's gets
   one plain line of its own row saying why and what raises it (views/grade.js gradeLowerLine). */
.view.job .grade-summary .grade-lower { flex: 1 0 100%; margin: 0; font-size: var(--t-sm); color: var(--ink); }
.view.job .grade-summary button.quiet { margin: 0; }

/* The drawer and the phone sheet have their own Close; the panel's is for the margin only
   (browser check 2026-10-06: two Close buttons). */
.rail-drawer .part-panel [data-key="part-close"],
.rail-sheet .part-panel [data-key="part-close"] { display: none; }

/* The Resume tab (views/resume.js renderMaster): "Your resume" and "Additional notes (N)" as a
   tablist above the page; then Additional notes (views/master-notes.js): numbered entries, each
   its words in the one-line editor, a quiet meta line and Remove. Text wraps, never scrolls
   sideways; 44px targets. */
.master-view .master-tabs { display: flex; flex-wrap: wrap; gap: 4px; margin: 0 0 12px; border-bottom: 1px solid var(--line); }
.master-view .master-tabs button.tab { min-height: 44px; font-size: var(--t-sm); padding: 8px 14px; }
.master-view .master-notice:empty { display: none; }
.master-view .additional-notes { max-width: 860px; }
.master-view .additional-notes .notes-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 12px; }
.master-view .additional-notes .notes-head h2 { margin: 0; }
.master-view .additional-notes .actions { display: flex; flex-wrap: wrap; gap: 8px 12px; align-items: center; margin: 8px 0 12px; }
.master-view .additional-notes button { min-height: 44px; }
.master-view .notes-list { list-style: none; margin: 0; padding: 0; }
.master-view .notes-list .note { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 4px 12px; align-items: start; padding: 10px 0; border-top: 1px solid var(--line); }
.master-view .note-num { min-width: 2.2em; padding-top: 10px; text-align: right; color: var(--ink-dim); font-variant-numeric: tabular-nums; }
.master-view .note-body { min-width: 0; }
/* The one-line editor draws its own edge (resume-editor.css .re-is-single); no second box. */
.master-view .note-text { overflow-wrap: anywhere; }
.master-view .note-text .re { margin: 0; }
.master-view .note-text .re-is-single .re-sheet { min-height: 44px; padding: 10px 12px; box-sizing: border-box; }
.master-view .note-foot { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 12px; margin: 4px 0 0; }
.master-view .note-meta { margin: 0; font-size: var(--t-xs); overflow-wrap: anywhere; }
.master-view .note-status-slot:empty { display: none; }
.master-view .note-add { margin: 0 0 12px; }
.master-view .note-add-label { margin: 0 0 4px; font-weight: 600; }
.master-view .notes-undo { display: flex; flex-wrap: wrap; gap: 8px 12px; align-items: center; margin: 0 0 8px; }
.master-view .notes-undo p { margin: 0; }
.master-view .notes-facts { margin: 4px 0 0; padding-left: 20px; overflow-wrap: anywhere; }
/* The Change log tab (views/master-changelog.js): read only, grouped by day. */
.master-view .change-log { max-width: 860px; }
.master-view .change-log h2 { margin: 0 0 4px; }
.master-view .clog-day-h { margin: 20px 0 4px; font-size: var(--t-sm); color: var(--ink-dim); }
.master-view .clog-list, .master-view .clog-older-list { list-style: none; margin: 0; padding: 0; }
.master-view .clog-event, .master-view .clog-older-list > li { padding: 10px 0; border-top: 1px solid var(--line); overflow-wrap: anywhere; }
.master-view .clog-title, .master-view .clog-older-text { margin: 0; }
.master-view .clog-time { font-variant-numeric: tabular-nums; margin-right: 4px; }
.master-view .clog-job { margin: 4px 0 0; }
.master-view .clog-fold { margin: 4px 0 0; }
.master-view .clog-fold button { min-height: 44px; margin-top: 8px; }
.master-view .clog-lines { margin: 4px 0; padding-left: 20px; }
.master-view .clog-lines li { margin: 2px 0; }
.master-view .clog-sub { margin: 8px 0 0; font-weight: 600; }
.master-view .clog-older { margin-top: 28px; }
.master-view .clog-older h3 { margin: 0 0 4px; }
@media (max-width: 599px) {
  .master-view .notes-list .note { grid-template-columns: auto minmax(0, 1fr); }
  .master-view .notes-list .note > button { grid-column: 2; justify-self: start; }
}
/* I have this on a claim card: the flagged line, quoted for context above his empty box. */
.claim-context .claim-quote { margin: 0 0 8px; padding: 6px 10px; border-left: 3px solid var(--line); color: var(--ink-dim); overflow-wrap: anywhere; }

/* The review view (PR B, 2026-10-07, views/review-view.js): the tailored resume as read-only redline
   pages, with ONE bar pinned to the window's foot that walks the review's stops. The editor stays
   mounted but hidden (.review-hidden). js/views/review-view.js watchReviewBar measures the bar
   and puts an rv-bar-h-<px> class on <html> (16px steps, the CSP forbids style writes), which sets
   --rv-bar-h: the page's bottom padding and every block's scroll margin, so the current line is
   never under the bar or under the pinned top bars. */
:root { --rv-bar-h: 200px; }
html.rv-bar-h-64 { --rv-bar-h: 64px; } html.rv-bar-h-80 { --rv-bar-h: 80px; } html.rv-bar-h-96 { --rv-bar-h: 96px; }
html.rv-bar-h-112 { --rv-bar-h: 112px; } html.rv-bar-h-128 { --rv-bar-h: 128px; } html.rv-bar-h-144 { --rv-bar-h: 144px; }
html.rv-bar-h-160 { --rv-bar-h: 160px; } html.rv-bar-h-176 { --rv-bar-h: 176px; } html.rv-bar-h-192 { --rv-bar-h: 192px; }
html.rv-bar-h-208 { --rv-bar-h: 208px; } html.rv-bar-h-224 { --rv-bar-h: 224px; } html.rv-bar-h-240 { --rv-bar-h: 240px; }
html.rv-bar-h-256 { --rv-bar-h: 256px; } html.rv-bar-h-272 { --rv-bar-h: 272px; } html.rv-bar-h-288 { --rv-bar-h: 288px; }
html.rv-bar-h-304 { --rv-bar-h: 304px; } html.rv-bar-h-320 { --rv-bar-h: 320px; } html.rv-bar-h-336 { --rv-bar-h: 336px; }
html.rv-bar-h-352 { --rv-bar-h: 352px; } html.rv-bar-h-368 { --rv-bar-h: 368px; } html.rv-bar-h-384 { --rv-bar-h: 384px; }
html.rv-bar-h-400 { --rv-bar-h: 400px; } html.rv-bar-h-416 { --rv-bar-h: 416px; } html.rv-bar-h-432 { --rv-bar-h: 432px; }
html.rv-bar-h-448 { --rv-bar-h: 448px; } html.rv-bar-h-464 { --rv-bar-h: 464px; } html.rv-bar-h-480 { --rv-bar-h: 480px; }
html.rv-bar-h-496 { --rv-bar-h: 496px; } html.rv-bar-h-512 { --rv-bar-h: 512px; }
.review-hidden { display: none !important; }
html:has(.rv-bar) body { padding-bottom: calc(var(--rv-bar-h) + 16px); }
.review-pages { margin-top: 8px; }
.review-legend { margin: 0 0 8px; }
.review-pages .resume-preview :is(li, p, h1, h2, h3) {
  scroll-margin-top: calc(var(--sticky-h) + 12px); scroll-margin-bottom: calc(var(--rv-bar-h) + 12px);
}
/* An open suggestion reads as a tracked change here: struck and underlined with a tint, scoped to
   the review pages so the editor's marks are unchanged. */
.review-pages ins.rl-pending { text-decoration: underline solid var(--accent); background: var(--accent-soft); color: var(--accent-strong); }
/* A posting keyword the tailoring added, inside new wording (design review 2026-10-20): orange
   only (app-parity.css .rl-kw-add). An inline-block does not take its parent insert's green
   underline, so orange always means "keyword added for this job". */
.review-pages ins .rl-kw-add { display: inline-block; }
.review-pages ins .rl-kw-have { display: inline-block; }
.review-pages del.rl-pending { text-decoration: line-through solid var(--accent); background: var(--accent-soft); color: var(--accent-strong); }
.view .rv-bar {
  position: fixed; z-index: 35; bottom: 0; left: max(16px, calc((100vw - 1360px) / 2)); right: max(16px, calc((100vw - 1360px) / 2));
  /* At most 45vh, its body scrolling inside, so the stop's line always has room above it (round 2,
     2026-10-07: the fill form grew the bar over the line). */
  max-height: 45vh; display: flex; flex-direction: column; margin: 0; padding: 0;
  background: var(--panel); border: 1px solid var(--line-strong); border-bottom: 0; border-radius: var(--r-card) var(--r-card) 0 0;
  box-shadow: var(--shadow-pop);
}
.rv-inner { display: flex; flex-direction: column; gap: 6px; flex: 1 1 auto; min-height: 0; overflow: hidden; padding: 12px 16px 10px; }
.rv-pos { margin: 0; display: flex; gap: 8px; align-items: center; color: var(--ink-dim); font-size: var(--t-xs); font-variant-numeric: tabular-nums; }
.rv-body { display: grid; gap: 8px; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
.rv-body .walk-line { margin: 0; }
.rv-body .walk-rewrites { margin: 0; padding: 0; list-style: none; display: grid; gap: 8px; }
.rv-nav { flex: none; }
@media (max-width: 767px) {
  .view .rv-bar { left: 0; right: 0; border-radius: 0; max-height: 45vh; }
  .rv-inner { padding: 10px 12px; }
  .rv-nav button { flex: 1 1 auto; }
}

/* Card flow (2026-10-07, owner feedback): a change shown as a compact inline redline of its line
   (views/change-diff.js), the last decision's "Kept. Undo" line in the review bar, and the
   Completed group decided cards move into. */
.cd-line { margin: 0; line-height: 1.5; overflow-wrap: anywhere; }
.cd-line del.cd-del { color: var(--danger); text-decoration: line-through; }
.cd-line ins.cd-ins { color: var(--ink); background: var(--accent-soft); text-decoration: underline; text-underline-offset: 2px; }
.walk-line-title { margin: 0 0 2px; color: var(--ink); font-weight: 600; font-size: var(--t-sm, 14px); }
.rv-last { margin: 0; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; color: var(--ink-dim); font-size: var(--t-xs); }
.rv-line-pos { margin: 0; color: var(--ink-dim); font-size: var(--t-xs); font-variant-numeric: tabular-nums; }
.mc-completed { margin-top: 8px; border-top: 1px solid var(--line); padding-top: 6px; }
.mc-completed > summary { cursor: pointer; color: var(--ink-dim); font-size: var(--t-xs); }
.mc-completed[open] > summary { margin-bottom: 6px; }

/* Suggestions mode (2026-10-15, views/review-view.js reviewSplit): on a wide desktop the review is
   a Docs-style split. A sticky head across the section (what the marks mean, the keyword tally,
   Change i of n, Previous, Next, Done reviewing), then the redline pages and a rail whose cards
   sit beside their lines (js/margin-cards.js). Closed cards show one line; the current one is
   open with its choices. */
/* No gap above the head (2026-10-26, owner: "Reviewing your resume text should be near the top of
   the header, there's some weird white space"): the section's own padding is the only space. */
.rv-split { margin-top: 0; }
/* z-index 8, the editor bar's: under the job bar (9) and the top bar (10), so when the resume
   section scrolls away (toward the cover letter) the head slides under the pinned bars, not over. */
/* Two columns lined up with .rv-cols below (2026-10-26, owner: the arrows and Done reviewing were
   "just floating over there, it's not clear it goes to the cards"): the pages' column, then the
   rail's exact 320px, the 1px padding standing in for .rv-cols' edge, so the navigator sits right
   over the cards it drives. */
.rv-head {
  position: sticky; top: var(--sticky-h); z-index: 8; display: grid;
  grid-template-columns: minmax(0, 1fr) 320px; align-items: start; gap: 0; padding: 4px 1px 12px; margin-bottom: 12px;
  /* No box of its own (design audit 2026-10-21: a box inside the section's box); the panel fill
     covers the pages scrolling under it, and one rule under it (2026-10-26, owner: "there's no
     line for the sticky resume header") makes it read as a header over them. */
  background: var(--panel); border-bottom: 1px solid var(--line);
}
.rv-head-info { display: grid; gap: 4px; min-width: 0; align-self: start; padding-right: 16px; }
/* The title, its "?" right after it, then the keyword tally and the last choice. */
.rv-title-row { display: flex; align-items: center; gap: 8px; min-width: 0; }
.rv-head h2.rv-title { margin: 0; font-size: var(--t-md); line-height: var(--lh-md); min-width: 0; }
/* What the colours mean (2026-10-26, owner: "a ? in a circle next to the title with that info as
   a click-on popover"): a 24px round button and a panel under it, placed by classes only. */
.rv-help { position: relative; display: inline-flex; flex: none; }
.view .rv-head button.rv-help-btn, .view .letter-section-head button.rv-help-btn {
  width: 24px; height: 24px; min-width: 24px; min-height: 24px; margin: 0; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line-strong); border-radius: var(--r-pill); background: var(--panel);
  color: var(--ink-dim); font-size: var(--t-xs); font-weight: 700; line-height: 1;
}
.view .rv-head button.rv-help-btn:hover, .view .rv-head button.rv-help-btn[aria-expanded="true"],
.view .letter-section-head button.rv-help-btn:hover, .view .letter-section-head button.rv-help-btn[aria-expanded="true"] { border-color: var(--accent); color: var(--accent); }
.view .rv-head button.rv-help-btn:focus-visible, .view .letter-section-head button.rv-help-btn:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.rv-pop {
  position: absolute; top: calc(100% + 8px); left: -8px; z-index: 12; box-sizing: border-box;
  width: min(360px, calc(100vw - 32px)); padding: 12px 14px;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-card); box-shadow: var(--shadow-pop);
}
.rv-pop[hidden] { display: none; }
.rv-pop-title { margin: 0 0 8px; font-size: var(--t-xs); font-weight: 600; color: var(--ink); }
/* One shared grid (design review 2026-10-26): every sample in the first column, every meaning in the second, so the text lines up. */
.rv-pop .rv-keys { grid-template-columns: max-content 1fr; gap: 8px 12px; align-items: baseline; font-size: var(--t-xs); }
.rv-pop .rv-key { grid-column: 1 / -1; grid-template-columns: subgrid; gap: 0 12px; }
.rv-keys { margin: 0; padding: 0; list-style: none; display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 8px 24px; max-width: 110ch; font-size: var(--t-sm); color: var(--ink-dim); }
.rv-key { display: grid; grid-template-columns: 9.5em 1fr; align-items: baseline; gap: 12px; }
.rv-key > .rv-swatch, .rv-key > .rv-pill { justify-self: start; }
.rv-key-text { display: grid; gap: 1px; }
.rv-key-name { color: var(--ink); font-weight: 600; }
.rv-keys-off { margin: 8px 0 0; max-width: 64ch; font-size: var(--t-sm); }
.rv-pill { display: inline-block; padding: 0 6px; border-radius: 999px; font-size: var(--t-xs); font-weight: 700; line-height: 1.5; white-space: nowrap; }
.rv-pill-flag { border: 1px solid var(--ink-dim); background: var(--panel-2); color: var(--ink); }
.rv-pill-claim { border: 1px solid var(--blocker, #b3261e); background: var(--blocker-bg, #fdecea); color: var(--blocker, #b3261e); }
@media (max-width: 640px) { .rv-key { grid-template-columns: 1fr; gap: 4px; } }
.rv-swatch { font-size: var(--t-xs); padding: 0 3px; border-radius: 2px; }
.rv-key-ins .rv-swatch { text-decoration: underline; text-decoration-color: #1f7a45; background: #e6f4ea; color: var(--ink); }
.rv-key-kw .rv-swatch { background: var(--kw-add-bg); color: var(--kw-add-ink); border-bottom: 2px dotted var(--kw-add-edge); border-radius: 2px 2px 0 0; }
.rv-key-have .rv-swatch { background: var(--kw-have-bg); color: var(--kw-have-ink); box-shadow: inset 0 0 0 1.5px var(--kw-have-edge); border-radius: 3px; }
.rv-key-del .rv-swatch { text-decoration: line-through; color: #b3261e; }
.rv-key-pend .rv-swatch { text-decoration: underline dashed var(--accent); background: var(--accent-soft); color: var(--accent-strong); }
/* The navigator, in the rail's column with the cards' own 12px inset (design review 2026-10-26:
   it read like a form field): row 1 one joined control [Previous]["Change 3 of 9 · 6 left"][Next],
   its middle with no edges of its own; row 2 Done reviewing across the rail's width. */
/* One row (owner, 2026-10-26: "the left and right selector and the done in the same row", Done
   "clear it's a button"): the stepper, then Done reviewing as an ordinary secondary button. The row
   keeps the rail's right edge and may run left past the rail's start (unsafe end). */
.rv-head-nav { display: flex; align-items: center; gap: 8px; padding: 0 12px; width: max-content; max-width: none; justify-self: unsafe end; }
/* Editing has the same head (2026-10-26, owner: "Reviewing and Editing should always be in the
   same spot (far right) and keep the same header that Reviewing has", views/review-view.js
   editHead): the navigator's column is as wide as it needs (Download joins it), so the mode menu
   is still the last control 13px from the head's right edge, exactly where Reviewing has it. The
   editor's bar rides in a row under the title (its save status and the formatting tools), plain:
   no stickiness, box or rule of its own, since the head is the sticky part. */
.rv-head.rv-head-editing { grid-template-columns: minmax(0, 1fr) auto; }
.rv-head-tools.re { margin: 6px 0 0; min-width: 0; }
.rv-head .rv-head-tools .re-bar {
  position: static; z-index: auto; min-height: 0; padding: 0; border: 0; background: none; gap: 6px 12px;
}
.rv-head .rv-head-tools .doc-title { display: none; }
.rv-head .rv-head-nav .doc-download { flex: none; }
/* The editor and its margin park under the head: its height (--rv-head-h, watchReviewHead) is
   their sticky top, and the bar inside it takes no height of its own. */
#resume:has(> .rv-head-editing) .re { --re-sticky-top: calc(var(--sticky-h) + var(--rv-head-h)); --re-bar-h: 0px; }
#resume:has(> .rv-head-editing) .rail-margin .mc-card { scroll-margin-top: calc(var(--sticky-h) + var(--rv-head-h) + 12px); }
#resume:has(> .rv-head-editing) .review-editor .re-body { border-top: 1px solid var(--line); }
/* Editing's cards (editCard): the review rail's card, with a check and a cross at the end of its
   head line, Google Docs style. 32px icon buttons, 44px on a touch screen. */
.rv-edit-head { flex-wrap: nowrap; align-items: flex-start; }
.rv-edit-head > .card-title { flex: 1 1 auto; min-width: 0; }
.rv-edit-head > .tag { flex: none; }
.rv-decide { display: inline-flex; flex: none; gap: 4px; margin: -4px -4px 0 auto; }
.view .rv-decide button { margin: 0; }
.view .rv-decide button.rv-decide-yes { color: var(--accent); }
.view .rv-decide button.rv-decide-no { color: var(--ink-dim); }
.view .rv-decide button.rv-decide-yes:hover:not(:disabled) { background: var(--accent-soft); color: var(--accent-strong); }
.view .rv-decide button.rv-decide-no:hover:not(:disabled) { background: var(--panel-2); color: var(--ink); }
@media (pointer: coarse) { .view .rv-decide button { min-width: 44px; min-height: 44px; } }
.rv-edit-card .cd-line { margin: 4px 0 0; }
.rv-edit-card .cd-line ins.cd-ins { color: #14532d; background: #e6f4ec; text-decoration-color: #1f7a45; }
.rv-edit-card .cd-line del.cd-del { color: #b3261e; text-decoration-color: #b3261e; }
.rv-edit-card .rv-chat { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line); display: grid; gap: 6px; }
.rv-edit-card .rv-chat .rv-chat-title { margin: 0; font-size: var(--t-xs); font-weight: 600; }
.rv-edit-card .rv-chat .pp-note, .rv-edit-card .rv-chat .pp-cost { margin: 0; font-size: var(--t-xs); }
.rail-margin .mc-card:not(.is-active) > .rv-edit-card { cursor: pointer; }
/* The rail's own tools: Accept all and Reject all at its top, History at its foot. */
.rail-tools { margin: 0 0 4px; display: flex; flex-wrap: wrap; gap: 0 4px; }
.rail-foot { margin: 8px 16px 0; }
.view .rail-tools button.rv-link, .view .rail-foot button.rv-link, .view .rail-body > button.rv-link {
  min-height: 32px; margin: 0; padding: 4px 6px; font-size: var(--t-xs); font-weight: 500; text-decoration: underline; text-underline-offset: 2px;
}
@media (pointer: coarse) { .view .rail-tools button.rv-link, .view .rail-foot button.rv-link, .view .rail-body > button.rv-link { min-height: 44px; } }
.rv-stepper { flex: none; }
.rv-stepper {
  display: flex; align-items: stretch; min-height: 36px;
  border: 1px solid var(--line-strong); border-radius: var(--r-pill); background: var(--panel); overflow: hidden;
}
.rv-stepper:focus-within { border-color: var(--accent); }
.rv-step-pos {
  flex: 1; display: flex; align-items: center; justify-content: center; padding: 0 4px; min-width: 0;
  font-size: var(--t-xs); font-weight: 700; color: var(--ink);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.rv-step-sep { white-space: pre; }
.view .rv-stepper button.rv-arrow {
  min-width: 44px; min-height: 36px; height: auto; margin: 0; padding: 0 10px; border: 0; border-radius: 0;
  background: transparent; box-shadow: none; color: var(--accent); font-size: var(--t-lg); line-height: 1;
}
.view .rv-stepper button.rv-arrow:hover:not(:disabled) { background: var(--accent-soft); }
.view .rv-stepper button.rv-arrow:disabled { color: var(--ink-dim); opacity: 0.5; }
.view .rv-stepper button.rv-arrow:focus-visible { outline: 3px solid var(--focus); outline-offset: -3px; }
/* The one stepper inside a card (design system 2026-10-26: the keyword card, the part panel),
   32px like the other small buttons, 44px on a phone. */
.rv-stepper.sm { display: inline-flex; min-height: 32px; }
.view .rv-stepper.sm button.rv-arrow { min-width: 32px; min-height: 32px; padding: 0 8px; font-size: var(--t-md); }
.rv-stepper.sm .rv-step-pos { padding: 0 8px; font-weight: 600; color: var(--ink-dim); }
@media (max-width: 640px) { .view .rv-stepper.sm button.rv-arrow { min-width: 44px; min-height: 44px; } }
.rv-head .dm-mode { flex: none; }
.rv-count { margin: 0; font-variant-numeric: tabular-nums; font-size: var(--t-xs); color: var(--ink-dim); }
.rv-head .rv-last { margin: 0; }
@media (max-width: 640px) {
  .view .rv-head button.rv-help-btn, .view .letter-section-head button.rv-help-btn { width: 44px; height: 44px; min-width: 44px; min-height: 44px; }
  .view .rv-head .rv-stepper button.rv-arrow, .rv-head .dm-mode .dm-trigger { min-height: 44px; }
}
/* What this job asks for most, the first card in the rail (2026-10-26, views/job-themes.js
   asksRailCard): one compact row per ask, its status pill (themes.css .theme-mark), and a quiet
   Answer it link for an ask still open. It is no change of its own, so no pointer over it. */
.rv-rail .mc-card:has(> .rv-asks) { cursor: auto; }
.rv-rail .mc-card:has(> .rv-asks):hover { box-shadow: none; }
.rv-asks-title { margin: 0 0 2px; font-size: var(--t-xs); font-weight: 600; color: var(--ink); }
.rv-asks-note { margin: 0 0 6px; color: var(--ink-dim); font-size: var(--t-xs); }
/* Ready, it is one closed line (design review 2026-10-26): the heading and the summary with a
   chevron, opening to the list. */
details.rv-asks > summary {
  display: block; position: relative; padding: 2px 0 2px 18px; cursor: pointer; list-style: none;
  font-size: var(--t-xs); color: var(--ink-dim);
}
details.rv-asks > summary::-webkit-details-marker { display: none; }
details.rv-asks > summary::before {
  content: ""; position: absolute; left: 2px; top: 0.55em; width: 6px; height: 6px;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor; transform: rotate(-45deg);
  transition: transform var(--dur-fast) var(--ease-out);
}
details.rv-asks[open] > summary::before { transform: rotate(45deg); }
details.rv-asks > summary:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
details.rv-asks > summary .rv-asks-title { margin: 0; }
details.rv-asks[open] > summary { margin-bottom: 6px; }
@media (prefers-reduced-motion: reduce) { details.rv-asks > summary::before { transition: none; } }
@media (pointer: coarse) { details.rv-asks > summary { min-height: 44px; } }
.rv-asks-note.themes-failed p { margin: 0; }
.rv-asks-list { list-style: none; margin: 0; padding: 0; display: grid; }
.rv-ask { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 8px; padding: 6px 0; border-top: 1px solid var(--line); }
.rv-ask-name { flex: 1 1 140px; min-width: 0; color: var(--ink); overflow-wrap: anywhere; }
.view .rv-ask button.rv-asks-go {
  min-height: 32px; margin: 0 0 0 -6px; padding: 4px 6px; flex-basis: 100%; justify-content: flex-start; text-align: left;
  font-size: var(--t-xs); font-weight: 500; text-decoration: underline; text-underline-offset: 2px;
}
@media (pointer: coarse) { .view .rv-ask button.rv-asks-go { min-height: 44px; } }
.rv-cols {
  display: grid; grid-template-columns: minmax(0, 1fr) 320px; align-items: start;
  border: 1px solid var(--line); border-radius: var(--r-card); background: var(--desk);
}
.rv-cols .review-pages { margin: 0; min-width: 0; }
.rv-cols .resume-preview { border-radius: var(--r-card) 0 0 var(--r-card); max-width: none; }
/* B7 (2026-10-16, owner: "any way to make the resume bigger / wider"): the review pages fill the
   column beside the 320px rail instead of stopping at 8.5in; the sheet scales with it (cqw units). */
.rv-rail { position: relative; min-width: 0; padding: 24px 0; }
.rv-rail .mc-layer { font-size: var(--t-xs); }
/* The current card and line land just under the sticky head (design review 2026-10-26: after Next
   the card's title sat under it): --rv-head-h is the head's measured height, set by an
   rv-head-h-<px> class on <html> in 8px steps (views/review-view.js watchReviewHead). */
.rv-rail .mc-card { scroll-margin-top: calc(var(--sticky-h) + var(--rv-head-h) + 12px); }
/* In the review rail the open card keeps the column's edge (design review 2026-10-26: its 16px
   step out drew it left of every other card); its accent edge and shadow say which one it is.
   resume-editor.css loads later, so these out-rank its .mc-card.is-active rules. */
.rv-rail .mc-layer > .mc-card.is-active { transform: none; }
.rv-rail .mc-layer > .mc-card.is-leaving.is-active { transform: translateY(-6px); }
@starting-style { .rv-rail .mc-layer > .mc-card.mc-enter.is-active { transform: translateY(6px); } }
@media (prefers-reduced-motion: reduce) {
  .rv-rail .mc-layer > .mc-card.is-leaving.is-active { transform: none; }
  @starting-style { .rv-rail .mc-layer > .mc-card.mc-enter.is-active { transform: none; } }
}
:root { --rv-head-h: 112px; }
html.rv-head-h-48 { --rv-head-h: 48px; } html.rv-head-h-56 { --rv-head-h: 56px; } html.rv-head-h-64 { --rv-head-h: 64px; }
html.rv-head-h-72 { --rv-head-h: 72px; } html.rv-head-h-80 { --rv-head-h: 80px; } html.rv-head-h-88 { --rv-head-h: 88px; }
html.rv-head-h-96 { --rv-head-h: 96px; } html.rv-head-h-104 { --rv-head-h: 104px; } html.rv-head-h-112 { --rv-head-h: 112px; }
html.rv-head-h-120 { --rv-head-h: 120px; } html.rv-head-h-128 { --rv-head-h: 128px; } html.rv-head-h-136 { --rv-head-h: 136px; }
html.rv-head-h-144 { --rv-head-h: 144px; } html.rv-head-h-152 { --rv-head-h: 152px; } html.rv-head-h-160 { --rv-head-h: 160px; }
html.rv-head-h-168 { --rv-head-h: 168px; } html.rv-head-h-176 { --rv-head-h: 176px; } html.rv-head-h-184 { --rv-head-h: 184px; }
html.rv-head-h-192 { --rv-head-h: 192px; } html.rv-head-h-200 { --rv-head-h: 200px; } html.rv-head-h-208 { --rv-head-h: 208px; }
html.rv-head-h-216 { --rv-head-h: 216px; } html.rv-head-h-224 { --rv-head-h: 224px; } html.rv-head-h-232 { --rv-head-h: 232px; }
html.rv-head-h-240 { --rv-head-h: 240px; }
.rv-split .resume-preview :is(li, p, h1, h2, h3) { scroll-margin-top: calc(var(--sticky-h) + var(--rv-head-h) + 12px); scroll-margin-bottom: 24px; cursor: pointer; }
.rv-card { margin: 0; }
.rv-card.is-decided .card-why { display: none; }
.rv-card .rv-body { margin-top: 8px; display: grid; gap: 8px; }
/* The open card's choices (owner decision 2026-10-16): one filled, one outlined, the rest text
   buttons, all one size; then Edit this line and Skip as a quiet row of text links. */
.view .rv-card .flag-buttons { display: flex; flex-wrap: wrap; gap: 8px; }
.view .rv-card .flag-buttons button { margin: 0; white-space: normal; }
.view .rv-card .flag-buttons button.primary { font-weight: 600; }
.view .rv-card .flag-buttons button.quiet { padding-left: 6px; padding-right: 6px; }
.rv-card-links { margin-top: 6px; display: flex; flex-wrap: wrap; align-items: center; gap: 0 2px; }
.view .rv-card-links button.rv-link {
  min-height: 32px; margin: 0; padding: 4px 6px; font-size: var(--t-xs); font-weight: 500;
  text-decoration: underline; text-underline-offset: 2px; text-decoration-thickness: 1px;
}
.view .rv-card-links button.rv-link:first-child { margin-left: -6px; }
.rv-sep { color: var(--ink-dim); font-size: var(--t-xs); }
@media (pointer: coarse) { .view .rv-card-links button.rv-link { min-height: 44px; } }
/* A decision already made, as plain words (owner feedback 2026-10-16: no pill): Kept in green
   with its check, every other state muted. */
.decided-note { display: inline-flex; align-items: center; margin: 0; font-size: var(--t-xs); font-weight: 600; color: var(--ink-dim); }
.decided-note.is-ok { color: var(--ok); }
.decided-check { white-space: pre; }
.rv-rail .mc-card:not(.is-active) { cursor: pointer; }
.rv-rail .mc-card:not(.is-active):hover { box-shadow: 0 0 0 1px var(--line-strong); }
.rv-quote { margin: 4px 0 0; color: var(--ink); overflow-wrap: anywhere; }
/* The current line in the split is outlined in the open card's blue, not the yellow of the
   older views, so one colour says "this one" on both sides. */
.rv-split .resume-preview .is-jumped { outline-color: var(--accent); }
/* In the rail the change reads in the page's own colours: added green, taken out red. */
.rv-card .cd-line ins.cd-ins { color: #14532d; background: #e6f4ec; text-decoration-color: #1f7a45; }
.rv-card .cd-line del.cd-del { color: #b3261e; text-decoration-color: #b3261e; }

/* "How we know" (2026-10-19, spec 2026-10-19-resume-why-and-start-from-zero R3): one quiet link
   beside a run change's reason, and the evidence page it opens (views/how-we-know.js). */
.why-how { font-size: var(--t-xs); color: var(--accent); white-space: nowrap; }
.how-we-know .hwk-nav { margin: 0 0 8px; }
.how-we-know .hwk-lead { color: var(--ink-dim); margin: 0 0 24px; }
.how-we-know .hwk-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 16px; }
.how-we-know .hwk-item { border: 1px solid var(--line); border-radius: var(--r-card); background: var(--panel); padding: 16px; }
.how-we-know .hwk-item.is-cited { background: var(--accent-soft); border-color: var(--accent); }
.how-we-know .hwk-item p { margin: 0; }
.how-we-know .hwk-cited { margin-bottom: 6px; }
.how-we-know .hwk-says { color: var(--ink); }
.how-we-know .hwk-meta, .how-we-know .hwk-source { margin-top: 6px; font-size: var(--t-xs); color: var(--ink-dim); overflow-wrap: anywhere; }
/* Phone: the reason's link and the page's Back are 44px targets (the design review measured 17 to
   20px). The reason line's link sits after its text, so CSS cannot tell it from a link alone on
   its line; every one gets the target. */
@media (max-width: 767px) {
  .why-how, .how-we-know .hwk-back { display: inline-flex; min-height: 44px; align-items: center; }
}
/* The job posting fold (2026-10-19, views/job-posting.js): a borderless section like About the
   company, the posting at a readable width, and the keywords the tailored resume does not use
   yet marked with a dotted underline only (no fill: colour is for meaning). */
.view.job #posting { margin: 32px 0; padding: 0; background: transparent; border: 0; border-radius: 0; box-shadow: none; }
.view.job #posting > h2 { margin: 0 0 12px; font-size: var(--t-md); line-height: var(--lh-md); }
/* One section heading (design system audit 2026-10-26): the resume, the cover letter and the
   job posting each get an 18px h2 with the rule under it that the cover letter got in PR 447.
   The resume and the cover letter sit in the same .panel container (owner, 2026-10-26); the
   posting is a flat section. */
.view.job section#cover-letter > h2, .view.job section#posting > h2, .view.job section#resume .resume-head > h2 {
  margin: 0 0 24px; padding: 0 0 12px; border-bottom: 1px solid var(--line);
  font-size: var(--t-md); line-height: var(--lh-md); letter-spacing: 0; }
/* The resume's head is a grid whose lead and count lines belong to the header: its gap spaces them. */
.view.job section#resume .resume-head > h2 { margin-bottom: 6px; }
/* The job page's small folds (Mark as applied, How the Fit Score is built, Want a second pass?,
   the posting) are ui.js fold(): a quiet accent line with no grey hover fill (design system audit
   2026-10-26); 44px under 640px comes from app.css. */
.view.job details.fold.fold-inline > summary:hover { background: transparent; }
/* Mark as applied in the status row: its date form opens BELOW the row, over what follows, so the
   pill and the trigger never move. */
.view.job .job-status { position: relative; }
.view.job .job-status-mark[open] { flex: none; }
.view.job .job-status-mark > summary { padding: 6px 0; font-size: var(--t-sm); }
/* Mark as applied keeps the status row's icon plus words (owner, 2026-10-06), so its check mark
   stands in for the fold chevron rather than sitting beside it. */
.view.job details.fold.job-status-mark > summary::before { display: none; }
.view.job .job-status-mark > .flow-submit { position: absolute; left: 0; top: calc(100% + 8px); z-index: 5; margin: 0;
  padding: 12px 16px; background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-card); box-shadow: var(--shadow-pop); }
@media (max-width: 640px) { .view.job .job-status-mark > .flow-submit { right: 0; } }
/* A to-do row that folds (claims): the row's number, label and tag as its summary, in ink. */
.view.job details.fold.todo-fold { border-top: 0; padding: 0; }
.view.job details.fold.todo-fold > summary { margin: 0; padding: 0; font-size: inherit; color: var(--ink); align-items: center; }
.view.job details.fold.todo-fold > summary:hover { background: transparent; }
/* Tags stay on the row they describe at every width: the label shrinks and wraps, the tag does
   not move to a line of its own. */
.view.job .todo-line, .view.job .todo-fold > summary { flex-wrap: nowrap; }
.view.job .todo-label { flex: 1 1 auto; min-width: 0; }
/* A phone gives the label its own line; the tag and Show them wrap under it (browser walk
   2026-10-26: at 390 the label was squeezed to 0px and printed one letter per line). */
@media (max-width: 640px) {
  .view.job .todo-line, .view.job .todo-fold > summary { flex-wrap: wrap; }
  /* The number stays beside the label; only the tag and Show them wrap below. */
  .view.job .todo-label { flex: 1 1 calc(100% - 48px); }
  .gp-caption { white-space: normal; max-width: 8rem; text-align: center; }
}
.view.job .todo-line > .tag, .view.job .todo-fold > summary > .tag, .view.job .todo-line > button { flex: none; }
.view.job #before-apply .ba-card .ba-head { flex-wrap: nowrap; }
.view.job #before-apply .ba-card .ba-head b { min-width: 0; overflow-wrap: anywhere; }
.view.job #before-apply .ba-card .ba-verdict.tag { flex: none; margin-left: auto; }
/* The run again's cost, under its button (requestCostText). */
.view.job .rerun-cost { margin: 0; }
.view.job #posting details.posting-fold { border-top: 0; }
.view.job #posting details.posting-fold > summary { color: var(--accent); font-weight: 500; }
.view.job #posting .posting-fold > .hint { margin: 10px 0 0; max-width: 85ch; }
.view.job #posting .posting-read { max-width: 85ch; margin-top: 10px; color: var(--ink); overflow-wrap: anywhere; }
.view.job #posting .posting-read p { margin: 0 0 10px; line-height: 1.55; }
.post-kw-missing { background: transparent; color: inherit; text-decoration: underline dotted currentColor; text-decoration-thickness: 2px; text-underline-offset: 4px; }
@media (max-width: 767px) {
  .view.job #posting details.posting-fold > summary { min-height: 44px; box-sizing: border-box; align-items: center; }
}
@media (max-width: 640px) {
  .view.job #posting { margin: 28px 0; }
}
/* Send to a friend for review (2026-10-19, views/send-friend.js): a small dialog like the AI
   notice, its three copies as secondary buttons in one column, the tip muted, Close quiet. */
dialog.send-friend {
  max-width: 30rem; background: var(--panel); color: var(--ink); border: 1px solid var(--line);
  border-radius: var(--r-card); padding: 20px 22px; box-shadow: var(--shadow-pop);
}
dialog.send-friend::backdrop { background: rgba(33, 28, 22, 0.4); }
dialog.send-friend h2 { margin-top: 0; }
.send-friend-choices { display: flex; flex-direction: column; align-items: stretch; gap: 8px; margin: 16px 0; }
.send-friend-choices button { margin: 0; text-align: left; }
.send-friend-tip { color: var(--ink-dim); font-size: var(--t-xs); margin: 0 0 12px; }
dialog.send-friend .actions { display: flex; justify-content: flex-end; }

/* ---- Posting keywords in the next-step card (2026-10-20, views/job-keywords.js keywordsLine): one
   line, its count and a quiet "Go through the N missing" text button; 44px on a phone. */
.next-step .next-keywords { margin: 12px 0 0; color: var(--ink); font-size: var(--t-sm); }
.view .next-step button.next-keywords-go { min-height: 32px; margin: 0; padding: 2px 4px; font-size: var(--t-sm); text-decoration: underline; }
@media (max-width: 767px) {
  .view .next-step button.next-keywords-go { min-height: 44px; }
}
/* The keyword card in the review (views/job-walk.js keywordsBody), one term at a time (owner,
   2026-10-20: "expected ONE card you click through"): "Keyword 2 of 6" with Previous and Next,
   the term, its question and choices; the answered ones in a closed Done fold, ruled apart; the
   soft skills in one quiet line. Fits the 320px rail and the phone bar. */
.kwc-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-width: 0; }
.kwc-pos { margin: 0; font-size: var(--t-xs); color: var(--ink-dim); font-variant-numeric: tabular-nums; }
.kwc-row { display: grid; gap: 4px; min-width: 0; overflow-wrap: anywhere; }
.kwc-row p { margin: 0; }
.kwc-row .kwc-term { font-weight: 600; color: var(--ink); }
.kwc-row .kwc-says { color: var(--ink-dim); font-size: var(--t-xs); }
.kwc-row .flag-buttons { margin: 0; }
.kwc-rows { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 8px; min-width: 0; }
.kwc-rows .kwc-row { padding-top: 8px; border-top: 1px solid var(--line); }
.kwc-rows .kwc-row:first-child { padding-top: 0; border-top: 0; }
.kwc-done-list { margin: 4px 0 0; font-size: var(--t-xs); }
.kwc-say { display: grid; gap: 6px; }
.kwc-say .field { margin: 0; }
.kwc-say .field input { width: 100%; box-sizing: border-box; min-height: 44px; }
/* The refusal reads at the card's own 13px, never louder than its question (design review 2026-10-20). */
.kwc-say .field-error { margin: 0; font-size: var(--t-xs); font-weight: 400; }
.kwc-more, .kwc-soft { margin: 0; font-size: var(--t-xs); }
/* The grade card names itself (2026-10-21): "Resume grade" over the letters, full width. */
.view.job .grade-summary .grade-eyebrow { flex: 1 0 100%; margin: 0; }
/* What the Fit Score is about, beside it (2026-10-21). */
.view.job .job-fit-means { flex: 0 1 auto; color: var(--ink-dim); }
/* How the Fit Score is built follows the line it explains (owner, 2026-10-21: it "weirdly shows
   to the right side"); open, it takes its own row under the line. */
.view.job .job-fit-fold[open] { flex-basis: 100%; }
/* Why the review did not open (2026-10-21), shown under the resume header's count once. */
.view.job .review-refused { margin: 8px 0 0; padding-left: 10px; border-left: 3px solid var(--accent); color: var(--ink); }
/* Design review 2026-10-21: the grade sentence at a reading width, the Fit value readable, the
   phone-sized targets for the plan rows and the folds. */
.view.job .grade-summary-text { max-width: 60ch; }
.view.job .job-fit-score { font-size: var(--t-sm); }
@media (max-width: 640px) {
  .view.job #before-apply button.ba-more, .view.job .job-ratings button.ratings-toggle { min-height: 44px; }
  #cover-letter .letter-plan-list label { min-height: 44px; display: flex; align-items: center; }
}
/* The grade row with How it's graded open (2026-10-21): the letters and the sentence stay at the
   top instead of centring against the tall fold; the held or pending words stay on one line, so
   their box fits the words and the caption centres under it. */
.view.job .grade-summary { align-items: flex-start; }
.view.job .grade-progress .gp-pending, .view.job .grade-progress .gp-held { max-width: none; white-space: nowrap; }

/* Loading states (2026-10-21). Add a job's link step while the posting is read, and the search
   on the company's own site (views/addjob.js): the button spins and says "Reading the
   posting...", the field locks, and a line under the form says what is happening over a slim bar
   that runs back and forth (a transform only). The universal reduced-motion rule above stops the
   spinner and the bar; the words still say it is working.
   contrast-pairs: --ink on --bg; --on-accent on --accent */
.wait-spinner {
  display: inline-block; flex: none; width: 18px; height: 18px; box-sizing: border-box; border-radius: 50%;
  border: 2px solid var(--accent-soft); border-top-color: var(--accent);
  animation: run-spin 0.9s linear infinite;
}
.wait-spinner.in-button { width: 16px; height: 16px; border-color: currentColor; border-top-color: transparent; opacity: 0.9; }
button.is-working { display: inline-flex; align-items: center; gap: 8px; cursor: progress; }
.view button.primary.is-working:disabled { opacity: 1; }
form[aria-busy="true"] input[readonly] { background: var(--panel-2); cursor: progress; }
.wait-status { margin: 4px 0 16px; max-width: 40rem; }
.wait-status p { margin: 0 0 10px; color: var(--ink); }
.wait-line { display: flex; align-items: center; gap: 10px; }
.wait-line p { flex: 1 1 auto; min-width: 0; margin: 0; }
.wait-line + .wait-bar { margin-top: 12px; }
.wait-bar { position: relative; display: block; height: 4px; overflow: hidden; border-radius: 999px; background: var(--accent-soft); }
.wait-bar-fill {
  position: absolute; top: 0; left: 0; width: 40%; height: 100%; border-radius: inherit;
  background: var(--accent); transform: translateX(-100%); animation: run-sheen 1.4s ease-in-out infinite;
}
