/*
  Resume Tailor — tool chrome ("Spread" direction).

  Independent from the resume PDF's own stylesheet (print_resume.css) and
  hand-authored from scratch — no Tailwind, no build step, no shared classes
  with the PDF template. See REDESIGN plan for the full rationale.

  Signature idea: the app is shaped like an open two-page spread from step
  one. The tailored/final side is the lit page (bright white); anything
  provisional or original sits on a recessed warm grey. Colour is spent in
  exactly one place — changed text, the active step, focus — not sprayed
  across the chrome.

  Palette/type/radius tokens below are ported from jobrhyme's brand seed
  (bronze/amber, hue 38 / chroma 0.16 / lightness 0.55, radius 0.5rem, Inter) —
  same oklch() math, literal values instead of jobrhyme's live calc() ramp
  since this is a single fixed (light-only) theme, not a seed to re-derive.
  `--added`/`--added-wash` (diff "addition" green) and the danger/added
  border+text companions below have no jobrhyme equivalent (it has no diff
  view) — picked to read as warm-neutral against the bronze accent, not
  literally ported. `--font-read` (Newsreader) and `--font-mono` (JetBrains
  Mono) are also kept rather than flattened to Inter: they're content-type
  choices (serif for resume prose, mono for dates/meta) jobrhyme never had to
  make, not brand identity.
*/

/* ---------- Tokens ---------- */
:root {
  --page-recto: oklch(1 0.002 38);      /* the lit page: tailored content, primary surfaces */
  --page-verso: oklch(0.96 0.006 38);   /* the recessed page: original content, secondary surfaces */
  --ink: oklch(0.18 0.01 38);
  --dim: oklch(0.5 0.02 38);
  --line: oklch(0.9 0.008 38);
  --accent: oklch(0.47 0.16 38);        /* jobrhyme brand-600 */
  --accent-hover: oklch(0.39 0.144 38); /* jobrhyme brand-700 */
  /* Wash tones below are hand-softened, not jobrhyme's literal brand-100/200
     (chroma 0.064/0.096) — at this hue (~38, orange/amber) that chroma reads
     as a bold salmon at large-panel size (.notes, .message-*), noticeably
     more saturated than the pale indigo wash it replaces. Chroma dialed down
     until sampled rgb() spread matched the original wash/border pairs'
     spread; --accent itself and small-badge uses stay at jobrhyme's literal
     values. */
  --accent-wash: oklch(0.96 0.02 38);
  --accent-wash-line: oklch(0.89 0.04 38);
  --accent-wash-ink: oklch(0.32 0.1 38);
  --danger: oklch(0.577 0.245 27.325);  /* jobrhyme's own --destructive */
  --danger-wash: oklch(0.96 0.018 27.325);
  --danger-wash-line: oklch(0.88 0.045 27.325);
  --danger-wash-ink: oklch(0.35 0.14 27.325);
  --added: oklch(0.5 0.13 155);         /* not a jobrhyme token — see file header */
  --added-wash: oklch(0.95 0.02 155);
  --added-wash-line: oklch(0.86 0.06 155);
  --added-wash-ink: oklch(0.32 0.09 155);

  --font-ui: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-read: "Newsreader", Georgia, serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SFMono-Regular", Consolas, monospace;

  --radius: 0.5rem;
  --radius-sm: 0.375rem;
  --shadow-card: 0 1px 2px oklch(0.2 0.03 38 / 0.06), 0 8px 24px -12px oklch(0.2 0.04 38 / 0.14);
  --content-width: 46rem;
  --content-width-wide: 76rem;
}

@media (prefers-color-scheme: dark) {
  /* Single-user internal tool, always used in daylight-adjacent contexts
     (reading resume text) — deliberately no dark theme. Explicit no-op
     block so it reads as a decision, not an oversight. */
}

/* ---------- Reset & base ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--page-verso);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 15.5px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3, h4 { margin: 0; font-weight: 600; line-height: 1.25; }
p { margin: 0 0 0.75em; }
p:last-child { margin-bottom: 0; }
a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 0.15em; }
a:hover { text-decoration-thickness: 2px; }
ul, ol { margin: 0; padding: 0; list-style: none; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

.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;
}

/* ---------- Shell ---------- */
.site-nav {
  background: var(--page-recto);
  border-bottom: 1px solid var(--line);
}
.site-nav-inner {
  max-width: var(--content-width-wide);
  margin: 0 auto;
  padding: 0.9rem 1.5rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  position: relative; /* anchors .nav-links's dropdown positioning below */
}
.site-brand {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--ink);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}
.beta-badge {
  font-family: var(--font-ui);
  font-size: 0.65rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--accent);
  background: var(--accent-wash);
  border: 1px solid var(--accent-wash-line);
  border-radius: 999px;
  padding: 0.12rem 0.5rem;
}
.nav-links { display: flex; align-items: center; gap: 1rem; }

/* Hamburger button — hidden by default, shown only under the breakpoint
   below where .nav-links itself switches from an inline row to a
   dropdown. Three-line icon drawn with the button's own border-box
   (a middle bar plus a ::before/::after pair) rather than an inline SVG —
   nothing else in this app's chrome uses icons, so one three-line CSS
   shape is simpler than adding an icon dependency for a single glyph. */
.nav-menu-toggle {
  display: none;
  background: none;
  border: none;
  padding: 0.5rem;
  margin: -0.5rem 0 -0.5rem -0.5rem;
  cursor: pointer;
}
.nav-menu-icon {
  position: relative;
  display: block;
  width: 1.15rem;
  height: 2px;
  background: var(--ink);
  border-radius: 1px;
}
.nav-menu-icon::before, .nav-menu-icon::after {
  content: "";
  position: absolute;
  left: 0;
  width: 100%;
  height: 2px;
  background: var(--ink);
  border-radius: 1px;
}
.nav-menu-icon::before { top: -6px; }
.nav-menu-icon::after { top: 6px; }

