/* ============================================================
   KAZIPOA — styles.css
   Brand tokens are the SOURCE OF TRUTH. The bold palette below
   (off-white / true black / red, Archivo) is the chosen identity;
   change the :root values to re-skin the whole app.
   ============================================================ */

:root {
  --bg:        #F5F5F5; /* off-white background */
  --accent:    #E4002B; /* signal red — primary accent */
  --soft:      #0A0A0A; /* near-black primary text */
  --muted:     #595959; /* neutral grey for secondary text (>=6:1 on off-white) */
  --surface:   #FFFFFF; /* cards / raised surfaces */
  --surface2:  #E0E0E0; /* secondary surface, borders */
  --accent2:   #FF2B4D; /* brighter red for hover/glow */
  --accent-ink:#B80022; /* darker red for SMALL red text — AA (>=6:1) on off-white where #E4002B is borderline */
  --success:   #6F9A6A; /* sage — "GROWING" tag (semantic) */
  --warn:      #C99A3F; /* ochre — "FLAT" tag (semantic) */
  --danger:    #C26A57; /* clay — "OVERSUBSCRIBED" tag (semantic) */
  --grade-free:#E3B24A; /* butter — GRADE-FREE highlight (semantic) */

  /* vivid "pop" spark — used on <10% of the page: the revealed code,
     hero KSh numbers and celebration moments. A spark, not a flood. */
  --pop:       #E4002B; /* signal red, same as the accent */
  --pop-soft:  rgba(228, 0, 43, 0.12);

  --font-display: "Archivo", system-ui, sans-serif;
  --font-body: "Archivo", system-ui, Arial, sans-serif;      /* legible body paragraphs */
  --font-num: "Archivo", system-ui, Arial, sans-serif;       /* code, numerals, tags, labels */

  --radius: 22px;
  --radius-sm: 16px;
  --maxw: 560px;
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--soft);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
}

/* No background washes: the page sits on a plain, confident off-white.
   (Faint corner red gradients used to live here as a body::before texture —
   removed deliberately: half-visible washes read as indecision, and a clean
   surface lets the single red CTA carry the brand.) */

.skip-link {
  position: absolute;
  left: -999px;
  top: 0;
  background: var(--accent);
  color: #fff;
  padding: 10px 16px;
  border-radius: 0 0 var(--radius-sm) 0;
  z-index: 100;
}
.skip-link:focus { left: 0; }

/* Visually hidden but kept in the accessibility tree (and focusable — the quiz
   heading wears this from Q2 on). Standard clip pattern. */
.sr-only {
  position: absolute !important;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ---------- header / footer ---------- */
.site-header {
  position: relative;
  z-index: 1;
  padding: 16px 20px;
  text-align: center;
  border-bottom: 1px solid var(--surface2);
}
.wordmark {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.95rem;
  letter-spacing: 0.07em;
  color: var(--soft);
}
.wordmark-accent { color: var(--accent); }
/* During the 30 questions the header steps back so the question owns the
   stage: smaller wordmark, tighter padding. :has() is progressive
   enhancement — engines without it simply keep the full-size header. */
body:has(#screen-quiz:not([hidden])) .site-header { padding: 10px 20px; }
body:has(#screen-quiz:not([hidden])) .wordmark { font-size: 1.25rem; }
/* (The header brand-credit line was removed: the Recser attribution now
   appears exactly once on the welcome screen, in the #hero-credit footer.
   Saying it twice on one screen read as insecurity, and the leaner header
   also keeps the tight vertical fit on short quiz viewports.) */

main {
  position: relative;
  z-index: 1;
  flex: 1;
  width: 100%;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 20px 18px 40px;
  display: flex;
  flex-direction: column;
}

/* ---------- screens ---------- */
.screen { animation: fade 0.25s ease; }
/* The welcome screen fills the available height so the book credit can be
   pinned to the very bottom (see .hero-credit margin-top:auto). Scoped to
   #screen-hero only — never a global footer, which previously overlapped the
   results-page buttons. The [hidden] guard keeps the screen truly hidden when
   another screen is active (display:flex would otherwise beat the UA [hidden]
   rule and leave the hero showing). */
#screen-hero {
  display: flex;
  flex-direction: column;
  flex: 1;
}
#screen-hero[hidden] { display: none; }
@keyframes fade { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

/* ---------- buttons ---------- */
.btn {
  display: inline-block;
  width: 100%;
  border: none;
  border-radius: var(--radius);
  padding: 16px 20px;
  font-family: var(--font-body);
  font-size: 1.05rem;
  font-weight: 700;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  min-height: 52px;
  transition: transform 0.12s ease, background 0.15s ease, box-shadow 0.15s ease;
}
/* The primary CTA is the ONE red moment on the welcome screen, so it gets a
   real material finish: a whisper of resting depth and an honest pressed
   state (sinks + shadow tightens). Transforms here are direct :active
   feedback, not animation — fine under prefers-reduced-motion. */
.btn-primary {
  background: var(--accent);
  color: #fff;
  box-shadow: 0 2px 12px rgba(228, 0, 43, 0.18);
}
.btn-primary:hover { background: var(--accent-ink); }
/* Double-class selector on purpose: at single-class specificity this rule
   loses to the later `.btn:active` (transform) and `.btn-glow:hover`
   (shadow, hover stays active during a mouse press), and the sink +
   tightened shadow would never render on desktop. */
.btn.btn-primary:active {
  transform: translateY(1px) scale(0.985);
  box-shadow: 0 1px 5px rgba(228, 0, 43, 0.22);
}
.btn-glow { box-shadow: 0 2px 12px rgba(228, 0, 43, 0.18); }
.btn-glow:hover { box-shadow: 0 6px 26px rgba(228, 0, 43, 0.30); }
.btn-ghost {
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--surface2);
}
.btn-ghost:hover { color: var(--soft); border-color: var(--muted); }
.btn-whatsapp { background: #25D366; color: #04391F; }
.btn-whatsapp:hover { background: #1faa53; color: #fff; }
.btn-outline { background: transparent; color: var(--accent-ink); border: 2px solid var(--accent); }
.btn-outline:hover { background: rgba(228, 0, 43, 0.08); }
.btn:active { transform: scale(0.985); }

.btn-link {
  background: none;
  border: none;
  color: var(--accent-ink);
  font-family: var(--font-body);
  font-size: 0.95rem;
  font-weight: 600;
  cursor: pointer;
  min-height: 44px;
  padding: 10px 8px;
}
.btn-link:hover { text-decoration: underline; }
.btn-link-muted { color: var(--muted); }

/* visible focus everywhere */
:focus-visible {
  outline: 3px solid var(--accent2);
  outline-offset: 2px;
}
/* ...except on the screen headings (tabindex="-1"): show() moves focus to them
   PROGRAMMATICALLY so assistive tech lands on the active section, but keyboard
   users can never Tab to them, so the red ring only ever reads as a confusing
   "box" around plain text (users mistook the hero headline for a button).
   Suppressing the ring here loses nothing: screen readers still get the focus
   move, and every genuinely Tab-reachable control keeps the visible outline. */
[tabindex="-1"]:focus-visible {
  outline: none;
}

/* ---------- HERO ---------- */
.hero { padding: 8px 0; }
.eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.18em;
  font-size: 0.72rem;
  color: var(--accent-ink);
  font-weight: 700;
  margin: 0 0 12px;
}
/* On the welcome + intro screens, red belongs to the CTA alone — the eyebrow
   steps back to quiet grey so each page has exactly one red moment.
   (The shared .eyebrow rule stays red for the other screens.) */
#screen-hero .eyebrow,
#screen-intro .eyebrow { color: var(--muted); }
.hero-title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.8rem, 7.6vw, 2.5rem);
  line-height: 1.06;
  letter-spacing: -0.01em;
  margin: 0 0 14px;
}
/* Solid black headline: the two-tone trick lives in the logo only (one
   typographic trick per page). The .hl span is kept for the line-break
   control — nowrap holds "study next." together so the wrap always lands
   as "Choose what to / study next.", never orphaning the last word. */
.hero-title .hl { color: inherit; white-space: nowrap; }
.hero-sub {
  font-size: 1.1rem;
  color: var(--soft);
  margin: 0 0 24px;
}
.resume-banner {
  margin-top: 18px;
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--surface2);
  border-radius: var(--radius-sm);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 14px;
  font-size: 0.9rem;
}
/* The `hidden` attribute must win over the display:flex above, otherwise the
   resume banner is always shown regardless of saved progress. */
.resume-banner[hidden] {
  display: none;
}

/* Book attribution pinned to the very bottom of the welcome screen (a direct
   child of #screen-hero, which is a full-height flex column): margin-top:auto
   pushes it below the empty space under the CTA. Centred, subtle supporting
   credit with a top-border separator. */
.hero-credit {
  margin-top: auto;
  padding-top: 12px;
  text-align: center;
  font-size: 0.78rem;
  line-height: 1.45;
  color: var(--muted);
  border-top: 1px solid var(--surface2);
}

/* Tiny risk-reducer directly under the CTA — the real Gen-Z hook (zero friction
   + privacy). Solid muted colour (never opacity) keeps AA contrast on cream. */
.hero-trust {
  margin: 12px 0 0;
  text-align: center;
  font-size: 0.78rem;
  letter-spacing: 0.02em;
  color: var(--muted);
}

/* Invite share — a round share button riding the header, top-right of the
   wordmark. Deliberately a QUIET monochrome ghost (outline circle, ink
   glyph): the visitor has nothing to share yet, so this control must not
   compete with the one red CTA below — sharing gets its loud moment on the
   results screen instead. Shown ONLY on the clean welcome screen — hidden
   on quiz/results and on the shared-result visitor view via body:has().
   The [hidden]-style default is display:none so it can never leak elsewhere. */
