/* 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: rgba(255, 255, 255, 0.1); }
.top nav a[aria-current="page"] { background: rgba(255, 255, 255, 0.24); 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: 999px;
  border: 1px solid rgba(255, 255, 255, 0.35); 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 rgba(255, 255, 255, 0.55); 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: rgba(255, 255, 255, 0.14); 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: 999px; background: transparent; color: var(--on-bar); box-shadow: none;
}
.top button.icon-btn:not(:disabled):hover, .top button.icon-btn[aria-expanded="true"] { background: rgba(255, 255, 255, 0.16); }
/* 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: 13px; 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 sits on the column's edge, like the text around it. The
   import picker's Paste the text instead follows the drop zone, so it is matched as a child. */
:is(.actions, .import-choose, .import-paste, .unlock-foot) > button.quiet:first-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. */
:is(.actions, .next-actions, .import-actions) + .hint { margin-top: 8px; }
/* 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 summary { color: var(--ink-dim); cursor: pointer; }
.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; }
}
fieldset, .view fieldset { border: 1px solid var(--line); border-radius: var(--r-control); padding: 8px 16px; margin: 16px 0; }
.view legend { font-weight: 700; padding: 0 4px; }
/* 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: 30px; margin: 0; padding: 3px 12px; border-radius: 999px; 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); }
/* A pressed toggle (Show changes, Show keywords, Edit, the rail's Changes and Chat) reads as on
   without the solid accent fill: the page keeps exactly one filled button, the next-step card's
   (job page flow, 2026-10-05). The job list's bucket chips keep their fill. */
.view button.chip[aria-pressed="true"] { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); font-weight: 600; }
.view .chips button.chip[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.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 .gp-pending { max-width: 9rem; padding: 1px 6px; }
.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); }
/* Phone: the stats share the width in three equal columns. */
@media (max-width: 639px) {
  .job-card { padding: 16px; }
  .job-card .card-stats { grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: 12px; }
}
/* 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; }

/* Verdict pills: solid, white, uppercase, so a verdict reads by shape and weight too. */
.pill {
  display: inline-block; padding: 2px 9px; border-radius: 999px; border: 1px solid transparent;
  font-size: var(--t-eyebrow); font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; line-height: 1.5; white-space: nowrap;
}
.pill-ok, .pill-covered { background: var(--ok); color: var(--on-band); }
.pill-risk, .pill-stretch { background: var(--risk); color: var(--on-band); }
.pill-blocker, .pill-gap { background: var(--blocker); color: var(--on-band); }
.pill-unknown { background: var(--unknown-bg); color: var(--unknown); border-color: var(--line); }
/* 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; }
/* Recommendation tags: bordered, tinted, in words. */
.tag {
  display: inline-block; padding: 0 7px; border: 1px solid var(--ink-faint); border-radius: 999px;
  font-size: var(--t-eyebrow); font-weight: 600; letter-spacing: 0.08em; line-height: 1.5; color: var(--ink-dim); white-space: nowrap;
}
.tag-auto { border-color: var(--ok); background: var(--ok-bg); color: var(--ok); }
.tag-approve { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
.tag-manual { border-color: var(--manual); background: var(--manual-bg); color: var(--manual-ink); }
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: no box, a rule above, a CSS chevron in place of the native marker. */
details.fold { border-top: 1px solid var(--line); padding: 2px 0; margin: 0; }
details.fold > summary {
  cursor: pointer; font-weight: 600; 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 { display: none; }
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: 2px solid var(--accent); 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-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; }
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: 6px 0 0; padding: 4px 10px; border-radius: 999px; background: var(--panel-2); font-size: var(--t-sm); white-space: nowrap; 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-fold details.fold { border-top: 0; }
.code-fold details.fold > summary { color: var(--accent); font-size: var(--t-sm); }
.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); }
.done-pill { display: inline-block; margin: 0 0 8px; padding: 2px 10px; border-radius: 999px;
  font-size: var(--t-eyebrow); font-weight: 500; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--ink-dim); background: var(--panel-2); }
.done-card.is-ok .done-pill { color: var(--ok); background: var(--ok-bg); }
.done-card.is-danger .done-pill { color: var(--danger-strong); background: var(--danger-soft); }
/* 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. */
.posting-body { max-height: 22rem; overflow: auto; margin: 0 0 16px; padding: 14px 16px; background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--r-control); box-shadow: none; }
.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 paste step's choice: two equal segments (js/views/ui.js segmented), each a label around a
   visually hidden radio, so the segment is relative to keep that radio inside it. 44px targets;
   the focus ring is drawn on the segment whose radio has keyboard focus. */