@media (max-width: 640px) {
  .nav-menu-toggle { display: inline-flex; align-items: center; justify-content: center; order: 1; }
  .nav-links {
    display: none;
    position: absolute;
    top: calc(100% + 0.5rem);
    right: 0;
    z-index: 20;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    min-width: 10rem;
    background: var(--page-recto);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow-card);
    padding: 0.4rem;
  }
  .nav-links.is-open { display: flex; }
  .nav-links a, .nav-links .nav-logout-form, .nav-links button.nav-logout {
    width: 100%;
    text-align: left;
    padding: 0.6rem 0.65rem;
    border-radius: var(--radius-sm);
  }
  .nav-links a:hover, .nav-links button.nav-logout:hover { background: var(--page-verso); color: var(--accent); }
}
.nav-logout {
  font-size: 0.82rem;
  color: var(--dim);
  text-decoration: none;
}
.nav-logout:hover { color: var(--accent); }
.nav-profile-link { display: inline-flex; align-items: center; gap: 0.35rem; }
.nav-profile-icon { width: 1.05em; height: 1.05em; flex-shrink: 0; }
/* "Log out" is a form button now (Django's LogoutView needs POST), not a
   plain <a> — reset button chrome so it still reads as the same plain-text
   link the "Log in" <a> next to it is. */
.nav-logout-form { display: inline-flex; }
button.nav-logout {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  cursor: pointer;
}

.page-main {
  max-width: var(--content-width);
  margin: 0 auto;
  padding: 2.25rem 1.5rem 4rem;
}
.page-main.wide { max-width: var(--content-width-wide); }

.pending-approval-banner {
  background: var(--accent-wash);
  border-bottom: 1px solid var(--accent-wash-line);
}
.pending-approval-banner-inner {
  max-width: var(--content-width-wide);
  margin: 0 auto;
  padding: 0.6rem 1.5rem;
  font-size: 0.85rem;
  color: var(--accent-wash-ink);
  text-align: center;
}

.page-eyebrow {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 0.5rem;
}
.page-title {
  font-family: var(--font-ui);
  font-size: 1.85rem;
  font-weight: 650;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.page-lede {
  font-size: 1rem;
  color: var(--dim);
  max-width: 38rem;
  margin-top: 0.6rem;
}
.page-section-heading {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--dim);
  margin: 0 0 0.9rem;
}

/* ---------- Messages ---------- */
.messages { margin: 1.25rem 0 0; display: flex; flex-direction: column; gap: 0.5rem; }
.message {
  padding: 0.7rem 1rem;
  border-radius: var(--radius);
  font-size: 0.87rem;
  line-height: 1.5;
  border: 1px solid transparent;
}
.message-success { background: var(--added-wash); border-color: var(--added-wash-line); color: var(--added-wash-ink); }
.message-info { background: var(--accent-wash); border-color: var(--accent-wash-line); color: var(--accent-wash-ink); }
.message-error, .message-warning { background: var(--danger-wash); border-color: var(--danger-wash-line); color: var(--danger-wash-ink); }

/* ---------- Stepper ---------- */
.stepper {
  display: flex;
  gap: 0;
  margin: 0 0 2.25rem;
  padding: 0;
  counter-reset: none;
}
.stepper-step {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding-bottom: 0.75rem;
  border-bottom: 2px solid var(--line);
  color: var(--dim);
  font-size: 0.82rem;
  position: relative;
}
.stepper-step + .stepper-step { margin-left: 0.9rem; }
.stepper-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.4rem;
  height: 1.4rem;
  border-radius: 50%;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  border: 1px solid var(--line);
  background: var(--page-recto);
  flex-shrink: 0;
}
.stepper-label { white-space: nowrap; }
/* Only steps that are reachable (is-current or is-done) render an <a> at
   all — a future step stays plain <span>s, so there's nothing here to
   style for that case. Overrides the global `a` rule (accent color,
   underline) since a stepper entry should still read as a step, not a
   normal inline text link; the underline moves to just the label, and
   only on hover, as the one "yes, this is clickable" cue. */
.stepper-link {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  color: inherit;
  text-decoration: none;
}
.stepper-link:hover .stepper-label { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.15em; }
.stepper-step.is-current { color: var(--ink); border-bottom-color: var(--accent); font-weight: 600; }
.stepper-step.is-current .stepper-num { background: var(--accent); border-color: var(--accent); color: #fff; }
.stepper-step.is-done { color: var(--ink); border-bottom-color: var(--added); }
.stepper-step.is-done .stepper-num { background: var(--added-wash); border-color: var(--added); color: var(--added); }

@media (max-width: 640px) {
  .stepper-label { display: none; }
  .stepper-step.is-current .stepper-label { display: inline; }
}

/* ---------- Cards & forms ---------- */
.card {
  background: var(--page-recto);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  padding: 1.75rem;
}
.card + .card { margin-top: 1.25rem; }

.field { margin-top: 1.25rem; }
.field:first-child { margin-top: 0; }
.field label {
  display: block;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 0.4rem;
}
.field .hint { font-size: 0.78rem; color: var(--dim); margin-top: 0.4rem; }

/* Styled stand-in for the raw OS file-picker button — pairs with a
   visually-hidden <input type="file"> (see forms.py/step_resume.html);
   the previous bare native button looked visually jarring next to every
   other button in the app. */
.file-upload-row { display: flex; align-items: center; gap: 0.85rem; flex-wrap: wrap; }
.file-upload-btn {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0.55rem 1.1rem;
  background: var(--page-recto); color: var(--ink); border: 1px solid var(--line);
  border-radius: var(--radius-sm); font-size: 0.85rem; font-weight: 600;
  cursor: pointer; transition: border-color 0.15s, color 0.15s;
}
.file-upload-btn:hover { border-color: var(--accent); color: var(--accent); }
.file-upload-name { font-size: 0.85rem; color: var(--dim); }

.field input[type="text"], .field input[type="url"], .field input[type="password"],
.field input[type="email"], .field textarea, .field select {
  width: 100%;
  box-sizing: border-box;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font-family: inherit;
  font-size: 0.92rem;
  background: var(--page-recto);
  color: var(--ink);
  transition: border-color 0.15s, box-shadow 0.15s;
}
.field textarea { resize: vertical; }
.field input:focus, .field textarea:focus, .field select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-wash);
}
textarea#id_resume_yaml {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  line-height: 1.6;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  padding: 0.65rem 1.4rem;
  background: var(--accent);
  color: #fff;
  border: 1px solid var(--accent);
  border-radius: var(--radius-sm);
  font-family: inherit;
  font-size: 0.88rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, opacity 0.15s;
}
.btn:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.btn:disabled { opacity: 0.6; cursor: not-allowed; }
.btn-secondary { background: var(--page-recto); color: var(--ink); border-color: var(--line); }
.btn-secondary:hover { border-color: var(--accent); color: var(--accent); background: var(--page-recto); }
.btn-ghost {
  background: transparent; color: var(--dim); border: none; padding: 0.4rem 0.1rem;
  font-size: 0.82rem; text-decoration: underline; text-underline-offset: 0.2em; cursor: pointer;
}
.btn-ghost:hover { color: var(--accent); }
.actions { margin-top: 1.75rem; display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; }
/* Groups controls into their own line within .actions (result.html's
   export cluster vs. save/navigation cluster) without changing .actions
   itself — that's still a plain single-row flex container everywhere
   else it's used (step_resume.html's upload/YAML-form button groups).
   flex: 1 1 100% claims the full row width, so .actions's own flex-wrap
   pushes the next .actions-row onto a new line on its own. */