.header-share {
  display: none;
  position: absolute;
  right: 14px;
  top: 50%;
  transform: translateY(-50%);
  border: none;
  background: none;
  padding: 0;
  cursor: pointer;
  justify-items: center;
  gap: 2px;
}
body:has(#screen-hero:not([hidden])):not(:has(#shared-result:not([hidden]))) .header-share {
  display: grid;
}
.header-share svg {
  display: block;
  box-sizing: content-box;
  width: 22px;
  height: 22px;
  padding: 10px; /* + border ≈ 44px disc = full-size tap target on its own */
  border-radius: 50%;
  background: var(--surface);
  border: 1.5px solid var(--surface2);
  color: var(--soft);
  transition: border-color 0.15s ease, color 0.15s ease, transform 0.12s ease;
}
.header-share:hover svg {
  border-color: var(--muted);
}
.header-share:active svg { transform: scale(0.94); }
.header-share-label {
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

/* "What's inside" preview. A direct child of #screen-hero (a flex column).
   Deliberately a FIXED gap below the trust line (not margin-top:auto): auto
   used to float the hint into the middle of the free space, leaving a dead
   zone that read as unfinished. Now the eye steps headline → promise → CTA →
   proof in one composed run, and any leftover height pools at the bottom
   above the pinned credit (which keeps its own margin-top:auto). Hidden in
   the resume / shared-result states (see app.js); the [hidden] guard makes
   el.hidden win over the block display. */
.benefit-hint {
  margin-top: clamp(30px, 6vh, 56px);
  text-align: center;
}
.benefit-hint[hidden] { display: none; }
.benefit-cap {
  margin: 0 0 12px;
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}
.benefit-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, auto);
  justify-content: center;
  gap: 10px 22px;
  text-align: left;
}
/* On narrow phones the two-column grid forces "The course to get there" to
   wrap — a ragged edge. One aligned column, nothing ever wraps. */
@media (max-width: 380px) {
  .benefit-list {
    grid-template-columns: auto;
    gap: 8px;
  }
}
.benefit-list li {
  position: relative;
  padding-left: 22px;
  font-size: 0.9rem;
  line-height: 1.3;
  color: var(--soft);
}
/* Pure-CSS tick (rotated box with right+bottom borders) — crisp and identical
   on every device, unlike emoji check glyphs. Ink, not red: on the welcome
   screen the CTA is the only red moment, so four red ticks would dilute it. */
.benefit-list li::before {
  content: "";
  position: absolute;
  left: 3px;
  top: 0.18em;
  width: 6px;
  height: 11px;
  border: solid var(--soft);
  border-width: 0 2.5px 2.5px 0;
  transform: rotate(45deg);
}

/* ---------- INTRO (how it works) ---------- */
/* One-screen primer before Q1. The section keeps normal flow (no `display` set on
   #screen-intro) so the `hidden` attribute keeps winning — same as the other
   screens; setting display here would need a matching [hidden] guard. */
.intro { padding: 8px 0; }
.intro-title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.7rem, 7vw, 2.3rem);
  line-height: 1.08;
  letter-spacing: -0.01em;
  margin: 6px 0 14px;
}
.intro-lead {
  font-size: 1.05rem;
  line-height: 1.5;
  color: var(--muted);
  margin: 0 0 22px;
}

.intro-steps {
  list-style: none;
  margin: 0 0 20px;
  padding: 0;
  display: grid;
  gap: 12px;
}
.intro-steps li {
  display: flex;
  align-items: center;
  gap: 14px;
  font-size: 1rem;
  line-height: 1.3;
}
.intro-step-n {
  flex: none;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  /* Ink, not red: three red discs above the CTA would give the screen four
     red moments — the button must stay the only one. */
  background: var(--soft);
  color: #fff;
  font-family: var(--font-num);
  font-weight: 800;
  font-size: 0.95rem;
}
.intro-step-t { color: var(--soft); }

.intro-trust {
  margin: 12px 0 0;
  text-align: center;
  font-size: 0.78rem;
  letter-spacing: 0.02em;
  color: var(--muted);
}

/* ---------- QUIZ ---------- */
.progress { margin-bottom: 22px; }
.progress-track {
  height: 12px;
  background: var(--surface2);
  border-radius: 99px;
  overflow: hidden;
}
.progress-fill {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, var(--accent), var(--accent2));
  border-radius: 99px;
  transition: width 0.3s ease;
}
.progress-text {
  margin: 10px 0 0;
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--soft);
  letter-spacing: 0.01em;
}
/* game-like counter: the current number pops in the accent colour */
.progress-num { color: var(--accent-ink); font-size: 1.05em; font-family: var(--font-num); font-variant-numeric: tabular-nums; }
/* Compact quiz header: the bar and the "N/30" counter share one line (the full
   "Question N of 30" sentence rides along visually hidden for screen readers
   and the tap-through test). */
#screen-quiz .progress { display: flex; align-items: center; gap: 12px; }
#screen-quiz .progress-track { flex: 1 1 auto; height: 8px; }
#screen-quiz .progress-text { margin: 0; flex: 0 0 auto; font-variant-numeric: tabular-nums; }

.grade-title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.6rem, 7vw, 2.2rem);
  letter-spacing: -0.01em;
  margin: 0 0 24px;
}

/* The standing question is identical on every card, so it rides as a small
   eyebrow label; the changing activity below it is the real hero of the page. */
.quiz-q {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  margin: 0 0 6px;
}

/* The activity prompt sits above the rating scale; only the activity text is
   ever shown — the RIASEC type is never rendered to the quiz-taker. It is the
   page hero now: big display type, tight line-height and tracking. */
.activity-text {
  margin: 0 0 22px;
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 6.5vw, 2.1rem);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: var(--soft);
  /* Cap a long activity to 3 lines so an outlier question can never push the
     rating options off-screen; short screens tighten this to 2 lines below. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
}
/* ---- rating row: five faces in the thumb zone (Gen-Z redesign) ----
   One row of five emoji squares with tiny labels replaces the old stack of
   five colour-coded cards. Resting state is strictly monochrome (white square,
   grey border, muted label); red appears ONLY on states that mean "you acted
   here" (.is-selected / .is-chosen) — the same red-means-act rule screens 1-2
   follow. The DOM is unchanged: the 1-5 number keys still answer, their chips
   are just hidden, and the labels keep their exact psychometric wording. The
   old emotion-coded colour ramp (--opt-color/--opt-tint per rating) was
   removed ON PURPOSE with this repaint; don't re-add per-option colours. */
.rating-scale {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 8px;
  align-items: start;
}
.option {
  display: flex;
  align-items: center;
  gap: 16px;
  width: 100%;
  min-height: 72px;
  padding: 16px 18px;
  background: var(--surface);
  border: 2px solid var(--surface2);
  border-radius: var(--radius);
  color: var(--soft);
  font-family: var(--font-body);
  font-size: 1.1rem;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease, box-shadow 0.15s ease, transform 0.12s ease;
}
/* Only show hover on devices with a real hover pointer. On touchscreens the
   :hover state sticks to the last-tapped element, and since the rating buttons
   are reused for every question that made each new question open with the
   just-tapped option still highlighted (a false preselection). */
@media (hover: hover) {
  .option:hover { border-color: var(--opt-color, var(--accent)); background: var(--opt-tint, #F0F0F0); }
}
.option:active { transform: scale(0.99); }
.option.is-selected { border-color: var(--opt-color, var(--accent)); background: var(--opt-tint, #F0F0F0); }

/* Rating buttons become transparent COLUMNS: emoji square on top, tiny label
   under it. Every generic .option surface (card bg, border, hover pill,
   selected tint) is neutralised here — the FACE square carries the visuals
   while the whole column stays the tap target. Grade options keep the generic
   card look above. */
#rating-scale .option {
  flex-direction: column;
  gap: 8px;
  min-height: 0;
  padding: 4px 2px;
  background: transparent;
  border: none;
  border-radius: 14px;
  box-shadow: none;
  text-align: center;
}
/* number chips gone from view; typing 1-5 still answers */
#rating-scale .option-key { display: none; }
#rating-scale .option-text {
  flex: 0 0 auto;
  font-size: 0.66rem;
  font-weight: 700;
  line-height: 1.3;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}
#rating-scale .option-face {
  /* DOM order is key, label, face (unchanged for tests/SRs) — visually the
     face goes ON TOP and the label under it. This also keeps the five squares
     on one straight line: columns top-align (align-items:start on the grid),
     so uneven label wrapping hangs BELOW the row instead of pushing squares
     to different heights. */
  order: -1;
  display: grid;
  place-items: center;
  width: 100%;
  /* static fallback first, then the dvh clamp so the squares breathe a little
     with the REAL visible height (same pattern as the fit block below) */
  max-width: 54px;
  max-width: clamp(48px, 8.5dvh, 62px);
  aspect-ratio: 1;
  margin: 0 auto;
  font-size: 1.6rem;
  line-height: 1;
  opacity: 1;
  background: var(--surface);
  border: 2px solid var(--surface2);
  border-radius: 16px;
  box-shadow: 0 2px 10px rgba(10, 10, 10, 0.06);
  transition: border-color 0.15s ease, background 0.15s ease, box-shadow 0.15s ease;
}
@media (hover: hover) {
  #rating-scale .option:hover { background: transparent; }
  #rating-scale .option:hover .option-face { border-color: var(--soft); }
}
/* red = you acted here: the saved answer shown on Back / resume */
#rating-scale .option.is-selected { background: transparent; border: none; }
#rating-scale .option.is-selected .option-face {
  border-color: var(--accent);
  background: var(--pop-soft);
  box-shadow: 0 4px 14px rgba(228, 0, 43, 0.14);
}
#rating-scale .option.is-selected .option-text { color: var(--soft); }

.quiz-nav {
  margin-top: 20px;
  padding-bottom: env(safe-area-inset-bottom, 0px);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

/* keep an animating question card from spilling into a horizontal scrollbar */
.quiz { position: relative; z-index: 0; overflow-x: clip; }

/* ---------- fit the quiz on one screen (answers never cut off) ----------
   The quiz screen fills the available viewport so all five rating options stay
   in view without scrolling. The answer block is the flexible region: on tall
   screens it centres (via auto margins, which collapse cleanly on overflow); on
   genuinely short viewports (landscape / very large text) the screen scrolls
   gently as a graceful fallback rather than crushing the buttons. The vertical
   rhythm is sized in dvh just below so it tracks the ACTUAL visible viewport
   (see the note there) rather than relying on max-height media queries. */
#screen-quiz:not([hidden]) {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  overscroll-behavior: contain;
}
#screen-quiz .quiz {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
#screen-quiz .quiz-card {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
#screen-quiz .progress,
#screen-quiz .quiz-q,
#screen-quiz .activity-text,
#screen-quiz .quiz-nav { flex: 0 0 auto; }
/* THUMB-ZONE LAYOUT: the question owns the top, the face row rides the lower
   third. The activity is ordered first (order:-1) so ::before becomes a spacer
   BETWEEN question and answers: it grows with the viewport but is CAPPED — the
   "capped gap" guarantee, so question and answers never pin to opposite
   extremes of a tall phone and the question always reads as the header of its
   choices. ::after keeps a smaller, also-capped share below the row; leftover
   height pools harmlessly at the bottom. Both spacers have flex-basis 0, so on
   short screens they collapse to nothing and the screen scrolls gently as
   before. Static max-height first, then the dvh clamp for engines that honour
   it (same fallback pattern as the block below). */