.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: grid; grid-template-columns: 1fr 1fr; gap: 4px; padding: 3px; border: 1px solid var(--accent); border-radius: var(--r-card); background: var(--panel); }
.segment { position: relative; display: flex; align-items: center; justify-content: center; min-height: 44px; padding: 8px 12px; border-radius: var(--r-control); text-align: center; font-weight: 600; color: var(--accent); cursor: pointer; overflow-wrap: anywhere; }
.segment:hover { background: var(--accent-soft); }
.segment.is-selected, .segment:has(input:checked) { background: var(--accent); color: var(--on-accent); }
.segment:has(input:focus-visible) { outline: 3px solid var(--focus); outline-offset: 2px; }
/* 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 .segments { display: inline-grid; grid-template-columns: repeat(2, minmax(0, auto)); max-width: 100%; }
.add-job .segment { font-size: var(--t-sm); padding: 6px 14px; }
.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 .page-grab-how { margin: 0 0 8px; font-size: var(--t-sm); color: var(--ink-dim); }
.add-alt .page-grab-status:empty { display: none; }
.add-alt > button.quiet { margin: 4px 0 0; padding-left: 0; padding-right: 0; }
/* 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. */
.add-head { display: flex; align-items: flex-start; gap: 12px; margin: 4px 0 16px; padding: 14px 16px; border: 1px solid var(--line); border-radius: var(--r-control); background: var(--panel); }
.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%); } }
.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; }
.menu-wrap > button { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; margin: 0; }
.menu-caret { font-size: var(--t-xs); 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);
}
.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; }
.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. */
.doc-start:has(> .doc-title) { 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); }
.view .resume-head button.resume-review { min-height: 44px; margin: 0; padding: 0 18px; border: 1px solid var(--accent-strong); border-radius: 999px;
  background: var(--panel); color: var(--accent-strong); font-weight: 600; box-shadow: none; }
.view .resume-head button.resume-review:hover { background: var(--accent-soft); }
.view .resume-head button.resume-review:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: 2px; }
/* 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; }
.dm.doc-suggestions .dm-trigger { min-height: 36px; padding: 0 12px 0 16px; border: 1px solid var(--line-strong); border-radius: 999px; }
.doc-suggestions .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 { min-height: 36px; padding: 0 12px 0 16px; border: 1px solid var(--line-strong); border-radius: 999px; }
/* 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; }
/* Why a card matters, one plain sentence (core/why.mjs), and its three ways out. */
.rl-why { color: var(--ink); }
.rl-fix { display: grid; gap: 6px; margin-top: 6px; }
.rl-fix .field { margin: 0; }
/* The compact card's head: its kind, and a short reason at the right. */
.rl-card .rl-card-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 2px 8px; }
.rl-card-kind { font-weight: 600; color: var(--ink); }
.rl-card-reason { color: var(--ink-dim); font-size: var(--t-xs); overflow-wrap: anywhere; }
.rl-card-label { color: var(--ink-dim); font-size: var(--t-xs); }
/* Edit on a card: a quiet blue word, not one more pill. */
.view button.rl-edit-link { min-height: 28px; margin: 0; padding: 3px 4px; border: 0; background: none; box-shadow: none;
  color: var(--accent-strong); font-weight: 600; text-decoration: underline; text-underline-offset: 2px; text-decoration-thickness: 1px; }