.actions-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; flex: 1 1 100%; }
.actions-row-secondary { margin-top: 0.1rem; }
.pdf-actions { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }

/* Compact <select>, sized to sit inline next to .btn/.btn-ghost in a
   .resume-row-actions row — .field select (the form-field version) is
   width:100% and meant for a block-level container, wrong fit here. */
.theme-select-inline {
  padding: 0.4rem 0.5rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font-family: inherit;
  font-size: 0.82rem;
  background: var(--page-recto);
  color: var(--ink);
}
.theme-select-inline:focus { outline: none; border-color: var(--accent); }
.application-status-select { margin-top: 0.5rem; }
.pdf-actions select {
  padding: 0.6rem 2rem 0.6rem 0.75rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font-family: inherit;
  font-size: 0.85rem;
  background: var(--page-recto);
  color: var(--ink);
}
.pdf-actions select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-wash); }

.errorlist { list-style: none; padding: 0; margin: 0.75rem 0 0; }
.errorlist li {
  background: var(--danger-wash); border: 1px solid var(--danger-wash-line); color: var(--danger-wash-ink);
  padding: 0.65rem 0.9rem; border-radius: var(--radius-sm); font-size: 0.85rem; margin-bottom: 0.5rem;
}
.notes {
  background: var(--accent-wash); border: 1px solid var(--accent-wash-line); color: var(--accent-wash-ink);
  padding: 1rem 1.1rem; border-radius: var(--radius); margin-top: 1rem; font-size: 0.87rem; line-height: 1.55;
}
.notes strong { display: block; margin-bottom: 0.15rem; }
.notes-danger {
  background: var(--danger-wash); border-color: var(--danger-wash-line); color: var(--danger-wash-ink);
}
.gap-list { list-style: none; padding: 0; margin: 0.5rem 0 0; display: flex; flex-direction: column; gap: 0.4rem; }
.gap-item { font-size: 0.87rem; line-height: 1.5; }
.gap-priority {
  display: inline-block; font-size: 0.68rem; font-weight: 700; letter-spacing: 0.02em; text-transform: uppercase;
  padding: 0.1rem 0.45rem; border-radius: 999px; margin-right: 0.4rem; vertical-align: middle;
}
.gap-priority-required { background: var(--danger-wash); color: var(--danger-wash-ink); }
.gap-priority-nice_to_have { background: var(--page-verso); border: 1px solid var(--line); color: var(--dim); }
.gap-count-badge {
  display: inline-block; font-family: var(--font-mono); font-size: 0.78rem; font-weight: 600;
  background: var(--accent-wash); color: var(--accent-wash-ink); padding: 0.05rem 0.45rem;
  border-radius: var(--radius-sm); margin-right: 0.5rem; vertical-align: middle;
}
.gap-item-meta { display: block; font-size: 0.78rem; color: var(--dim); margin-top: 0.1rem; }

/* Recurring-gaps chips on /resumes/ — a grid of small chips rather than
   the plain .gap-list/.gap-item stack above (kept as-is: still used by
   result.html's per-result gaps and landing.html's illustrative preview,
   both fine as a plain list in their own single-column context). A
   chip's small footprint suits this page's dashboard-of-cards language
   better than a tall vertical list would once there are several gaps.

   Shape/color vary with what the data says, not for decoration's own
   sake — see resume_library.html's comment above the loop. Badge sizing
   (2.25rem, mono) matches landing.html's .step-num; the hexagon clip-path
   is new, but only applied to the badge — a short, fixed "N×" string,
   never the variable-length requirement text next to it, which stays in
   a plain rectangular card so it can wrap normally at any length. */
.gap-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  gap: 0.6rem;
  margin-top: 0.5rem;
}
.gap-chip {
  border-radius: var(--radius);
  padding: 0.85rem 1rem;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.4rem;
}
.gap-chip-required { background: var(--danger-wash); border: 1px solid var(--danger-wash-line); }
.gap-chip-nice { background: var(--accent-wash); border: 1px solid var(--accent-wash-line); }
.gap-chip-badge {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.25rem; height: 2.25rem;
  clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
  color: #fff; font-family: var(--font-mono);
  font-size: 0.82rem; font-weight: 600; flex-shrink: 0;
}
/* The wash tint above is real but too pale to actually read as two
   colors (both ~96% lightness, ~0.02 chroma) — checked computed styles
   directly to confirm. The badge is where the required/nice-to-have
   distinction needs to actually be visible: solid --danger/--accent,
   both verified against white text (4.76:1 / 7.35:1 — WCAG AA is 4.5:1
   for normal text), not just eyeballed. */
.gap-chip-required .gap-chip-badge { background: var(--danger); }
.gap-chip-nice .gap-chip-badge { background: var(--accent); }
.gap-chip-requirement { font-weight: 600; font-size: 0.87rem; color: var(--ink); }
.gap-chip .gap-item-meta { margin-top: -0.15rem; }

/* The single most-recurring gap (gap_summary's first entry, already
   sorted by count descending) gets more room and a bigger badge instead
   of competing at the same weight as every other chip. */
.gap-chip-featured {
  grid-column: span 2;
  padding: 1.1rem 1.25rem;
}
.gap-chip-featured .gap-chip-badge { width: 2.75rem; height: 2.75rem; font-size: 0.95rem; }
.gap-chip-featured .gap-chip-requirement { font-size: 1.05rem; }
@media (max-width: 460px) {
  .gap-chip-featured { grid-column: span 1; }
}

/* Category bars — a coarser "what kind of gap, mostly" read above the
   per-requirement chips. Reuses the chips' own required/nice-to-have
   color semantics (--danger for "at least one required", --accent
   otherwise) rather than a new palette, same reasoning as the chips. */