#screen-quiz .activity-text { order: -1; }
#screen-quiz .quiz-card::before,
#screen-quiz .quiz-card::after { content: ""; display: block; }
#screen-quiz .quiz-card::before {
  flex: 2.5 1 0;
  max-height: 96px;
  max-height: clamp(20px, 13dvh, 118px);
}
#screen-quiz .quiz-card::after {
  flex: 1 1 0;
  max-height: 36px;
  max-height: clamp(8px, 4dvh, 40px);
}
#screen-quiz .rating-scale { margin-top: 0; margin-bottom: 0; }

/* ---- viewport-aware compaction (tracks the REAL visible height) ----
   The quiz used to compress via @media (max-height) tiers, but those misfire on
   mobile: a browser matches @media (max-height) against the toolbar-RETRACTED
   (taller) viewport, while the page box uses 100dvh, which shrinks when the
   address bar is shown. So on tall phones the tiers never fired, the quiz
   rendered full-size, and once the toolbar appeared the 5th option + the nav
   dropped below the fold. Sizing the quiz's vertical rhythm in dvh instead makes
   it track the actual visible height: it breathes on tall screens and compacts
   smoothly on short ones. Floors keep tap targets ~>=50px; anything shorter
   still (landscape / huge text) scrolls via the overflow rule above. Each dvh
   value is preceded by a static fallback for browsers without dvh support. When
   the quiz is the active screen, main's bottom padding is reclaimed for the fit
   budget; every other screen keeps the roomier default. */
/* The static fallback on each line is the COMPACT size — tuned so the whole
   screen still fits a short (~600px) visible viewport even on browsers that
   ignore dvh in clamp(); the dvh clamp then lets it breathe up to the roomier
   ceiling on tall screens. The :has() rule needs its own static fallback too,
   or padding-bottom would revert to main's full 40px when dvh isn't honoured. */
main:has(#screen-quiz:not([hidden])) {
  padding-bottom: 16px;
  padding-bottom: clamp(16px, 2.4dvh, 28px);
  /* The quiz is the only screen that must fit in one viewport, so reclaim main's
     top padding here too (every other screen keeps the roomier default 20px).
     Static fallback is the compact value; the dvh clamp lets it breathe on tall
     screens. Without this reclaim the header(69)+column+padding overflowed the
     smallest common phones (~640px visible). */
  padding-top: 8px;
  padding-top: clamp(8px, 1.6dvh, 20px);
}
#screen-quiz .progress { margin-bottom: 12px; margin-bottom: clamp(11px, 2.2dvh, 22px); }
#screen-quiz .quiz-q {
  /* push the activity DOWN, away from the eyebrow label (the gap below the
     activity is tightened to match, so the one-screen budget is unchanged) */
  margin-bottom: 9px;
  margin-bottom: clamp(9px, 1.8dvh, 16px);
}
#screen-quiz .activity-text {
  /* breathing room below the activity so the question reads clearly ABOVE its
     choices (per request this gap is ~doubled vs the old tight grouping). The
     space it adds is reclaimed from the inter-option gap below, so the one-screen
     budget is unchanged — see .rating-scale. Static fallback first (compact, for
     engines that drop dvh in clamp), then the dvh value that breathes on tall
     screens. */
  margin-bottom: 13px;
  margin-bottom: clamp(13px, 2.2dvh, 18px);
  font-size: clamp(1.4rem, 5.6vw, 2.1rem);
}
/* (The old per-option dvh compaction — stacked-card heights, number-chip
   sizes, stack gap — is gone: the single face row is far shorter than the old
   five-card stack. The face squares carry their own small dvh breathe in
   their rule above.) */
#screen-quiz .quiz-nav { margin-top: 12px; margin-top: clamp(11px, 2dvh, 20px); }
/* (The old faint red radial glow behind the prompt was removed with the
   two-colour repaint: the quiz resting state is strictly monochrome — red
   appears only on action.) */

/* card transition (input/animation layer): a pure fade-out on commit, then a
   short slide-in for the next activity. Reduced motion is handled by the global
   rule near the bottom of this file, which zeroes these durations. */
#quiz-card { transition: opacity 0.18s ease; will-change: opacity; }
#quiz-card.q-exit { opacity: 0; }
@keyframes q-enter-kf {
  from { opacity: 0; transform: translateX(var(--enter-dx, 24px)); }
  to   { opacity: 1; transform: none; }
}
#quiz-card.q-enter { animation: q-enter-kf 0.2s ease both; }
/* brief commit pulse on the tapped rating: the face square flashes solid red
   with a soft red ring — "red = you acted here" — then the card advances */
#rating-scale .option.is-chosen { background: transparent; }
#rating-scale .option.is-chosen .option-face {
  border-color: var(--accent);
  background: var(--accent);
  box-shadow: 0 0 0 5px var(--pop-soft);
  animation: opt-pop 140ms cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
#rating-scale .option.is-chosen .option-text { color: var(--accent-ink); }
@keyframes opt-pop {
  0%   { transform: scale(1); }
  60%  { transform: scale(1.06); }
  100% { transform: scale(1); }
}

/* encouraging midpoint cue — a fixed toast, so it never shifts layout, and a
   role=status aria-live region so screen-reader users hear it too */
.quiz-cue {
  position: fixed;
  left: 50%;
  bottom: 24px;
  transform: translate(-50%, 14px);
  max-width: calc(100vw - 32px);
  background: var(--soft);
  color: var(--surface);
  padding: 10px 18px;
  border-radius: 999px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.92rem;
  box-shadow: 0 10px 34px rgba(10, 10, 10, 0.28);
  opacity: 0;
  pointer-events: none;
  z-index: 60;
  transition: opacity 0.3s ease, transform 0.3s ease;
}
.quiz-cue.is-show { opacity: 1; transform: translate(-50%, 0); }

/* ---------- GRADE ---------- */
.grade-sub { color: var(--muted); margin: 0 0 22px; font-size: 1rem; }

/* Exam-system selector: a two-up segmented control above the grade buttons.
   Quieter than the grade options so grade stays the clear first action. */
.exam-system {
  display: flex;
  gap: 10px;
  margin: 0 0 18px;
}
.exam-opt {
  flex: 1;
  min-height: 48px;
  padding: 10px 12px;
  font-family: inherit;
  font-size: 0.98rem;
  font-weight: 600;
  color: var(--muted);
  background: var(--surface);
  border: 2px solid var(--surface2);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease, color 0.15s ease;
}
.exam-opt:hover { border-color: var(--accent); color: var(--soft); }
.exam-opt.is-selected { border-color: var(--accent); background: #F0F0F0; color: var(--soft); }

.grade-options { display: flex; flex-direction: column; gap: 12px; }
/* The hidden attribute must win over the flex display above, or both the KCSE
   and GCSE option sets render at once (the bare [hidden] UA rule is too weak to
   beat a class that sets display). */
.grade-options[hidden] { display: none; }
.grade-opt { min-height: 60px; font-size: 1.05rem; justify-content: flex-start; }
.grade-free-note {
  margin-top: 20px;
  padding: 12px 14px;
  background: rgba(227, 178, 74, 0.14);
  border: 1px solid rgba(227, 178, 74, 0.4);
  border-radius: var(--radius-sm);
  color: var(--soft);
  font-size: 0.92rem;
}
.grade-free-note strong { color: var(--grade-free); }

/* ---------- SUBJECTS (optional refinement on the grade step) ----------
   No card: the subjects live on the same open page as the grade, one tier
   quieter, separated from the grade reassurance note by a hairline + air. */
.subjects {
  margin-top: 28px;
  padding-top: 26px;
  border-top: 1px solid var(--surface2);
}
.subjects-title {
  margin: 0 0 8px;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.25rem, 5vw, 1.5rem);
  letter-spacing: -0.01em;
  color: var(--soft);
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 10px;
}
.subjects-hint {
  margin: 14px 0 0;
  font-family: var(--font-num);
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--accent-ink);
}
.subjects-hint[hidden] { display: none; }
.subjects-sub { color: var(--muted); margin: 0 0 22px; font-size: 1rem; }
.subjects-selects { display: flex; flex-direction: column; gap: 12px; }
.subject-field { display: flex; flex-direction: column; gap: 6px; }
.subject-rank {
  font-family: var(--font-num);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--soft);
}
/* Matches the grade tap buttons (.option): same height, radius, 2px border and
   raised surface, so grade + subjects read as one set of controls. Text is
   centred — note native <select> value centring is honoured best-effort across
   mobile browsers (Android may keep it left). */
.subject-select {
  width: 100%;
  min-height: 60px;
  padding: 14px 40px;
  font-size: 1.05rem;
  font-weight: 500;
  font-family: inherit;
  text-align: center;
  text-align-last: center;
  color: var(--soft);
  background-color: var(--surface);
  border: 2px solid var(--surface2);
  border-radius: var(--radius);
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236B6256' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
}
.subject-select option { text-align: center; }
/* Soft-bold the dropdown category headings (Compulsory / Sciences / …) so the
   groups read as distinct from the subjects beneath them — a semi-bold, not a
   heavy 700. Native dropdown styling is honoured best-effort: desktop + most
   mobile respect optgroup weight; a few mobile browsers may ignore it. */
.subject-select optgroup { font-weight: 600; }
.subject-select:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.subject-select option:disabled { color: var(--muted); }
.grade-cta { margin-top: 20px; }
.grade-cta .btn { width: 100%; }

/* ---------- RESULTS ---------- */
.results { position: relative; z-index: 0; padding-bottom: 92px; }

/* sticky in-results jump nav — chips sit centred together, wrapping only on
   very narrow screens. */