.view button.rl-edit-link:hover { background: var(--accent-soft); }
.review-phone .rail button.rl-edit-link { min-height: 44px; padding: 3px 10px; }
/* 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; }
.view .ask-starters button.chip { margin: 0; min-height: 28px; padding: 3px 10px; font-size: var(--t-xs); }
.review-phone .ask-starters button.chip { min-height: 44px; }
.ask-foot { display: flex; flex-direction: column; gap: 6px; }
.ask-foot .ask-note { margin: 0; }
.ask-foot button { margin: 0; align-self: flex-end; }
.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; }
.view .ask-box button.icon-btn { display: inline-grid; place-items: center; min-height: 32px; min-width: 32px; margin: 0; padding: 4px;
  border: 0; border-radius: 999px; background: transparent; color: var(--ink-dim); box-shadow: none; }
.view .ask-box button.icon-btn:not(:disabled):hover { background: var(--panel-2); color: var(--ink); }
.ask-box button.icon-btn svg { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
.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; }
.review-bar { position: sticky; bottom: 0; z-index: 30; 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-suggested { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); border-style: dashed; }
.tag-run { border-color: var(--ok); background: var(--ok-bg); color: var(--ok); }
.tag-untraceable { border-color: var(--manual); background: var(--manual-bg); color: var(--manual-ink); }
.tag-dropped { border-color: var(--blocker); background: var(--blocker-bg); color: var(--blocker); }
.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; }
.tag-block { border-color: var(--blocker); background: var(--blocker-bg); color: var(--blocker); }
.tag-check { border-color: var(--risk); background: var(--risk-bg); color: var(--risk-ink); }
.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 .tag-wording, .tag-wording { border: 1px dotted #b26a00; background: #fff6e8; color: #8a5200; }
.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); }
/* 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; font-weight: 600; font-size: var(--t-xs); color: var(--ink-dim); }
.pp-head .pp-pos-head { font-size: var(--t-xs); color: var(--ink-dim); }
.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-nav .pp-pos { font-size: var(--t-xs); color: var(--ink-dim); }
.pp-nav > button:last-child { margin-left: auto; }
.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; }
.walk-scope .segments { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; padding: 0; border: 0; border-radius: 0; background: transparent; }
.walk-scope .segment { min-height: 36px; padding: 6px 14px; border: 1px solid var(--line-strong); border-radius: var(--r-pill); background: var(--panel);
  color: var(--accent); font-size: var(--t-xs); font-weight: 600; line-height: 1.25;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px; }
.walk-scope .segment:hover { background: var(--accent-soft); }
.walk-scope .segment .seg-check { display: none; width: 14px; height: 14px; stroke-width: 2.4; }
.walk-scope .segment.is-selected, .walk-scope .segment:has(input:checked) { background: var(--accent-soft); border-color: var(--accent); color: var(--accent-strong); }
.walk-scope .segment.is-selected .seg-check, .walk-scope .segment:has(input:checked) .seg-check { display: inline-block; }
@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. */
.view.job #before-apply, .view.job #cover-letter { margin: 32px 0; padding: 0; background: transparent; border: 0; border-radius: 0; box-shadow: none; }
.view.job #before-apply > h2, .view.job #cover-letter > 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-verdict { font-size: var(--t-xs); color: var(--ink-dim); }
.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-verdict { margin-left: auto; padding: 1px 10px; border-radius: var(--r-pill); background: var(--unknown-bg); color: var(--unknown); font-weight: 500; white-space: nowrap; }
.view.job #before-apply .ba-card .ba-verdict.is-risk { background: var(--risk-bg); color: var(--risk-ink); }
.view.job #before-apply .ba-card .ba-verdict.is-blocker { background: var(--blocker-bg); color: var(--blocker); }
.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, .view.job #cover-letter { 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-meta { margin: 4px 0 0; font-size: var(--t-xs); overflow-wrap: anywhere; }
.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 > summary { min-height: 44px; box-sizing: border-box; padding: 11px 0; cursor: pointer; }
.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-why { margin: 0; }
.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; }
.cd-why { margin: 0; color: var(--ink-dim); font-size: var(--t-xs); }
.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. */
.rv-split { margin-top: 8px; }
/* 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. */
.rv-head {
  position: sticky; top: var(--sticky-h); z-index: 8; display: flex; flex-wrap: wrap; align-items: center;
  justify-content: space-between; gap: 8px 16px; padding: 10px 12px; margin-bottom: 0;
  /* No edge of its own (design audit 2026-10-21: a box inside the section's box); the panel fill
     stays only so the pinned head covers the pages scrolling under it. */
  background: var(--panel);
}
.rv-head-info { display: grid; gap: 2px; min-width: 0; }
/* The head's title and place (2026-10-20): the title, "Change 3 of 9 · 6 left" under it, the last
   choice under that, and What the colours mean as one quiet closed disclosure. */
.rv-head h2.rv-title { margin: 0; font-size: var(--t-md); line-height: var(--lh-md); }
.rv-colours { font-size: var(--t-xs); color: var(--ink-dim); }
.rv-colours > summary { cursor: pointer; width: max-content; max-width: 100%; }
.rv-colours[open] > .rv-keys { margin-top: 4px; }
/* Two columns across the head's width, and the head stops sticking while the key is open, so an
   open key never pins half the screen over the pages (design review, 2026-10-21). */
.rv-head:has(.rv-colours[open]) { position: static; }
.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); }
.rv-head-nav { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.rv-count { margin: 0; font-variant-numeric: tabular-nums; font-size: var(--t-xs); color: var(--ink-dim); }
.view .rv-head button.rv-arrow { min-width: 36px; min-height: 36px; height: 36px; margin: 0; padding: 0 8px; font-size: var(--t-lg); line-height: 1; }
.rv-head .rv-last { margin: 0; }
.view .rv-head button.rv-kw-toggle { min-height: 36px; margin: 0; padding: 4px 12px; font-size: var(--t-xs); }
.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); }
.rv-split .resume-preview :is(li, p, h1, h2, h3) { scroll-margin-top: calc(var(--sticky-h) + 120px); scroll-margin-bottom: 24px; cursor: pointer; }
.rv-card { margin: 0; }
.rv-card-head { margin: 0; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.rv-kind { font-weight: 600; color: var(--ink); }
.rv-card .rv-why { margin: 4px 0 0; color: var(--ink-dim); }
.rv-card.is-decided .rv-why { display: none; }
.rv-card.is-active .rv-why { color: var(--ink); }
.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 { min-height: 36px; margin: 0; padding: 6px 14px; font-size: var(--t-xs); 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); }
.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-nav { display: inline-flex; gap: 2px; }
.view button.kwc-arrow { min-width: 32px; min-height: 32px; margin: 0; padding: 0 6px; font-size: var(--t-md); line-height: 1; }
.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); }
@media (max-width: 767px) {
  .view button.kwc-arrow { min-width: 44px; min-height: 44px; }
}
/* 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
   folded second pass a quiet summary, 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); }
.second-pass.is-folded > summary { cursor: pointer; min-height: 32px; }
@media (max-width: 640px) {
  .second-pass.is-folded > summary, .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;
}