.gap-category-bars {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-bottom: 1.1rem;
}
.gap-category-row {
  display: grid;
  grid-template-columns: 9rem 1fr 1.5rem;
  align-items: center;
  gap: 0.6rem;
}
.gap-category-label { font-size: 0.78rem; color: var(--dim); }
.gap-category-bar {
  height: 0.5rem;
  background: var(--page-verso);
  border-radius: 999px;
  overflow: hidden;
}
.gap-category-fill { height: 100%; background: var(--accent); border-radius: 999px; }
.gap-category-fill-required { background: var(--danger); }
.gap-category-count {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--dim);
  text-align: right;
}
@media (max-width: 460px) {
  .gap-category-row { grid-template-columns: 6.5rem 1fr 1.25rem; }
  .gap-category-label { font-size: 0.72rem; }
}

/* Recurring gaps as a floating bubble + popover, not an inline section —
   the only genuinely floating/overlay element anywhere in this app's
   chrome (no FABs or dropdowns elsewhere), so it stays deliberately
   light-weight: no dimmed backdrop like a real modal, closes on an
   outside click the same as a normal dropdown would (see extra_js).
   env(safe-area-inset-bottom) accounts for a phone's home-indicator
   area; falls back to 0px on anything that doesn't support it. */
.gaps-bubble {
  position: fixed;
  right: 1.25rem;
  bottom: calc(1.25rem + env(safe-area-inset-bottom, 0px));
  z-index: 40;
  width: 3.5rem;
  height: 3.5rem;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  border: none;
  box-shadow: var(--shadow-card);
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  line-height: 1.1;
}
.gaps-bubble:hover { background: var(--accent-hover); }
.gaps-bubble-count { font-size: 1.1rem; font-weight: 700; }
.gaps-bubble-label { font-size: 0.55rem; text-transform: uppercase; letter-spacing: 0.04em; opacity: 0.85; }

.gaps-panel {
  display: none;
  position: fixed;
  right: 1.25rem;
  bottom: calc(5.5rem + env(safe-area-inset-bottom, 0px)); /* clears the bubble above it */
  z-index: 40;
  width: min(23rem, calc(100vw - 2.5rem));
  max-height: min(28rem, calc(100vh - 8rem));
  overflow-y: auto;
  background: var(--page-recto);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
}
.gaps-panel.is-open { display: block; }
.gaps-panel-header {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.9rem 1.1rem;
  background: var(--page-recto);
  border-bottom: 1px solid var(--line);
}
.gaps-panel-close {
  background: none;
  border: none;
  color: var(--dim);
  cursor: pointer;
  font-size: 1.2rem;
  line-height: 1;
  padding: 0.2rem;
}
.gaps-panel-close:hover { color: var(--accent); }
.gaps-panel-body { padding: 1.1rem; }
.gaps-panel-footer-link {
  display: block;
  margin-top: 1rem;
  padding-top: 0.9rem;
  border-top: 1px solid var(--line);
  font-size: 0.85rem;
  font-weight: 600;
}

@media (max-width: 460px) {
  .gaps-bubble { right: 1rem; width: 3.25rem; height: 3.25rem; }
  .gaps-panel { right: 1rem; left: 1rem; width: auto; bottom: calc(5rem + env(safe-area-inset-bottom, 0px)); }
}

details.advanced { margin-top: 1.5rem; }
details.advanced > summary {
  cursor: pointer; font-size: 0.82rem; font-weight: 600; color: var(--dim);
  list-style: none; display: inline-flex; align-items: center; gap: 0.35rem;
}
details.advanced > summary::-webkit-details-marker { display: none; }
/* A CSS-drawn triangle, not the Unicode "▸"/"▾" glyphs this used to be —
   those rendered as a bare "·" in real testing (Chrome/macOS), reading as
   a stray, broken bullet with nothing before it. Border-trick triangle
   has no font/glyph dependency at all, so there's nothing left to fail to
   render; rotating the same shape 90° for the open state also means only
   one shape to draw instead of two separate glyphs to keep in sync. */
details.advanced > summary::before {
  content: "";
  display: inline-block;
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 3.5px 0 3.5px 5px;
  border-color: transparent transparent transparent currentColor;
  transition: transform 0.15s;
}
details.advanced[open] > summary::before { transform: rotate(90deg); }
details.advanced > summary:hover { color: var(--accent); }
details.advanced .field { margin-top: 1rem; }
details.advanced-body-pad { padding-top: 1rem; }

.upload-panel {
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  padding: 1.5rem;
  background: var(--page-verso);
}
.confirm-row { display: flex; gap: 0.75rem; flex-wrap: wrap; margin-top: 0.5rem; }

/* ---------- Working / progress panel ---------- */
.working {
  margin-top: 1.5rem;
  padding: 1.75rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--page-recto);
  text-align: center;
}
.working[hidden] { display: none; }
.working-rule {
  height: 2px;
  background: var(--line);
  border-radius: 2px;
  overflow: hidden;
  margin-bottom: 1.1rem;
}
.working-rule::after {
  content: "";
  display: block;
  height: 100%;
  width: 40%;
  background: var(--accent);
  animation: working-sweep 1.6s ease-in-out infinite;
}
.working-label { font-size: 0.9rem; color: var(--ink); font-weight: 500; }
.working-sub { font-size: 0.8rem; color: var(--dim); margin-top: 0.35rem; }

@keyframes working-sweep {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(250%); }
}
@media (prefers-reduced-motion: reduce) {
  .working-rule::after { animation: none; width: 100%; }
}

/* ---------- Result header / spread ---------- */
.result-header { margin-bottom: 1.75rem; }
.result-header h1 { font-size: 1.5rem; }
.result-posting-link { font-size: 0.85em; text-decoration: none; }
.result-meta { color: var(--dim); font-size: 0.88rem; margin-top: 0.3rem; }

.stats-bar {
  display: flex; flex-wrap: wrap; gap: 1.5rem;
  padding: 1rem 1.25rem; margin: 1.5rem 0;
  background: var(--page-recto); border: 1px solid var(--line); border-radius: var(--radius);
}
.stat { display: flex; flex-direction: column; }
.stat-value { font-family: var(--font-mono); font-size: 1.1rem; font-weight: 500; }
.stat-label { font-size: 0.72rem; color: var(--dim); text-transform: uppercase; letter-spacing: 0.05em; }

.untouched-note {
  font-size: 0.82rem; color: var(--dim); margin: 0.75rem 0 1.75rem;
  padding: 0.75rem 1rem; border-left: 2px solid var(--line);
}