.results-nav {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  scrollbar-width: none;
  padding: 10px 0;
  margin: 0 0 6px;
  background: var(--bg);
}
.results-nav::-webkit-scrollbar { display: none; }
.results-nav-chip {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 8px 18px;
  border-radius: 999px;
  background: var(--surface2);
  border: 1px solid #CFCFCF;
  font-family: var(--font-num);
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--soft);
  text-decoration: none;
  white-space: nowrap;
  transition: background 0.15s ease, border-color 0.15s ease, transform 0.12s ease;
}
.results-nav-chip:hover { border-color: var(--accent); background: #D4D4D4; }
.results-nav-chip:active { transform: scale(0.97); }
.results-nav-chip[hidden] { display: none; }
/* anchor targets clear the sticky nav when jumped to */
.section-h, #careers-list { scroll-margin-top: 68px; }
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
  /* results reveal — entrance-only, no loops. The HERO builds in stages so the
     NAME lands first (well under 1s), then the line, the strength chips and the
     scroll cue: the reveal settles in rather than appearing all at once. The
     mutually-exclusive reduced-motion query means none of this runs for users
     who ask for less motion — they get the final static state immediately. */
  #screen-results .results-eyebrow { animation: kp-reveal-up 0.45s both; }
  #screen-results .results-title   { animation: kp-pop-in 0.55s 0.10s cubic-bezier(0.34, 1.56, 0.64, 1) both; }
  #screen-results .results-read    { animation: kp-reveal-up 0.5s 0.40s cubic-bezier(0.22, 0.61, 0.36, 1) both; }
  #screen-results .results-chips   { animation: kp-reveal-up 0.5s 0.55s cubic-bezier(0.22, 0.61, 0.36, 1) both; }
  #screen-results .results-cue     { animation: kp-reveal-up 0.5s 0.70s cubic-bezier(0.22, 0.61, 0.36, 1) both; }
  #screen-results .share-card { animation: kp-reveal-up 0.55s 0.18s cubic-bezier(0.22, 0.61, 0.36, 1) both; }
  #screen-results .code-card { animation: kp-reveal-up 0.55s 0.05s cubic-bezier(0.22, 0.61, 0.36, 1) both; }
  #screen-results .results-code { animation: kp-pop-in 0.5s 0.22s cubic-bezier(0.34, 1.56, 0.64, 1) both; }
  #screen-results .type-read,
  #screen-results .career-card { animation: kp-reveal-up 0.5s cubic-bezier(0.22, 0.61, 0.36, 1) both; }
  #screen-results .career-card:nth-child(2) { animation-delay: 0.05s; }
  #screen-results .career-card:nth-child(3) { animation-delay: 0.10s; }
  #screen-results .career-card:nth-child(4) { animation-delay: 0.15s; }
  #screen-results .career-card:nth-child(5) { animation-delay: 0.20s; }
}
@keyframes kp-reveal-up {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}
@keyframes kp-pop-in {
  from { opacity: 0; transform: scale(0.84); }
  to { opacity: 1; transform: scale(1); }
}
/* faint topographic contour wash — concept texture, never competes with content */
.results::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='480'%20height='480'%3E%3Cg%20fill='none'%20stroke='%2333302A'%20stroke-width='1.4'%3E%3Ccircle%20cx='150'%20cy='160'%20r='40'/%3E%3Ccircle%20cx='150'%20cy='160'%20r='80'/%3E%3Ccircle%20cx='150'%20cy='160'%20r='120'/%3E%3Ccircle%20cx='150'%20cy='160'%20r='160'/%3E%3Ccircle%20cx='360'%20cy='350'%20r='40'/%3E%3Ccircle%20cx='360'%20cy='350'%20r='80'/%3E%3Ccircle%20cx='360'%20cy='350'%20r='120'/%3E%3C/g%3E%3C/svg%3E");
  background-size: 460px 460px;
  background-repeat: repeat;
  opacity: 0.05;
  z-index: 0;
  pointer-events: none;
}
.results > * { position: relative; z-index: 1; }
/* identity-first hero — the persona (tribe) is the headline AND the only thing
   in the first viewport (the reveal "aha"). svh keeps it stable against the
   mobile URL bar; we subtract a header+padding budget so a padded <main> can't
   force a scrollbar. vh first as a fallback for engines without svh. */
.results-hero {
  text-align: center;
  margin: 0 0 18px;
  min-height: calc(100vh - 150px);
  min-height: calc(100svh - 150px);
  display: flex;
  flex-direction: column;
}
/* two margin-top:auto split the free space above the content and between the
   content and the cue — so the reveal is centred and the cue sits at the bottom. */
.results-hero-main { margin-top: auto; }
.results-cue { margin-top: auto; align-self: center; }
.results-eyebrow {
  display: inline-block;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  font-size: 0.66rem;
  font-weight: 700;
  color: var(--accent-ink);
  background: rgba(228, 0, 43, 0.10);
  border: 1px solid rgba(228, 0, 43, 0.22);
  border-radius: 999px;
  padding: 5px 12px;
  margin: 0 0 14px;
}
.results-persona-wrap { position: relative; }
/* soft butter glow behind the persona, echoing the brand grade-free hue */
.results-persona-wrap::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 80%;
  height: 150%;
  transform: translate(-50%, -50%);
  background: radial-gradient(closest-side, rgba(227, 178, 74, 0.30), rgba(227, 178, 74, 0) 70%);
  z-index: -1;
  pointer-events: none;
}
.results-title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(2rem, 9vw, 3rem);
  line-height: 1.04;
  letter-spacing: -0.01em;
  color: var(--soft);
  margin: 0;
}
.results-read {
  max-width: 30rem;
  margin: 12px auto 0;
  color: var(--soft);
  font-size: 1rem;
  line-height: 1.5;
}
/* her blend in plain English — strength chips, no jargon, no numbers */
.results-chips {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  max-width: 26rem;
  margin: 18px auto 0;
}
.results-chip {
  display: inline-flex;
  align-items: center;
  padding: 6px 14px;
  border-radius: 999px;
  background: var(--surface);
  border: 1px solid var(--surface2);
  font-family: var(--font-num);
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--soft);
}
/* quiet downward scroll cue — jumps to the matches, also signals "more below" */
.results-cue {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 10px 12px 0;
  color: var(--muted);
  text-decoration: none;
  font-family: var(--font-num);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.04em;
}
.results-cue:hover { color: var(--accent-ink); }
.results-cue-ico { display: inline-flex; }
.results-cue-ico svg { width: 22px; height: 22px; }

/* the code card — RIASEC "fingerprint" with ranked bars */
.code-card {
  background: var(--surface);
  border: 1px solid var(--surface2);
  border-radius: var(--radius);
  padding: 18px;
}
.code-card-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
}
.code-card-id { min-width: 0; }
.code-card-label {
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: 0.62rem;
  font-weight: 700;
  color: var(--muted);
  margin: 0 0 3px;
}
.results-code {
  font-family: var(--font-num);
  font-weight: 700;
  font-size: 2.2rem;
  line-height: 1;
  letter-spacing: 0.08em;
  /* neutral fallback only — each letter carries its own RIASEC colour inline */
  color: var(--soft);
  margin: 0;
}
.results-code-full {
  font-size: 0.82rem;
  color: var(--muted);
  text-align: right;
  line-height: 1.35;
  max-width: 48%;
  margin: 0;
}

/* grade context callout — honest, always-true grade-free guarantee */
.grade-callout {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 14px 0 0;
  padding: 12px 14px;
  background: rgba(227, 178, 74, 0.12);
  border: 1px solid rgba(227, 178, 74, 0.45);
  border-radius: var(--radius-sm);
}
.grade-callout[hidden] { display: none; }
.gc-grade {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 40px;
  height: 40px;
  padding: 0 10px;
  background: var(--grade-free);
  color: #0A0A0A;
  font-family: var(--font-num);
  font-weight: 700;
  font-size: 1.05rem;
  border-radius: 12px;
}
.gc-note { margin: 0; font-size: 0.84rem; line-height: 1.45; color: var(--soft); }
.gc-note strong { color: #8A671F; }
/* (① station marker) Every results section title reads as a confident wayfinding
   marker, not quiet body copy: a soft red-tinted icon badge, heavier/larger
   Archivo Black type, generous air above, and a short bold red underline tick
   under the words in place of the old timid full-width grey hairline. */
.section-h {
  position: relative;
  font-family: var(--font-display);
  font-weight: 900;
  font-size: 1.34rem;
  letter-spacing: -0.01em;
  margin: 46px 0 16px;
  padding-bottom: 16px;
  display: flex;
  align-items: center;
  gap: 12px;
}
.sh-ico {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 11px;
  background: rgba(228, 0, 43, 0.10);
  border: 1px solid rgba(228, 0, 43, 0.20);
  color: var(--accent);
}
.sh-ico svg { width: 21px; height: 21px; }
.sh-txt { position: relative; min-width: 0; }
.sh-txt::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -13px;
  width: 38px;
  height: 3px;
  border-radius: 2px;
  background: var(--accent);
}

/* (③ marquee) The single most important heading stands apart — a solid black
   band with a white title and a solid-red icon chip — so the eye lands on the
   ranked matches first. Scoped to this one heading only; every other section
   keeps the lighter station marker above. */
#paths-h {
  margin-top: 46px;
  padding: 15px 18px;
  border-radius: var(--radius-sm);
  background: var(--soft);
  color: #fff;
  box-shadow: 0 10px 26px rgba(10, 10, 10, 0.18);
}
#paths-h .sh-ico {
  background: var(--accent);
  border-color: transparent;
  color: #fff;
}
#paths-h .sh-txt::after { display: none; }
/* per-type inline icon next to each RIASEC letter in the top-types list */
.type-ico { display: inline-flex; vertical-align: -0.18em; margin-right: 6px; }
.type-ico svg { width: 20px; height: 20px; }

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