/* The spread itself: verso (original) recessed, recto (tailored) lit. */
.spread-head {
  display: grid; grid-template-columns: 1fr 1fr; gap: 1px;
  background: var(--line); border: 1px solid var(--line); border-radius: var(--radius) var(--radius) 0 0; overflow: hidden;
}
.spread-head > div {
  padding: 0.6rem 1.25rem; font-size: 0.72rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
}
.spread-head .col-original { background: var(--page-verso); color: var(--dim); }
.spread-head .col-tailored { background: var(--page-recto); color: var(--accent); }

.diff-summary {
  display: grid; grid-template-columns: 1fr 1fr; gap: 1px; background: var(--line);
  border: 1px solid var(--line); border-top: none; border-radius: 0 0 var(--radius) var(--radius);
  margin-bottom: 1.75rem; font-family: var(--font-read); font-size: 1rem; line-height: 1.65;
}
.diff-summary > div { padding: 1.25rem; }
.diff-summary .col-original { background: var(--page-verso); color: var(--dim); }
.diff-summary .col-tailored { background: var(--page-recto); }

/* ---------- Diff entries ---------- */
.diff-entry {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  margin-bottom: 1rem;
  background: var(--page-recto);
  overflow: hidden;
}
.diff-entry > summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem 1.25rem;
  background: var(--page-verso);
}
.diff-entry > summary::-webkit-details-marker { display: none; }
.diff-entry-title { display: flex; flex-direction: column; gap: 0.1rem; }
.diff-entry-role { font-weight: 600; }
.diff-entry-company { font-size: 0.82rem; color: var(--dim); }
.diff-entry-meta { display: flex; align-items: center; gap: 0.75rem; flex-shrink: 0; }
.diff-entry-dates { font-size: 0.78rem; color: var(--dim); font-family: var(--font-mono); white-space: nowrap; }

.pill {
  display: inline-block; font-size: 0.68rem; font-weight: 600; letter-spacing: 0.04em;
  text-transform: uppercase; padding: 0.15rem 0.55rem; border-radius: 999px;
}
.pill-unchanged { background: var(--line); color: var(--dim); }
.pill-changed { background: var(--accent-wash); color: var(--accent); }

.diff-entry-body { padding: 1rem 1.25rem 1.25rem; }
.diff-rationale {
  font-size: 0.85rem; color: var(--accent-wash-ink); background: var(--accent-wash);
  border-radius: var(--radius-sm); padding: 0.6rem 0.85rem; margin-bottom: 1rem;
}
.diff-rationale::before { content: "Why: "; font-weight: 600; }

.diff-row {
  display: grid; grid-template-columns: 1fr 1fr; gap: 0;
  border-top: 1px solid var(--line);
  font-family: var(--font-read); font-size: 0.95rem; line-height: 1.6;
}
.diff-row:first-child { border-top: none; }
.diff-cell { padding: 0.6rem 1rem; }
.diff-cell.diff-original { background: var(--page-verso); color: var(--dim); }
.diff-empty { color: var(--line); }

.diff-row.diff-added .diff-cell.diff-original,
.diff-row.diff-removed .diff-cell.diff-tailored { background: repeating-linear-gradient(45deg, var(--page-verso), var(--page-verso) 6px, oklch(0.93 0.008 38) 6px, oklch(0.93 0.008 38) 7px); }

.tk-equal { color: inherit; }
.tk-del { color: var(--danger); text-decoration: line-through; text-decoration-thickness: 1px; background: var(--danger-wash); }
.tk-ins { color: var(--added); background: var(--added-wash); border-radius: 2px; }

.flag-badge {
  display: inline-flex; align-items: center; gap: 0.3rem; margin-left: 0.5rem;
  font-size: 0.7rem; font-family: var(--font-mono); color: var(--dim); vertical-align: middle;
}

/* ---------- Inline "edit wording" (result.html + _editable_text.html) ---------- */
.view-toggle-row { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; margin: 1.5rem 0; }
.view-toggle-row .view-toggle-label { margin: 0; }
.reset-edits-form { margin: 0; }

.editable-text { position: relative; }
.edit-icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.4rem; height: 1.4rem; margin-left: 0.35rem; vertical-align: middle;
  background: transparent; border: none; border-radius: var(--radius-sm);
  color: var(--dim); font-size: 0.85rem; line-height: 1; cursor: pointer;
}
.edit-icon-btn:hover { background: var(--accent-wash); color: var(--accent); }
.edit-badge {
  display: inline-block; margin-left: 0.4rem; padding: 0.05rem 0.5rem;
  font-size: 0.68rem; font-weight: 600; letter-spacing: 0.02em; text-transform: uppercase;
  background: var(--accent-wash); color: var(--accent); border-radius: 999px; vertical-align: middle;
}
.editable-area { display: block; margin-top: 0.4rem; }
/* Each of the three above sets its own `display`, which — same
   specificity as the browser's built-in "[hidden] { display: none }",
   later in the cascade — would otherwise win over JS's el.hidden =
   true/false and leave the editor and "Edited" badge stuck visible
   from first render. Same pattern .working[hidden] already uses above. */
.edit-icon-btn[hidden], .edit-badge[hidden], .editable-area[hidden] { display: none; }

.add-bullet-row { padding: 0.6rem 1rem; border-top: 1px solid var(--line); }
.add-bullet-row .editable-area { max-width: 26rem; }
.editable-area textarea {
  width: 100%; font-family: inherit; font-size: inherit; line-height: inherit;
  padding: 0.5rem 0.65rem; border: 1px solid var(--accent); border-radius: var(--radius-sm); resize: vertical;
}
.editable-area-actions { display: flex; gap: 0.75rem; margin-top: 0.4rem; }
.btn-tiny {
  padding: 0.3rem 0.75rem; font-size: 0.78rem; font-weight: 600; border-radius: var(--radius-sm);
  background: var(--accent); color: #fff; border: 1px solid var(--accent); cursor: pointer;
}
.btn-tiny:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.btn-tiny:disabled { opacity: 0.6; cursor: not-allowed; }
.btn-tiny-ghost { background: transparent; color: var(--dim); border-color: var(--line); }
.btn-tiny-ghost:hover { color: var(--accent); border-color: var(--accent); background: transparent; }

/* align-items: start — without it, grid stretches the shorter tag-list to
   match the taller (wrapped) one, and flex-wrap's default align-content:
   stretch then inflates that single line of pills into tall ellipses. Only
   shows up once the two sides' tag counts wrap to a different number of
   lines, which real tag lists do but small fixture data may not. */