/* ranked RIASEC fingerprint bars */
.riasec-bars { display: flex; flex-direction: column; gap: 12px; }
.bar-row { display: grid; gap: 5px; }
.bar-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
}
.bar-label { font-weight: 700; font-size: 0.9rem; color: var(--soft); }
.bar-score {
  font-family: var(--font-num);
  font-weight: 700;
  font-size: 0.85rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.bar-track {
  height: 10px;
  background: var(--surface2);
  border-radius: 999px;
  overflow: hidden;
}
.bar-fill {
  display: block;
  height: 100%;
  border-radius: 999px;
  transform-origin: left center;
  animation: barGrow 0.85s cubic-bezier(0.16, 1, 0.3, 1) both;
  animation-delay: calc(var(--bar-i, 0) * 70ms);
}
@keyframes barGrow { from { transform: scaleX(0); } to { transform: scaleX(1); } }
.code-card-foot { font-size: 0.74rem; color: var(--muted); margin: 14px 0 0; text-align: center; }
.ccf-plain { margin: 0; }
.ccf-method { margin: 6px 0 0; font-size: 0.72rem; }
.ccf-method > summary {
  cursor: pointer;
  color: var(--soft);
  text-decoration: underline;
  text-underline-offset: 2px;
  list-style: none;
  display: inline-block;
}
.ccf-method > summary::-webkit-details-marker { display: none; }
.ccf-method[open] > summary { margin-bottom: 4px; }
.ccf-method p { margin: 0; color: var(--muted); line-height: 1.45; }
.ccf-method .riasec-bars { text-align: left; margin: 12px 0 8px; }
.ccf-method .ccf-explain { margin-top: 8px; }

/* relative-emphasis rows — the code as "dominant / strong / present", NOT a
   grade. AA-safe: name in solid --soft, rank in solid --muted. The RIASEC colour
   is carried on the badge BORDER (a non-text accent, set inline as --emph-c) so
   the letter glyph itself stays solid --soft and clears 4.5:1 on cream — the
   raw RIASEC hues fail as text. No opacity on text. */
.code-emphasis { display: flex; flex-direction: column; gap: 8px; margin: 0 0 2px; }
.emph-row { display: flex; align-items: center; gap: 10px; }
/* (v4.0) Honest ties: exactly-tied letters share ONE slot — the chips sit
   side by side inside .emph-letters instead of faking separate ranks. */
.emph-letters { display: inline-flex; gap: 4px; flex: 0 0 auto; }
/* (v4.0) The small honesty note under the at-a-glance rows (exact-tie and/or
   widened-pool line). Hidden unless filled — keep the [hidden] guard so a
   display rule can never resurrect it (see hidden-attr gotcha). */
.tie-note {
  margin: 10px 2px 0;
  font-size: 0.82rem;
  line-height: 1.45;
  color: var(--muted);
}
.tie-note[hidden] { display: none; }
.emph-letter {
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  background: var(--bg);
  border: 2px solid var(--emph-c, var(--surface2));
  color: var(--soft);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 0.95rem;
}
.emph-name { flex: 1 1 auto; min-width: 0; color: var(--soft); font-weight: 600; font-size: 0.95rem; }
.emph-rank {
  flex: 0 0 auto;
  font-family: var(--font-num);
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
}
/* subtle attribution so an ad-hoc screenshot of the card still reads as ours */
.code-card-mark {
  margin: 10px 0 0;
  text-align: center;
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  color: var(--muted);
  opacity: 0.7;
}
/* de-emphasise the interest rows whose letter is not part of the code: carry the
   fade on the bar fill, and drop the label from primary ink (--soft) to the
   secondary ink (--muted, >=5:1 on cream). No opacity on text — the score + gloss
   are already --muted — so nothing fails contrast. */
.bar-row.is-muted .bar-fill { opacity: 0.35; }
.bar-row.is-muted .bar-label { color: var(--muted); }
/* short everyday gloss beside each interest name (Hands-on, Figure-it-out, …) */
.bar-gloss { font-weight: 600; font-size: 0.78rem; color: var(--muted); }

/* top types */
.top-types { display: flex; flex-direction: column; gap: 12px; }
.type-read {
  background: var(--surface);
  border: 1px solid var(--surface2);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm);
  padding: 14px 16px;
}
.type-read .type-name {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.05rem;
  letter-spacing: -0.005em;
  margin: 0 0 4px;
}
.type-read .type-name .type-letter { color: var(--accent); }
.type-read .type-tag { color: var(--accent-ink); font-weight: 600; }
.type-read p { margin: 0; color: var(--soft); font-size: 0.95rem; }

.banner-knbs {
  background: var(--surface2);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  font-size: 0.85rem;
  color: var(--soft);
  margin-bottom: 16px;
}

/* careers */
.careers-list { display: flex; flex-direction: column; gap: 18px; }
.career-card {
  background: var(--surface);
  border: 2px solid #CFCFCF;
  border-radius: var(--radius);
  padding: 16px;
}
.career-card.is-grade-free {
  border-color: rgba(227, 178, 74, 0.75);
  background: rgba(227, 178, 74, 0.08);
}
.career-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 4px;
}
.career-rank {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 999px;
  background: rgba(228, 0, 43, 0.12);
  color: var(--accent-ink);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 0.95rem;
}
.career-name {
  font-weight: 700;
  font-size: 1.1rem;
  margin: 0;
  flex: 1;
}
.career-do { color: var(--muted); font-size: 0.92rem; margin: 0 0 12px; }
.career-boss { margin: 0 0 12px; font-size: 0.82rem; font-weight: 700; color: var(--accent-ink); }
.career-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.tag {
  font-family: var(--font-num);
  font-size: 0.72rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 5px 11px;
  border-radius: 999px;
  border: 1.5px solid transparent;
  line-height: 1.1;
}
/* Self-describing meta chip rendered as a TWO-TONE segmented pill: a quiet,
   always-neutral key zone (Path / Market / Work / AI) butted against a bold,
   semantically-coloured value zone. Colour is reserved for the value so the
   answer reads first; the key is metadata, not a competing signal. The pill
   border carries the hue; the value fill + ink carry the meaning. */
.tag-meta {
  display: inline-flex;
  align-items: stretch;
  text-transform: none;
  padding: 0;
  overflow: hidden;
  background: transparent;
}
.tag-k {
  display: inline-flex;
  align-items: center;
  text-transform: uppercase;
  font-size: 0.55rem;
  font-weight: 600;
  letter-spacing: 0.07em;
  color: #5A5A5A;
  background: #ECECEC;
  padding: 6px 9px 5px;
  border-right: 1px solid rgba(10, 10, 10, 0.045);
}
.tag-v {
  display: inline-flex;
  align-items: center;
  font-size: 0.85rem;
  font-weight: 800;
  letter-spacing: 0.004em;
  padding: 6px 11px 5px;
}
.tag-pathway { border-color: rgba(10, 10, 10, 0.16); }
.tag-pathway .tag-v { background: var(--surface2); color: var(--soft); }
/* Path is the one chip whose value zone is grey (--surface2), not a colour tint,
   so it has no colour seam against the grey key zone — give it its own darker
   key divider so its two zones read as clearly as the coloured variants'. */