.diff-tags { padding: 0.85rem 1.25rem; border-top: 1px solid var(--line); display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; align-items: start; }
.tag-list { display: flex; flex-wrap: wrap; align-content: flex-start; gap: 0.4rem; }
.tag {
  font-size: 0.72rem; font-weight: 500; letter-spacing: 0.02em; padding: 0.2rem 0.55rem;
  border-radius: 999px; background: var(--line); color: var(--dim);
}
.tag.tk-del { text-decoration: line-through; background: var(--danger-wash); color: var(--danger); }
.tag.tk-ins { background: var(--added-wash); color: var(--added); }

/* ---------- Mobile: stack the spread ---------- */
/* No-JS "show original too" toggle: a checkbox immediately preceding
   .diff-view in the DOM (see result.html), targeted via the general
   sibling combinator. Unchecked (default) = tailored-only reading view. */
#show-original { position: absolute; opacity: 0; pointer-events: none; }
.view-toggle-label {
  display: none;
  align-items: center; gap: 0.5rem; font-size: 0.85rem; cursor: pointer;
  padding: 0.5rem 0.9rem; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--page-recto); width: fit-content; margin: 1.5rem 0;
}

@media (max-width: 780px) {
  .view-toggle-label { display: inline-flex; }

  .spread-head, .diff-summary, .diff-row, .diff-tags { grid-template-columns: 1fr; }
  .spread-head .col-original, .diff-summary .col-original { display: none; }
  .diff-row .diff-cell.diff-original { display: none; }
  .diff-row .diff-cell.diff-tailored::before {
    content: attr(data-label); display: block; font-size: 0.68rem; color: var(--dim);
    text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.2rem; font-family: var(--font-ui);
  }
  .diff-tags > div:first-child { display: none; }

  #show-original:checked ~ .diff-view .spread-head,
  #show-original:checked ~ .diff-view .diff-summary,
  #show-original:checked ~ .diff-view .diff-row,
  #show-original:checked ~ .diff-view .diff-tags { grid-template-columns: 1fr 1fr; }
  #show-original:checked ~ .diff-view .spread-head .col-original,
  #show-original:checked ~ .diff-view .diff-summary .col-original,
  #show-original:checked ~ .diff-view .diff-row .diff-cell.diff-original,
  #show-original:checked ~ .diff-view .diff-tags > div:first-child { display: block; }
}

/* ==========================================================================
   Marketing / landing page (tailor/landing.html) — the one public,
   unauthenticated page in the app. Reuses every token above (same nav,
   same accent, same fonts) so it reads as one product, not a bolted-on
   microsite. New component classes below; nothing here changes how the
   gated wizard renders.
   ========================================================================== */

.marketing-section { padding: 4.5rem 1.5rem; border-bottom: 1px solid var(--line); }
.marketing-section.is-verso { background: var(--page-verso); }
.marketing-inner { max-width: var(--content-width-wide); margin: 0 auto; }
.marketing-inner.is-narrow { max-width: 42rem; }
.marketing-eyebrow {
  font-family: var(--font-mono); font-size: 0.75rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--accent); margin: 0 0 0.75rem; text-align: center;
}
.marketing-heading {
  font-family: var(--font-ui); font-weight: 700; letter-spacing: -0.015em; color: var(--ink);
  text-align: center; font-size: 1.9rem; line-height: 1.15; margin: 0 auto 0.75rem; max-width: 40rem;
}
.marketing-lede {
  text-align: center; color: var(--dim); font-size: 1.05rem; line-height: 1.6;
  max-width: 38rem; margin: 0 auto 2.5rem;
}

/* ---------- Hero ---------- */
.hero { padding: 5.5rem 1.5rem 4.5rem; text-align: center; }
.hero-heading {
  font-family: var(--font-ui); font-weight: 750; letter-spacing: -0.02em; color: var(--ink);
  font-size: 2.6rem; line-height: 1.08; margin: 0 auto 1.1rem; max-width: 42rem;
}
.hero-heading em { color: var(--accent); font-style: normal; }
.hero-lede { color: var(--dim); font-size: 1.15rem; line-height: 1.6; max-width: 36rem; margin: 0 auto 2.25rem; }
@media (min-width: 640px) { .hero-heading { font-size: 3.4rem; } }

/* ---------- Waitlist form (hero + bottom CTA band both use this) ---------- */
.hero-actions { display: flex; gap: 0.6rem; justify-content: center; flex-wrap: wrap; }
.waitlist-form { display: flex; gap: 0.6rem; justify-content: center; flex-wrap: wrap; max-width: 30rem; margin: 0 auto; }
.waitlist-form input[type="email"] {
  flex: 1; min-width: 14rem; padding: 0.7rem 1rem; border: 1px solid var(--line); border-radius: var(--radius-sm);
  font-family: inherit; font-size: 0.95rem; background: var(--page-recto); color: var(--ink);
}
.waitlist-form input[type="email"]:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-wash); }
.waitlist-note { text-align: center; font-size: 0.8rem; color: var(--dim); margin-top: 0.75rem; }
.cta-band .waitlist-note { color: oklch(0.75 0.02 38); }

/* ---------- How it works ---------- */
.steps-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.75rem; counter-reset: step; }
.step-card { text-align: center; }
.step-num {
  display: inline-flex; align-items: center; justify-content: center; width: 2.25rem; height: 2.25rem;
  border-radius: 50%; background: var(--accent); color: #fff; font-family: var(--font-mono);
  font-size: 0.9rem; font-weight: 600; margin-bottom: 0.9rem;
}
.step-title { font-weight: 600; color: var(--ink); margin-bottom: 0.35rem; }
.step-body { font-size: 0.88rem; color: var(--dim); line-height: 1.55; }
@media (max-width: 780px) { .steps-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 480px) { .steps-grid { grid-template-columns: 1fr; } }

/* ---------- Capabilities ---------- */
.feature-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.25rem; }
.feature-card { background: var(--page-recto); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-card); padding: 1.5rem; }
.feature-title { font-weight: 600; color: var(--ink); margin-bottom: 0.4rem; }
.feature-body { font-size: 0.9rem; color: var(--dim); line-height: 1.6; }
@media (max-width: 640px) { .feature-grid { grid-template-columns: 1fr; } }