.tag-pathway .tag-k { border-right-color: rgba(10, 10, 10, 0.14); }
.tag-growing { border-color: rgba(111, 154, 106, 0.55); }
.tag-growing .tag-v { background: rgba(111, 154, 106, 0.28); color: #2F5A2A; }
.tag-flat { border-color: rgba(201, 154, 63, 0.55); }
.tag-flat .tag-v { background: rgba(201, 154, 63, 0.28); color: #6E4F12; }
.tag-oversubscribed { border-color: rgba(194, 106, 87, 0.55); }
.tag-oversubscribed .tag-v { background: rgba(194, 106, 87, 0.28); color: #7A2E1E; }
.tag-style { border-color: rgba(228, 0, 43, 0.32); }
.tag-style .tag-v { background: rgba(228, 0, 43, 0.16); color: var(--accent-ink); }
/* Solid, label-less status badges keep a single fill (deliberate exception).
   They centre their own label so they sit level with the taller two-tone meta
   pills in the same wrapped row. */
.tag-grade-free,
.tag-reach { display: inline-flex; align-items: center; }
.tag-grade-free { background: var(--grade-free); color: #4A370C; border-color: rgba(138, 103, 31, 0.35); }
.tag-reach { background: rgba(123, 104, 174, 0.18); color: #4A3C7A; border-color: rgba(123, 104, 174, 0.45); }

/* Stretch ("reach") cards in the top 5: a path above the user's grade, surfaced
   honestly and clearly flagged rather than hidden. */
.career-card.is-reach { border-color: rgba(123, 104, 174, 0.45); border-style: dashed; }
.reach-flag-note {
  margin: 0 0 12px;
  font-size: 0.85rem;
  color: var(--muted);
  background: rgba(123, 104, 174, 0.10);
  border-left: 3px solid rgba(123, 104, 174, 0.45);
  padding: 8px 10px;
  border-radius: 8px;
}

/* Optional KCSE-subject signal, surfaced honestly: a positive "fits well" note
   when the learner's subjects satisfy the career's slots, or a soft heads-up
   otherwise. Mirrors the reach-flag styling; text stays solid (never faded) for
   AA contrast on the cream card. */
/* (v3.9) State-A card line: names the learner's own matched subject.
   (v4.1) Calmer treatment: regular-weight sentence with ONE bold point of
   emphasis (the subject name), so it stops competing with the bold red
   income figure below; even breathing room above and below (the 12px
   margins collapse with the tag row's 12px, matching the 12px gap down to
   the meta grid) so it floats as its own statement, not an income caption. */
.subject-build {
  margin: 12px 0;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--accent-ink);
}
.subject-build strong { font-weight: 800; }

.subject-note {
  margin: 0 0 12px;
  font-size: 0.85rem;
  padding: 8px 10px;
  border-radius: 8px;
}
.subject-note.is-fit {
  color: #2F6B3D;
  background: rgba(76, 153, 92, 0.12);
  border-left: 3px solid rgba(76, 153, 92, 0.55);
}
.subject-note.is-soft {
  color: var(--muted);
  background: rgba(0, 0, 0, 0.04);
  border-left: 3px solid var(--border, rgba(0, 0, 0, 0.18));
}

.career-meta { display: grid; gap: 8px; }
.meta-row { display: flex; gap: 8px; font-size: 0.88rem; }
.meta-label {
  flex: 0 0 78px;
  color: var(--muted);
  text-transform: uppercase;
  font-size: 0.68rem;
  letter-spacing: 0.05em;
  padding-top: 2px;
}
.meta-val { flex: 1; color: var(--soft); }
.meta-val.income {
  font-family: var(--font-num);
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}
.income-note {
  display: block;
  font-weight: 400;
  font-size: 0.72rem;
  color: var(--muted);
  margin-top: 2px;
}
/* Quiet, consistent "trust receipt" at the foot of the meta block — when the pay
   range was checked + its source confidence. Solid --muted (never opacity-faded)
   so it stays AA-legible on the cream card. */
.career-receipt {
  margin: 10px 0 0;
  font-size: 0.74rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.abroad-note {
  margin: 10px 0 0;
  font-size: 0.78rem;
  color: var(--muted);
  border-top: 1px dashed var(--surface2);
  padding-top: 8px;
}

/* per-career "Where to start" call-to-action — one real on-ramp link */
.career-start {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 12px;
  margin-top: 12px;
  min-height: 48px;
  padding: 11px 14px;
  background: rgba(228, 0, 43, 0.08);
  border: 1px solid rgba(228, 0, 43, 0.35);
  border-radius: var(--radius-sm);
  text-decoration: none;
  transition: background 0.15s ease, border-color 0.15s ease, transform 0.12s ease;
}
.career-start:hover {
  background: rgba(228, 0, 43, 0.14);
  border-color: var(--accent);
  transform: translateY(-1px);
}
.career-start:active { transform: scale(0.99); }
.cs-icon {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 999px;
  background: var(--accent);
  color: var(--surface);
}
.cs-icon svg { width: 17px; height: 17px; display: block; }
.cs-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cs-label {
  text-transform: uppercase;
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  font-weight: 700;
  color: var(--accent-ink);
}
.cs-name { color: var(--accent); font-weight: 800; font-size: 0.95rem; }
.cs-arrow { font-weight: 800; }
.cs-desc { color: var(--muted); font-size: 0.8rem; }

/* optional "later, once qualified: register with ..." secondary note —
   only shown on careers that genuinely need professional registration */
.career-licence {
  margin: 8px 2px 0;
  font-size: 0.8rem;
  line-height: 1.4;
  color: var(--muted);
}
.career-licence .cl-label {
  text-transform: uppercase;
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  font-weight: 700;
  color: var(--accent-ink);
  margin-right: 4px;
}
.career-licence .cl-link {
  color: var(--soft);
  font-weight: 600;
  text-decoration: underline;
  text-decoration-color: rgba(228, 0, 43, 0.45);
  text-underline-offset: 2px;
}
.career-licence .cl-link:hover { color: var(--accent); }

/* per-career "Why this path?" disclosure */
.why-chosen {
  margin: 12px 0 0;
  border-top: 1px dashed var(--surface2);
  padding-top: 10px;
}
.why-chosen > summary {
  cursor: pointer;
  list-style: none;
  font-weight: 700;
  font-size: 0.84rem;
  color: var(--accent-ink);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;
}
.why-chosen > summary::-webkit-details-marker { display: none; }
.why-chosen > summary::before {
  content: "▸";
  font-size: 0.7rem;
  transition: transform 0.15s ease;
}
.why-chosen[open] > summary::before { transform: rotate(90deg); }
.why-chosen > summary:hover { color: var(--accent-ink); }
.why-list {
  margin: 8px 0 0;
  padding: 0 0 0 18px;
  display: grid;
  gap: 6px;
}
.why-list li {
  font-size: 0.84rem;
  color: var(--muted);
  line-height: 1.45;
}

/* results-wide "How were these chosen?" disclosure */
.how-chosen {
  margin: 16px 0 0;
  background: var(--surface);
  border: 1px solid var(--surface2);
  border-radius: var(--radius-sm);
  padding: 4px 16px;
}
.how-chosen-summary {
  cursor: pointer;
  list-style: none;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1rem;
  color: var(--soft);
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 48px;
}
.how-chosen-summary::-webkit-details-marker { display: none; }
.how-chosen-summary::before {
  content: "▸";
  font-size: 0.8rem;
  color: var(--accent-ink);
  transition: transform 0.15s ease;
}
.how-chosen[open] .how-chosen-summary::before { transform: rotate(90deg); }
.how-chosen-body { padding: 4px 0 16px; }
.how-chosen-body > p { font-size: 0.9rem; color: var(--soft); margin: 0 0 12px; }
.how-steps {
  margin: 0 0 12px;
  padding: 0 0 0 20px;
  display: grid;
  gap: 10px;
}
.how-steps li { font-size: 0.88rem; color: var(--muted); line-height: 1.5; }
.how-steps strong { color: var(--soft); }
.how-note { font-size: 0.85rem; color: var(--muted); margin: 0; }

/* within reach — the honest "level up" LADDER (clearly NOT qualified results) */
.reach {
  margin-top: 22px;
  padding: 16px 18px 18px;
  background: rgba(227, 178, 74, 0.10);
  border: 1px dashed rgba(227, 178, 74, 0.6);
  border-radius: var(--radius-sm);
}
.reach[hidden] { display: none; } /* the hidden attr must beat the block above */
/* the reach heading sits inside its own gold-dashed box, so it only drops the
   big top margin — it keeps the shared station-marker badge + red tick above
   (the old gold flex-line underline is retired to avoid a double underline). */
.reach .section-h { margin-top: 0; }
.reach-intro { font-size: 0.9rem; color: var(--soft); margin: 0 0 10px; }
.reach-intro em { font-style: normal; font-weight: 700; color: var(--accent-ink); }
.reach-bridge {
  font-size: 0.9rem;
  color: var(--soft);
  line-height: 1.5;
  background: var(--surface);
  border-left: 3px solid var(--grade-free);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  margin: 0 0 14px;
}
.reach-list { display: flex; flex-direction: column; gap: 10px; }
.reach-card {
  background: var(--surface);
  border: 1px solid var(--surface2);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
}
.reach-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 4px;
}
.reach-name { font-weight: 700; font-size: 1rem; margin: 0; }
.reach-need {
  flex: 0 0 auto;
  font-size: 0.64rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 3px 9px;
  border-radius: 99px;
  background: var(--grade-free);
  color: #0A0A0A;
  white-space: nowrap;
}
.reach-do { color: var(--muted); font-size: 0.88rem; line-height: 1.45; margin: 0; }
.reach-foot { font-size: 0.76rem; color: var(--muted); font-style: italic; margin: 12px 0 0; }

/* worth a look — the EXPLORATION lane (a TYPE stretch). Uses the terracotta
   accent so it reads as distinct from BOTH the ranked five and the yellow
   level-up ladder above it. */
.explore {
  margin-top: 22px;
  padding: 16px 18px 18px;
  background: rgba(228, 0, 43, 0.08);
  border: 1px dashed rgba(228, 0, 43, 0.55);
  border-radius: var(--radius-sm);
}
.explore[hidden] { display: none; } /* the hidden attr must beat the block above */
.explore .section-h { margin-top: 0; }
.explore-intro { font-size: 0.9rem; color: var(--soft); margin: 0 0 12px; }
.explore-intro em { font-style: normal; font-weight: 700; color: var(--accent-ink); }
.explore-intro strong { color: var(--accent-ink); }
.explore-list { display: flex; flex-direction: column; gap: 10px; }
.explore-card {
  background: var(--surface);
  border: 1px solid var(--surface2);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
}
.explore-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 4px;
}
.explore-name { font-weight: 700; font-size: 1rem; margin: 0; }
.explore-tag {
  flex: 0 0 auto;
  font-size: 0.64rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 3px 9px;
  border-radius: 99px;
  background: rgba(228, 0, 43, 0.14);
  color: var(--accent-ink);
  white-space: nowrap;
}
.explore-do { color: var(--muted); font-size: 0.88rem; line-height: 1.45; margin: 0; }
.explore-foot { font-size: 0.76rem; color: var(--muted); font-style: italic; margin: 12px 0 0; }

/* "Run your own business" — the per-career ENTERPRISING companion expander.
   Plum accent (the Enterprising type colour) sets it apart from the rest of the
   card. Sits inside each ranked-five career card; shown only for an Enterprising
   top-two learner. Leads with WHY, then names a business. */
.business-rec {
  margin-top: 10px;
  border-top: 1px solid var(--surface2);
  padding-top: 10px;
}
.business-rec > summary {
  cursor: pointer;
  list-style: none;
  font-size: 0.82rem;
  font-weight: 700;
  color: #6E3468;
  display: inline-flex;
  align-items: center;
  gap: 7px;
}
.business-rec > summary::-webkit-details-marker { display: none; }
.business-rec > summary::after {
  content: "";
  width: 0;
  height: 0;
  margin-left: 2px;
  border-left: 5px solid currentColor;
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  transition: transform 0.15s ease;
}
.business-rec[open] > summary::after { transform: rotate(90deg); }
.br-ico {
  display: inline-flex;
  width: 16px;
  height: 16px;
  color: #8E4585;
}
.br-ico svg { width: 100%; height: 100%; }
.business-rec-body {
  margin-top: 8px;
  padding: 10px 12px;
  background: rgba(142, 69, 133, 0.07);
  border-left: 3px solid #8E4585;
  border-radius: var(--radius-sm);
}
.br-why {
  font-size: 0.88rem;
  color: var(--ink);
  line-height: 1.5;
  margin: 0;
}
.br-why strong { color: #8E4585; font-weight: 700; }
.br-what {
  font-size: 0.9rem;
  color: var(--ink);
  line-height: 1.5;
  margin: 8px 0 0;
}
.br-label {
  display: inline-block;
  font-size: 0.6rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 2px 8px;
  border-radius: 99px;
  margin-right: 6px;
  background: rgba(142, 69, 133, 0.14);
  color: #6E3468;
  white-space: nowrap;
}

/* honesty */
.honesty {
  color: var(--muted);
  font-size: 0.92rem;
  background: var(--surface);
  border: 1px dashed var(--surface2);
  border-radius: var(--radius-sm);
  padding: 16px;
}
.honesty strong { color: var(--soft); }

/* where to look next */
.look-next { margin-top: 22px; }
.look-next-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.look-next-list a {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-height: 48px;
  justify-content: center;
  padding: 10px 14px;
  background: var(--surface);
  border: 1px solid var(--surface2);
  border-radius: var(--radius-sm);
  text-decoration: none;
  transition: border-color 0.15s ease, transform 0.12s ease;
}
.look-next-list a:hover { border-color: var(--accent2); transform: translateY(-1px); }
.look-next-list a:active { transform: scale(0.99); }
.ln-name { color: var(--soft); font-weight: 700; font-size: 0.95rem; }
.ln-desc { color: var(--muted); font-size: 0.8rem; }
.links-note { color: var(--muted); font-size: 0.76rem; margin: 10px 0 0; }

/* share card — persona-forward "flex" */
.share-card {
  margin: 4px 0 16px;
  border-radius: var(--radius);
  background: linear-gradient(150deg, #FFFFFF, #F0F0F0 60%);
  border: 1px solid var(--accent);
  overflow: hidden;
}
.share-card-inner { padding: 24px 20px; text-align: center; }
.share-wordmark {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.35rem;
  letter-spacing: 0.06em;
}
.share-eyebrow {
  display: block;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  font-size: 0.66rem;
  font-weight: 700;
  color: var(--muted);
  margin: 14px 0 8px;
}
.share-persona {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.9rem, 8.5vw, 2.7rem);
  line-height: 1.03;
  letter-spacing: -0.01em;
  color: var(--soft);
  margin: 0 0 10px;
}
.share-code {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: 0.05em;
  color: var(--accent-ink);
  margin: 0 0 12px;
}
.share-read { color: var(--soft); font-size: 0.96rem; line-height: 1.45; margin: 0 0 16px; }
.share-blend {
  display: flex;
  gap: 3px;
  height: 14px;
  max-width: 320px;
  margin: 0 auto 8px;
}
.blend-seg { border-radius: 3px; min-width: 4px; }
.share-blend-cap {
  display: block;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: 0.6rem;
  color: var(--muted);
  margin: 0 0 18px;
}
.share-top-career {
  background: rgba(10,10,10,0.04);
  border-radius: var(--radius-sm);
  padding: 14px 12px;
  margin-bottom: 16px;
}
.share-label {
  text-transform: uppercase;
  font-size: 0.64rem;
  letter-spacing: 0.1em;
  color: var(--accent-ink);
  font-weight: 700;
}
.share-career { font-weight: 800; font-size: 1.1rem; margin: 4px 0 0; color: var(--soft); }
.share-income { color: var(--accent-ink); font-weight: 700; font-size: 0.98rem; margin: 6px 0 0; }
.share-income-note { color: var(--muted); font-size: 0.72rem; margin: 4px 0 0; }
.share-income[hidden], .share-income-note[hidden] { display: none; }
.share-disclaimer {
  color: var(--muted);
  font-size: 0.74rem;
  font-style: italic;
  line-height: 1.4;
  margin: 0 0 14px;
}
.share-url { color: var(--accent-ink); font-weight: 700; font-size: 0.9rem; letter-spacing: 0.02em; }

/* sticky bottom action bar — the share + save actions stay one tap away no
   matter how far the learner has scrolled through their results. */
.results-actions {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 50;
  display: flex;
  flex-direction: row;
  gap: 10px;
  width: 100%;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 10px 16px calc(10px + env(safe-area-inset-bottom, 0px));
  background: var(--surface);
  border-top: 1px solid var(--surface2);
  box-shadow: 0 -6px 20px rgba(10, 10, 10, 0.10);
  /* lets the iOS-only save hint wrap onto its own full-width line; the two
     buttons themselves (flex: 1 1 0, min-width: 0) never wrap. */
  flex-wrap: wrap;
}
/* iOS-only "print preview → share icon → Save to Files" line under the
   Download buttons (revealed by app.js on iPhone/iPad only). The [hidden]
   guard keeps the hidden attribute working despite the display rules here. */
.pdf-ios-hint {
  flex: 1 1 100%;
  margin: 0;
  color: var(--muted);
  font-size: 0.78rem;
  line-height: 1.4;
  text-align: center;
}
.shared-banner .pdf-ios-hint { margin: 8px 0 0; }
.pdf-ios-hint[hidden] { display: none; }
.btn-action {
  position: relative;
  overflow: hidden;
  flex: 1 1 0;
  min-width: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 12px;
  font-size: 0.95rem;
  min-height: 48px;
}
.btn-action span { min-width: 0; }
.btn-action .btn-ico { width: 20px; height: 20px; flex: 0 0 auto; }
.btn-action-primary { background: var(--soft); color: var(--bg); }
.btn-action-primary:hover { background: #2A2A2A; }

/* (soft jazz) A slow specular sheen sweeps each CTA in turn — never both at once,
   with long rests between, so the action bar feels gently alive without nagging.
   The black primary glints in KAZIPOA red; the WhatsApp button glints soft white.
   call-and-response: the whatsapp sheen answers half a cycle after the primary.
   Frozen for reduced-motion in the block at the foot of this file. */
.btn-action::after {
  content: "";
  position: absolute;
  top: -10%;
  bottom: -10%;
  left: 0;
  width: 45%;
  pointer-events: none;
  transform: translateX(-160%) skewX(-18deg);
  background: linear-gradient(100deg, transparent 0%, rgba(255, 255, 255, 0.38) 50%, transparent 100%);
  animation: btn-sheen 10s ease-in-out infinite;
}
.btn-action-primary::after {
  background: linear-gradient(100deg, transparent 0%, rgba(228, 0, 43, 0.50) 50%, transparent 100%);
}
.btn-whatsapp::after {
  background: linear-gradient(100deg, transparent 0%, rgba(255, 255, 255, 0.48) 50%, transparent 100%);
  animation-delay: -5s;
}
@keyframes btn-sheen {
  0%   { transform: translateX(-160%) skewX(-18deg); opacity: 0; }
  3%   { opacity: 1; }
  20%  { opacity: 1; }
  23%  { transform: translateX(240%) skewX(-18deg); opacity: 0; }
  100% { transform: translateX(240%) skewX(-18deg); opacity: 0; }
}

/* shared-result banner — a friend's card on the hero, framed to funnel the
   visitor into taking their own test */
.shared-banner {
  margin: 4px 0 24px;
  padding: 20px 18px;
  text-align: center;
  background: linear-gradient(150deg, #FFFFFF, #F0F0F0 60%);
  border: 1px solid var(--accent);
  border-radius: var(--radius);
}
.shared-banner[hidden] { display: none; }
.shared-eyebrow {
  display: block;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  font-size: 0.66rem;
  font-weight: 700;
  color: var(--muted);
  margin: 0 0 8px;
}
.shared-persona {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.6rem, 7vw, 2.2rem);
  line-height: 1.05;
  color: var(--soft);
  margin: 0 0 6px;
}
.shared-code {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.98rem;
  letter-spacing: 0.05em;
  color: var(--accent-ink);
  margin: 0 0 10px;
}
.shared-read { color: var(--soft); font-size: 0.92rem; line-height: 1.45; margin: 0 0 14px; }
.shared-blend {
  display: flex;
  gap: 3px;
  height: 12px;
  max-width: 300px;
  margin: 0 auto 14px;
}
.shared-path { color: var(--soft); font-size: 0.9rem; font-weight: 700; margin: 0 0 12px; }
.shared-cta { color: var(--muted); font-size: 0.9rem; margin: 0; }
.shared-cta em { color: var(--accent-ink); font-style: normal; font-weight: 700; }
/* Soft grey panel holding the share nudge + peer line. Echoes the share card's
   radius and tone so it reads as a gentle extension of the card above. */
.share-nudge-card {
  margin: 14px 0 0;
  padding: 16px 18px;
  border-radius: var(--radius);
  background: #ECECEC;
  border: 1px solid var(--surface2);
}
.share-nudge {
  text-align: center;
  font-size: 0.84rem;
  color: var(--muted);
  margin: 0;
}

.delete-link-wrap { text-align: center; margin: 14px 0 0; }
.delete-link-note {
  color: var(--muted);
  font-size: 0.76rem;
  margin: 4px 0 0;
}
.delete-link-status {
  text-align: center;
  font-size: 0.84rem;
  font-weight: 700;
  color: var(--soft);
  margin: 12px 0 0;
}

/* Start over — a clear but secondary outlined control: more visible than a bare
   text link (it was muted grey and easy to miss), still quieter than the filled
   Download / WhatsApp CTAs below it. */
.restart-link {
  display: block;
  width: fit-content;
  margin: 24px auto 0;
  text-align: center;
  color: var(--soft);
  background: var(--surface);
  border: 1.5px solid var(--surface2);
  border-radius: var(--radius-sm);
  padding: 11px 26px;
}
.restart-link:hover { border-color: var(--soft); text-decoration: none; }
.shared-pdf-btn { margin-top: 14px; }

/* ============================================================
   Report v2.1 — identity header, ranked/safety split, AI badge +
   income-confidence dot, the hustle path + hero close.
   Brand uses the bold palette (the :root tokens: off-white / black / red).
   ============================================================ */

/* (07) Identity header — colour-coded code promoted into the hero, code spelled
   out, and the grade band, all centred under the name. */
.results-identity-code {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  margin: 16px auto 0;
}
.results-code-hero {
  font-size: clamp(2.4rem, 12vw, 3.2rem);
  letter-spacing: 0.1em;
  text-align: center;
}
.results-code-full-hero {
  /* override the code-card variant's right-aligned, 48%-clamped layout */
  max-width: none;
  text-align: center;
  font-size: 0.9rem;
}
.identity-grade {
  margin: 14px auto 0;
  display: inline-block;
  padding: 5px 14px;
  border-radius: 999px;
  background: rgba(228, 0, 43, 0.10);
  border: 1px solid rgba(228, 0, 43, 0.45);
  font-family: var(--font-num);
  font-size: 0.78rem;
  font-weight: 700;
  color: #B80022;
}

/* The ranked-list sub-line under the "best-fit paths" heading. */
.ranked-sub {
  margin: -6px 0 14px;
  font-size: 0.9rem;
  color: var(--muted);
}
.ranked-sub[hidden] { display: none; }

/* (v3.8) THE one top-of-results message slot — at most one message ever shows
   here (subjects-gap today; later runs reuse this same slot). Quiet card, red
   ink edge — kind, not an alarm. */
.results-msg {
  margin: 0 0 14px;
  padding: 12px 14px;
  background: var(--paper-2, #fff);
  border: 1px solid rgba(26, 26, 26, 0.14);
  border-left: 4px solid var(--accent-ink);
  font-size: 0.92rem;
  line-height: 1.55;
  color: var(--ink);
}
.results-msg[hidden] { display: none; }

/* (v3.8) guard: the section heading hides when the ranked list is empty —
   [hidden] must always win over any display the class sets. */
.section-h[hidden] { display: none; }

/* (02) AI badge tag — Low risk is the selling point (sage), Medium/High honest
   (ochre). Sits inline with the other meta tags. */
.tag-ai-low { border-color: rgba(111, 154, 106, 0.4); }
.tag-ai-low .tag-v { background: rgba(111, 154, 106, 0.16); color: #3F6B3A; }
.tag-ai-aware { border-color: rgba(201, 154, 63, 0.4); }
.tag-ai-aware .tag-v { background: rgba(201, 154, 63, 0.16); color: #8A671F; }

/* (02) Income-confidence dot — replaces the per-card "not an official salary"
   hedge. A small dot + word: amber = rough, sage = fairly sure. */
.income-conf {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-left: 8px;
  font-family: var(--font-num);
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  white-space: nowrap;
}
.conf-dot { width: 8px; height: 8px; border-radius: 999px; background: var(--muted); flex: 0 0 auto; }
.income-conf.is-sure .conf-dot { background: var(--success); }
.income-conf.is-rough .conf-dot { background: var(--warn); }

/* Safety-net card head uses a quiet check instead of a rank number. */
.safety-net[hidden] { display: none; }
.safety-net-body { margin: -4px 0 14px; font-size: 0.92rem; line-height: 1.5; color: var(--soft); }
.safety-net-list { display: grid; gap: 16px; }
.career-rank-free {
  background: rgba(111, 154, 106, 0.16);
  color: var(--success);
}
.career-rank-free svg { width: 17px; height: 17px; }

/* (03) The hustle path — one dignified block, never a fallback. */
.hustle[hidden] { display: none; }
.hustle-lead { margin: -4px 0 6px; font-size: 0.95rem; font-weight: 600; color: var(--soft); }
.hustle-body { margin: 0 0 12px; font-size: 0.88rem; line-height: 1.5; color: var(--muted); }
.hustle-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.hustle-line {
  padding: 14px 16px 14px 18px;
  background: var(--surface);
  border: 1px solid var(--surface2);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius-sm);
  font-size: 0.98rem;
  line-height: 1.5;
  font-weight: 600;
  color: var(--soft);
}
.hustle-prefix {
  display: block;
  width: fit-content;
  margin: 0 0 8px;
  padding: 3px 10px;
  background: rgba(228, 0, 43, 0.09);
  border-radius: 999px;
  font-family: var(--font-num);
  font-size: 0.62rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--accent-ink);
}
.hustle-for { color: var(--muted); font-weight: 500; }
/* The ~87% informal-work stat closes the hustle path (moved from the old frame). */
.hustle-stat {
  margin: 12px 0 0;
  padding-top: 12px;
  border-top: 1px solid var(--surface2);
  font-size: 0.84rem;
  line-height: 1.45;
  color: var(--muted);
}
.hustle-stat:empty { display: none; }

/* (09) Peer-prediction nudge sitting with the share rails. */
.share-peer {
  margin: 8px 0 0;
  text-align: center;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--muted);
}

/* (05) Hero-question close — the last thing she reads. A soft, intimate card:
   gentle gradient, hairline border + diffuse shadow, rounder corners and lighter
   display type so the emotional closer feels warm rather than loud. */
.hero-close {
  margin-top: 34px;
  padding: 34px 28px;
  text-align: center;
  background: linear-gradient(180deg, #FFFFFF 0%, #F7F7F7 100%);
  border: 1px solid rgba(10, 10, 10, 0.06);
  border-radius: 28px;
  box-shadow: 0 16px 40px rgba(10, 10, 10, 0.06);
}
.hero-close-line {
  margin: 0 auto;
  max-width: 34ch;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.18rem;
  line-height: 1.4;
  letter-spacing: -0.01em;
  color: var(--soft);
}
.hero-close-sub { margin: 16px auto 0; max-width: 34ch; font-size: 0.9rem; line-height: 1.5; color: var(--muted); }

/* ---------- print / PDF report ---------- */
/* The report container is invisible on screen; the "Download PDF" actions fill
   it on demand and call window.print(). It's a pure function of (blend, grade),
   so the document is identical from the live results OR a shared link. */
.print-report { display: none; }

@media print {
  /* Isolate the generated report: hide the live app entirely and show only the
     report, so the PDF is clean and branded no matter which screen triggered it. */
  body > *:not(#print-report) { display: none !important; }
  body::before { display: none !important; }
  body { background: #fff; color: #1a1a1a; display: block; }
  .print-report {
    display: block !important;
    max-width: 100%;
    color: #1a1a1a;
    font-family: var(--font-body);
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
  /* Section index (01, 02 …) for the numbered report headings below. */
  .pr-wrap { counter-reset: pr-sec; }
  .pr-top {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    border-bottom: 2px solid var(--accent);
    padding-bottom: 8px;
    margin-bottom: 6px;
  }
  .pr-brand {
    font-family: var(--font-display);
    font-weight: 800;
    letter-spacing: 0.06em;
    color: var(--accent);
    font-size: 1.3rem;
  }
  .pr-tagline { color: #555; font-size: 0.85rem; }
  .pr-title {
    font-family: var(--font-display);
    font-size: 2.5rem;
    font-weight: 800;
    line-height: 1.05;
    letter-spacing: -0.01em;
    margin: 8px 0 2px;
  }
  /* One deliberate signal-red word in the headline — the persona name's last
     word — so the hero pops without coloring the whole line. */
  .pr-title-hl { color: var(--accent); }
  .pr-code { font-weight: 800; letter-spacing: 0.1em; color: var(--accent); margin: 0; }
  .pr-code-full { color: #555; margin: 2px 0 0; }
  .pr-grade { font-weight: 700; margin: 6px 0 0; }
  .pr-subjects { color: #555; font-weight: 600; font-size: 0.92rem; margin: 3px 0 0; }
  .pr-section { margin-top: 18px; break-inside: avoid; page-break-inside: avoid; }
  .pr-h {
    counter-increment: pr-sec;
    font-family: var(--font-display);
    font-size: 1.25rem;
    font-weight: 800;
    margin: 0 0 10px;
  }
  /* Numbered, editorial index — red "01 — " ahead of each section title. */
  .pr-h::before {
    content: counter(pr-sec, decimal-leading-zero) "  —  ";
    color: var(--accent);
    font-weight: 800;
  }
  /* Short, thick red underline under just the heading — the single accent
     device that replaces the old full-width grey hairline. */
  .pr-h::after {
    content: "";
    display: block;
    width: 2.25rem;
    height: 3px;
    background: var(--accent);
    border-radius: 2px;
    margin-top: 6px;
  }
  .pr-sub, .pr-bridge { color: #555; font-size: 0.9rem; margin: 0 0 8px; }
  .pr-type { margin: 0 0 8px; break-inside: avoid; }
  .pr-type-name { font-weight: 800; margin: 0 0 2px; }
  .pr-type p { margin: 0; }
  .pr-career {
    border: 1px solid #ddd;
    border-radius: 8px;
    padding: 10px 12px;
    margin: 0 0 10px;
    break-inside: avoid;
    page-break-inside: avoid;
  }
  .pr-career-name { font-family: var(--font-display); font-weight: 800; margin: 0 0 4px; }
  .pr-career-do { margin: 0 0 6px; }
  .pr-meta { margin: 2px 0; font-size: 0.92rem; }
  .pr-note { color: #777; font-size: 0.82rem; }
  /* (v3.8) the one top-of-report message (subjects-gap) — quiet ruled box. */
  .pr-msg { border-left: 3px solid #B80022; padding: 6px 10px; margin: 6px 0; font-size: 0.9rem; }
  .pr-note-fit { color: #2F6B3D; font-weight: 600; }
  /* (v4.1) Mirror of the on-screen emphasis split: only the subject name
     inside the "Builds on your …" line is extra-bold. */
  .pr-note-fit strong { font-weight: 800; }
  .pr-why-h { font-weight: 700; margin: 8px 0 2px; font-size: 0.9rem; }
  .pr-why { margin: 0; padding-left: 18px; font-size: 0.88rem; color: #444; }
  .pr-kicker {
    text-transform: uppercase;
    letter-spacing: 0.14em;
    font-size: 0.7rem;
    font-weight: 700;
    color: var(--accent);
    margin: 10px 0 0;
  }
  .pr-flex { margin: 6px 0 8px; font-size: 0.96rem; }
  .pr-lead { font-weight: 700; margin: 0 0 4px; }
  .pr-hustle-line { margin: 4px 0; font-size: 0.92rem; }
  .pr-hero-close { text-align: center; }
  .pr-hero-line { font-family: var(--font-display); font-size: 1.15rem; font-weight: 800; margin: 0 0 4px; }
  .pr-foot {
    margin-top: 22px;
    border-top: 1px solid #ccc;
    padding-top: 8px;
    display: flex;
    justify-content: space-between;
    gap: 12px;
    color: #555;
    font-size: 0.82rem;
  }
  @page { margin: 16mm 14mm; }
}

/* ---------- responsive niceties ---------- */
@media (max-width: 360px) {
  .code-card-head { flex-direction: column; align-items: flex-start; gap: 6px; }
  .results-code-full { text-align: left; max-width: 100%; }
}

/* ---------- short-viewport activity clamp ----------
   The quiz's vertical rhythm is sized in dvh (see the fit block above), which
   compacts it continuously. The one thing dvh can't express is
   -webkit-line-clamp, so on genuinely short viewports (small phones in portrait,
   or landscape) cap the changing activity prompt to two lines and trim its size
   a touch, so a long prompt can't eat the room the five options need. */
@media (max-height: 620px) {
  /* keep the eyebrow gap a touch larger than the activity->options gap so the
     grouping still reads, while staying within the tight fit budget */
  #screen-quiz .quiz-q { margin-bottom: 8px; }
  #screen-quiz .activity-text {
    margin-bottom: 6px;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    font-size: clamp(1.3rem, 5.5vw, 1.7rem);
  }
}

/* ---------- reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
  /* the bar width is already final inline; drop the grow transform so a near-zero
     animation duration can't leave a delayed bar stuck at scaleX(0). */
  .bar-fill { animation: none !important; transform: none !important; }
  /* kill the CTA sheen entirely so it can't strobe at the near-zero duration. */
  .btn-action::after { animation: none !important; opacity: 0 !important; }
}