/* ---------- Approach ---------- */
.approach-list { display: flex; flex-direction: column; gap: 1.5rem; max-width: 40rem; margin: 0 auto; }
.approach-item { display: flex; gap: 1rem; }
.approach-mark { color: var(--accent); font-family: var(--font-mono); font-size: 0.9rem; flex-shrink: 0; padding-top: 0.15rem; }
.approach-title { font-weight: 600; color: var(--ink); margin-bottom: 0.25rem; }
.approach-body { font-size: 0.9rem; color: var(--dim); line-height: 1.6; }

/* ---------- FAQ (details/summary — matches details.advanced elsewhere) ---------- */
.faq-list { max-width: 42rem; margin: 0 auto; display: flex; flex-direction: column; gap: 0.75rem; }
.faq-item { background: var(--page-recto); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.faq-item > summary {
  cursor: pointer; list-style: none; padding: 1rem 1.25rem; font-weight: 600; color: var(--ink);
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
}
.faq-item > summary::-webkit-details-marker { display: none; }
.faq-item > summary::after { content: "+"; color: var(--dim); font-weight: 400; flex-shrink: 0; }
.faq-item[open] > summary::after { content: "\2212"; }
.faq-item-body { padding: 0 1.25rem 1.1rem; font-size: 0.9rem; color: var(--dim); line-height: 1.6; }

/* ---------- Final CTA band — the one deliberate dark surface on the site.
   Not a "dark mode" (Spread stays light-only everywhere else, see the
   :root comment above); this is a single high-contrast section for
   emphasis, a common landing-page technique. ---------- */
.cta-band { background: var(--ink); border-bottom: none; }
.cta-band .marketing-heading, .cta-band .marketing-eyebrow { color: var(--page-recto); }
.cta-band .marketing-eyebrow { color: oklch(0.72 0.1 38); }
.cta-band .marketing-lede { color: oklch(0.78 0.015 38); }
.cta-band .waitlist-form input[type="email"] { background: oklch(0.24 0.014 38); border-color: oklch(0.32 0.014 38); color: var(--page-recto); }
.cta-band .waitlist-form input[type="email"]::placeholder { color: oklch(0.6 0.015 38); }

/* ---------- Footer ---------- */
.marketing-footer { padding: 2rem 1.5rem; text-align: center; font-size: 0.8rem; color: var(--dim); }
/* base.html's sitewide copyright line — landing.html's own .marketing-footer
   above covers that page; this one reaches every other page (and landing
   too, since it renders outside {% block body %}), so it stays deliberately
   plainer: no border/background of its own, just enough padding to read as
   a distinct footer rather than a trailing line of body text. */
.site-footer { padding: 1.5rem 1.5rem 2.5rem; text-align: center; font-size: 0.78rem; color: var(--dim); }

/* ---------- Saved tailored results list ---------- */
/* .results-list-meta is also reused as a plain small-muted-text utility
   outside this page (step_resume.html, step_posting.html) — kept name and
   rule as-is rather than folding it into the resume-card-* set below. */
.results-list-meta { font-size: 0.82rem; color: var(--dim); margin-top: 0.15rem; }

.badge-default {
  display: inline-block; margin-left: 0.5rem; padding: 0.1rem 0.55rem;
  border-radius: 999px; background: var(--accent-wash); color: var(--accent);
  font-size: 0.72rem; font-weight: 600; vertical-align: middle;
}

/* A grid of cards, not a stacked list of dense rows — each saved item
   gets its own presence instead of competing for space in one long
   horizontal line of controls. auto-fill/minmax rather than a fixed
   column count: however many 15rem-ish cards fit the content width is
   how many show per row, no breakpoint math needed for the common cases. */
.resume-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  gap: 1rem;
}
.resume-card {
  background: var(--page-recto);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  overflow: hidden; /* clips resume-card-accent's square corners to the card's own radius */
  display: flex;
  flex-direction: column;
}
/* Thin accent edge instead of a literal photo/icon header — enough to
   give each card a visual anchor without this app's restrained palette
   turning into the source material's much louder, per-card color coding. */
.resume-card-accent { height: 0.3rem; background: var(--accent); flex-shrink: 0; }

/* A live preview of the actual PDF, not a static thumbnail — browsers
   already render PDFs natively inside an iframe, so this costs no new
   dependency (no poppler/pdf2image install on the Mac Mini) and is
   always accurate, never a stale cached snapshot. Small by default;
   .is-expanded (toggled by the click handler in resume_library.html)
   grows it in place rather than opening a new tab — the existing
   "Preview ↗" button still does that, for genuine reading/printing. */
.resume-pdf-preview {
  position: relative;
  height: 9rem;
  overflow: hidden;
  cursor: zoom-in;
  background: var(--page-verso);
  border-bottom: 1px solid var(--line);
  flex-shrink: 0;
}
.resume-pdf-preview.is-expanded { height: 32rem; cursor: default; }
.resume-pdf-preview iframe {
  width: 100%;
  height: 100%;
  border: none;
  /* Small/default state is look-don't-touch — scrolling/clicking inside
     the embedded viewer at thumbnail size would fight with the wrapper's
     own click-to-expand handler. Expanded, there's no such conflict (the
     hint badge below is a separate, always-on-top element that keeps
     working as the collapse control), so pointer-events turns back on:
     otherwise "expand" would just mean "bigger but still inert," unable
     to scroll past page 1 to see the rest. */
  pointer-events: none;
}
.resume-pdf-preview.is-expanded iframe { pointer-events: auto; }
.resume-pdf-preview-hint {
  position: absolute;
  bottom: 0.5rem;
  right: 0.5rem;
  background: var(--ink);
  color: var(--page-recto);
  font-size: 0.7rem;
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
  opacity: 0.85;
  /* Always clickable regardless of the iframe's own pointer-events state
     above — this badge, not the iframe, is what collapse falls back to
     once expanded. */
  pointer-events: auto;
}
.resume-card-body { padding: 1.1rem 1.25rem; flex: 1 1 auto; }
.resume-card-title { font-weight: 600; color: var(--ink); }
.resume-card-footer {
  padding: 0.85rem 1.25rem; border-top: 1px solid var(--line);
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 0.6rem;
}
/* View/Delete as plain text links, not full buttons — Preview (inside
   .preview-combo) is the one action people come to this page for; these
   two stay present but visually secondary, matching the source
   inspiration's one-clear-action-plus-small-metadata card footer. */
.resume-card-links { display: flex; align-items: center; gap: 0.85rem; font-size: 0.82rem; }
.resume-card-links a { color: var(--dim); }
.resume-card-links a:hover { color: var(--accent); }
.resume-card-links form { display: inline; }
.resume-card-links button {
  background: none; border: none; padding: 0; font: inherit; font-size: 0.82rem;
  color: var(--dim); cursor: pointer; text-decoration: underline; text-decoration-thickness: 1px;
}
.resume-card-links button:hover { color: var(--accent); }

/* "Tailor a new posting" — its own full-width row above .resume-grid,
   not a tile competing for attention inside it. Solid accent, not the
   dashed-outline/muted treatment this used when it lived in the grid:
   this is the one action most people come to this page to take, so it
   gets the strongest visual weight on the page, not the same weight as
   things already saved. */
.resume-cta-banner {
  display: flex; align-items: center; gap: 1rem;
  background: var(--accent); color: #fff;
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  padding: 1.1rem 1.4rem;
  margin-bottom: 1.25rem;
  text-decoration: none;
}
.resume-cta-banner:hover { background: var(--accent-hover); }
.resume-cta-banner-icon {
  width: 2.5rem; height: 2.5rem; border-radius: 50%;
  background: rgba(255, 255, 255, 0.18);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.4rem; line-height: 1; flex-shrink: 0;
}
.resume-cta-banner-text { flex: 1 1 auto; min-width: 0; }
.resume-cta-banner-title { display: block; font-weight: 700; font-size: 1.02rem; }
.resume-cta-banner-sub { display: block; font-size: 0.82rem; opacity: 0.85; margin-top: 0.1rem; }
.resume-cta-banner-arrow { font-size: 1.3rem; flex-shrink: 0; }
@media (max-width: 460px) {
  .resume-cta-banner-sub { display: none; } /* title + arrow alone still reads fine at phone width */
}

/* Preview: a style picker joined directly to its "Preview" button, one
   visual unit rather than two adjacent controls — the seam is the select's
   missing right border meeting the button's own left one. Kept as the
   first (leftmost/topmost) action in markup order — see resume_library.html
   — since it's the one people actually come to this page to use. */
.preview-combo { display: inline-flex; align-items: stretch; }
.preview-combo-select {
  border-top-right-radius: 0; border-bottom-right-radius: 0;
  border-right: none;
  max-width: 7rem;
  padding-top: 0.6rem; padding-bottom: 0.6rem;
}
.preview-combo-btn {
  border-top-left-radius: 0; border-bottom-left-radius: 0;
  white-space: nowrap;
}

@media (max-width: 460px) {
  .resume-grid { grid-template-columns: 1fr; }
}

/* Tailored-results carousel — see resume_library.html's own comment for
   why this is a horizontal strip rather than more .resume-grid rows.
   --carousel-item-width drives both the card width and the spacer math
   below from one place, so the two breakpoints below can't drift apart. */
.tailored-carousel {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}
.tailored-carousel-track {
  --carousel-item-width: 18rem;
  display: flex;
  align-items: stretch;
  gap: 1.25rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  padding: 0.5rem 0 1rem;
  min-width: 0;
  flex: 1 1 auto;
}
/* Half a card width (minus half the inter-card gap, so the math isn't
   thrown off by the one gap that lands between the spacer and the first/
   last real card) — lets the first and last cards reach true center same
   as any card in the middle, instead of stopping at the scroll edge. */
.tailored-carousel-spacer {
  flex: 1 0 auto;
  width: calc(50% - (var(--carousel-item-width) / 2) - 0.625rem);
}
.tailored-carousel-item {
  flex: 0 0 var(--carousel-item-width);
  width: var(--carousel-item-width);
  scroll-snap-align: center;
  transform-origin: center center;
  transition: transform 0.15s ease-out, opacity 0.15s ease-out;
}
.tailored-carousel-nav {
  flex: 0 0 auto;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: var(--page-recto);
  color: var(--ink);
  font-size: 1.3rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.tailored-carousel-nav:hover { border-color: var(--accent); color: var(--accent); }

@media (max-width: 460px) {
  .tailored-carousel-track { --carousel-item-width: 15rem; }
  .tailored-carousel-nav { display: none; }
}

/* Gap Readiness Board (gap_readiness.html) — three lanes grouped by what
   to do about a gap cluster (services.GAP_LANES), not by category. Each
   lane's accent color is semantic (build=accent, mention=a separate
   amber-ish hue so it reads as distinct from both "go" and "skip", skip=
   dim/neutral) rather than reusing --danger, which already means
   "required" via .gap-priority-required elsewhere on this same page -
   reusing it here for lane identity would collide with that meaning. */
.gap-readiness-headline { font-size: 1.05rem; color: var(--ink); max-width: 42rem; }
.gap-readiness-meta { font-size: 0.85rem; }

.gap-board {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.5rem;
  margin-top: 1.5rem;
  align-items: start;
}
@media (max-width: 860px) {
  .gap-board { grid-template-columns: 1fr; }
}

.gap-lane[data-kind="build"] { --lane-color: var(--accent); }
.gap-lane[data-kind="mention"] { --lane-color: oklch(0.6 0.1 95); }
.gap-lane[data-kind="skip"] { --lane-color: var(--dim); }

.gap-lane-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding-bottom: 0.7rem;
  border-bottom: 2px solid var(--lane-color, var(--line));
  margin-bottom: 1rem;
}
.gap-lane-title { font-weight: 600; font-size: 0.95rem; }
.gap-lane-sub { font-size: 0.76rem; color: var(--dim); margin-top: 0.15rem; }
.gap-lane-count { font-family: var(--font-mono); font-size: 0.8rem; color: var(--dim); }
.gap-lane-cards { display: flex; flex-direction: column; gap: 0.9rem; }

.gap-cluster-card .resume-card-accent { background: var(--lane-color, var(--accent)); }
.gap-cluster-category {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--dim);
  margin-bottom: 0.5rem;
}
.gap-cluster-top {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 0.5rem;
  margin-bottom: 0.6rem;
}
.gap-cluster-label { font-weight: 600; font-size: 0.96rem; line-height: 1.25; }
.gap-cluster-rec { font-size: 0.86rem; line-height: 1.45; margin: 0 0 0.6rem; }

details.seen { font-size: 0.78rem; color: var(--dim); }
details.seen summary {
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.02em;
  color: var(--dim);
}
details.seen summary:hover { color: var(--accent); }
details.seen .seen-list { margin: 0.4rem 0 0; padding-left: 1.1rem; }
details.seen .seen-list li { margin-bottom: 0.2rem; }
