/* Inter, served from this site. Variable across the weights the design uses,
   so one 48KB file covers 400-700 and nothing is fetched from a third party. */
@font-face {
  font-family: "Inter";
  src: url("fonts/inter-latin.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

/* Every colour in this file comes from a token below, so the dark palette at
   the bottom only has to redefine these — no rule needs a second copy. */
:root {
  color-scheme: light;
  --ink: #19201f;
  --ink-soft: #33403e;
  --muted: #63706e;
  --line: #d8dfdc;
  --paper: #fbfaf5;
  --surface: #ffffff;
  --surface-2: #fafafa;
  --teal: #146c72;

  /* Text that sits on top of an --ink or --theme fill. */
  --on-ink: #ffffff;
  --on-theme: #ffffff;

  /* Translucent whites layered over the paper. */
  --surface-veil: rgba(255, 255, 255, 0.46);

  --header-bg: rgba(251, 250, 245, 0.9);
  --header-line: rgba(25, 32, 31, 0.08);

  --backdrop: rgba(15, 23, 22, 0.58);
  --panel-edge: rgba(255, 255, 255, 0.52);

  --danger: #c0392b;
  --danger-soft: #fdf0ee;
  --danger-ink: #96271b;
  --danger-glow: rgba(192, 57, 43, 0.14);

  /* Panels deliberately inverted against the page: the result and the safety
     band. In dark mode these become raised surfaces rather than flipping. */
  --invert-bg: #19201f;
  --invert-ink: #ffffff;
  --invert-muted: rgba(255, 255, 255, 0.73);
  --invert-soft: rgba(255, 255, 255, 0.82);
  --invert-track: rgba(255, 255, 255, 0.16);
  --invert-track-2: rgba(255, 255, 255, 0.18);

  --shadow-sm: 0 12px 28px rgba(25, 32, 31, 0.08);
  --shadow-modal: 0 32px 90px rgba(0, 0, 0, 0.34);

  /* One horizontal gutter for the header, hero, sections, and footer, so every
     edge on the page lines up at every width. */
  --gutter: clamp(20px, 4vw, 56px);

  --theme: var(--teal);
  --theme-soft: #eef6f2;
  --theme-glow: rgba(20, 108, 114, 0.18);
}

body[data-active-category="personality"] {
  --theme: #6e4a7e;
  --theme-soft: #f1e9f5;
  --theme-glow: rgba(110, 74, 126, 0.2);
}

body[data-active-category="wellbeing"] {
  --theme: #24733a;
  --theme-soft: #e9f7ed;
  --theme-glow: rgba(36, 115, 58, 0.2);
}

body[data-active-category="relationships"] {
  --theme: #b04a43;
  --theme-soft: #fff0ed;
  --theme-glow: rgba(176, 74, 67, 0.22);
}

body[data-active-category="career"] {
  --theme: #1f6795;
  --theme-soft: #e7f2fa;
  --theme-glow: rgba(31, 103, 149, 0.2);
}

body[data-active-category="fun"] {
  --theme: #a94f18;
  --theme-soft: #fff1df;
  --theme-glow: rgba(169, 79, 24, 0.22);
}

* {
  box-sizing: border-box;
}

/* `display` set by any rule in this file outranks the browser's own
   `[hidden] { display: none }`, so hiding has to be stated here or panels like
   the result show through with their placeholder content. */
[hidden] {
  display: none !important;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family:
    Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
    sans-serif;
  /* Inter is the real face; never let the browser fake a weight it lacks. */
  font-synthesis: none;
  font-size: clamp(1rem, 0.97rem + 0.15vw, 1.0625rem);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

a {
  color: inherit;
  text-decoration: none;
}

button,
input {
  font: inherit;
}

.site-header {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  min-height: 72px;
  padding: 14px var(--gutter);
  border-bottom: 1px solid var(--header-line);
  background: var(--header-bg);
  backdrop-filter: blur(18px);
}

.brand,
.top-nav,
.hero-actions,
.filters,
.card-meta,
.site-footer {
  display: flex;
  align-items: center;
}

.brand {
  gap: 10px;
  font-weight: 600;
  letter-spacing: 0;
}

/* Fixed ink, not var(--theme): the logo is the one thing that must not change
   colour when the visitor filters to a different category. */
.brand-mark {
  display: grid;
  width: 30px;
  height: 30px;
  place-items: center;
  border-radius: 8px;
  background: var(--ink);
  color: var(--on-ink);
  font-size: 0.9rem;
  font-weight: 600;
}

.top-nav {
  gap: clamp(12px, 3vw, 28px);
  color: var(--muted);
  font-size: 0.94rem;
}

.top-nav a:hover {
  color: var(--ink);
}

/* A stated opening, not a full-screen splash: the library is the product, so
   the hero ends well above the fold and the cards start immediately after. */
.hero {
  position: relative;
  overflow: hidden;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(220px, 300px);
  align-items: end;
  gap: clamp(32px, 5vw, 56px);
  padding: clamp(52px, 7vw, 96px) var(--gutter) clamp(44px, 5vw, 72px);
  border-bottom: 1px solid var(--line);
}

/* Two soft colour fields drifting behind the headline. Blurred and low-opacity,
   so they read as light in the room rather than as shapes on the page. */
.hero-blob {
  position: absolute;
  z-index: 0;
  border-radius: 50%;
  filter: blur(60px);
  pointer-events: none;
}

.hero-blob-a {
  top: -140px;
  right: -60px;
  width: 420px;
  height: 420px;
  background: var(--theme-glow);
  animation: heroDrift 19s ease-in-out infinite;
}

.hero-blob-b {
  bottom: -180px;
  left: 18%;
  width: 340px;
  height: 340px;
  background: rgba(169, 79, 24, 0.16);
  animation: heroDrift 23s ease-in-out infinite reverse;
}

@keyframes heroDrift {
  0%,
  100% {
    transform: translate3d(0, 0, 0) scale(1);
  }
  50% {
    transform: translate3d(-32px, 26px, 0) scale(1.12);
  }
}

/* The headline's last phrase, marked the way you would with a highlighter.
   `box-decoration-break` keeps the swash intact when the line wraps. */
.hl {
  position: relative;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
  padding: 0 0.12em;
  border-radius: 10px 12px 11px 13px;
  background: linear-gradient(103deg, var(--theme-soft) 0%, var(--theme-glow) 100%);
  color: var(--theme);
}

.hero-content,
.hero-panel {
  position: relative;
  z-index: 1;
}

.hero-content {
  max-width: 720px;
}

.eyebrow,
.section-kicker,
.tag {
  color: var(--theme);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.eyebrow {
  display: inline-block;
  margin-bottom: 18px;
  padding: 7px 14px;
  border-radius: 999px;
  background: var(--theme-soft);
  box-shadow: inset 0 0 0 1px var(--theme-glow);
}

h1,
h2,
h3,
p {
  margin-top: 0;
}

/* Display sizes need negative tracking — at 50px, default spacing reads loose.
   The larger the size, the tighter it goes. */
h1 {
  max-width: 20ch;
  margin-bottom: 20px;
  font-size: clamp(2.375rem, 1.5rem + 3.6vw, 4.125rem);
  font-weight: 700;
  line-height: 1.04;
  letter-spacing: -0.035em;
}

h2 {
  margin-bottom: 12px;
  font-size: clamp(1.5rem, 1.2rem + 1.4vw, 2.125rem);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.022em;
}

h3 {
  margin-bottom: 8px;
  font-size: 1.0625rem;
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.012em;
}

.hero-copy {
  max-width: 58ch;
  color: var(--ink-soft);
  font-size: clamp(1.0625rem, 1rem + 0.35vw, 1.1875rem);
  line-height: 1.55;
}

.hero-actions {
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 28px;
}

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 46px;
  padding: 0 18px;
  border: 1px solid var(--ink);
  border-radius: 8px;
  cursor: pointer;
  font-weight: 600;
}

.button.primary {
  background: var(--ink);
  color: var(--on-ink);
}

.button.secondary {
  background: var(--surface-veil);
  color: inherit;
  border-color: var(--ink);
}

/* One bordered block with divided rows, rather than three floating cards —
   fewer edges on the page reads calmer. */
.hero-panel {
  align-self: end;
  display: grid;
  max-width: 320px;
  gap: 10px;
}

/* Three tiles rather than one bordered list: the numbers are the point, so
   they get the colour and the size. */
.hero-panel div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 18px;
  padding: 14px 18px;
  border-radius: 14px;
  background: var(--surface);
  box-shadow:
    inset 0 0 0 1px var(--theme-glow),
    var(--shadow-sm);
}

.metric {
  color: var(--theme);
  font-size: 1.875rem;
  font-weight: 700;
  letter-spacing: -0.03em;
}

.label {
  font-size: 0.875rem;
}

.label,
.test-card p,
.intro p,
.quiz-copy p,
.method-note,
.safety p,
.site-footer {
  color: var(--muted);
}

.method-note {
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface-2);
  font-size: 0.9375rem;
  line-height: 1.5;
}

.test-status {
  display: inline-flex;
  width: fit-content;
  margin-bottom: 14px;
  padding: 7px 10px;
  border-radius: 999px;
  background: var(--theme);
  color: var(--on-theme);
  font-size: 0.82rem;
  font-weight: 700;
}

.section {
  padding: clamp(54px, 8vw, 96px) var(--gutter);
}

.intro,
.section-heading,
.quiz-section {
  display: grid;
  grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
  gap: clamp(24px, 5vw, 64px);
}

.intro {
  border-bottom: 1px solid var(--line);
}

.section-heading {
  align-items: end;
  margin-bottom: 26px;
}

.filters {
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: 8px;
}

/* 44px is the smallest comfortable touch target; the chips used to be 38. */
.filter {
  min-height: 44px;
  padding: 0 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--muted);
  cursor: pointer;
  font-size: 0.9375rem;
}

.filter.active {
  border-color: var(--theme);
  background: var(--theme);
  color: var(--on-theme);
}

.filter[data-filter="personality"] {
  border-color: rgba(110, 74, 126, 0.28);
}

.filter[data-filter="wellbeing"] {
  border-color: rgba(36, 115, 58, 0.28);
}

.filter[data-filter="relationships"] {
  border-color: rgba(176, 74, 67, 0.28);
}

.filter[data-filter="career"] {
  border-color: rgba(31, 103, 149, 0.28);
}

.filter[data-filter="fun"] {
  border-color: rgba(169, 79, 24, 0.28);
}

/* auto-fill rather than a fixed column count: the grid reflows on its own from
   phone to desktop instead of needing a breakpoint per width. */
.test-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 270px), 1fr));
  gap: 18px;
}

.test-card {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 18px;
  /* The category colour is the card's own, so 58 cards read as five families
     rather than one grey field. It fades out downward, leaving the text on
     plain surface where it keeps its contrast. */
  background:
    linear-gradient(165deg, var(--theme-soft) 0%, transparent 58%),
    var(--surface);
  cursor: pointer;
  transition:
    transform 200ms cubic-bezier(0.2, 0.8, 0.3, 1),
    box-shadow 200ms ease,
    border-color 200ms ease;
}

/* The colour bar is back, but it no longer repeats the tag: the tag names the
   category in words, the bar and the tint carry it as colour, and the mark
   below belongs to this test alone. Clipped to the radius by the overflow
   above, so it follows the corners. */
.test-card::before {
  position: absolute;
  z-index: 1;
  inset: 0 0 auto 0;
  height: 6px;
  background: var(--theme);
  content: "";
}

.test-card.selected {
  border-color: var(--theme);
  box-shadow: 0 0 0 1px var(--theme);
}

.test-card[hidden] {
  display: none;
}

.tag {
  display: inline-flex;
}

.card-meta {
  justify-content: flex-start;
  gap: 8px;
  margin-top: 20px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: 0.8125rem;
}

.card-meta span + span::before {
  margin-right: 8px;
  content: "·";
}

/* Flat surface, not a tinted gradient: the test area used to wash the whole
   panel in the category colour, which changed the page's mood per test. */
.quiz-section {
  border-block: 1px solid var(--line);
  background: var(--surface);
}

/* On the homepage the quiz only ever appears inside the modal, so it stays
   hidden in the page flow. A test's own page has no modal and must show it. */
body:not([data-test-slug]) main > .quiz-section {
  display: none;
}

.test-modal[hidden] {
  display: none;
}

.test-modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  align-items: center;
  justify-items: center;
  padding: clamp(12px, 3vw, 34px);
}

.modal-backdrop {
  position: absolute;
  inset: 0;
  background: var(--backdrop);
  backdrop-filter: blur(10px);
}

.modal-panel {
  position: relative;
  z-index: 1;
  width: min(1240px, calc(100vw - 28px));
  max-height: min(88vh, 900px);
  overflow: auto;
  border: 1px solid var(--panel-edge);
  border-radius: 12px;
  background: var(--paper);
  box-shadow: var(--shadow-modal);
  animation: modalEnter 180ms ease-out;
}

.modal-panel .quiz-section {
  display: grid;
  border: 0;
  grid-template-columns: minmax(280px, 0.62fr) minmax(560px, 1.38fr);
  gap: clamp(28px, 4vw, 58px);
  padding: clamp(28px, 4vw, 54px);
  min-height: auto;
}

.modal-close {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 3;
  display: grid;
  width: 46px;
  height: 46px;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink);
  cursor: pointer;
  font-size: 1.125rem;
  font-weight: 600;
  line-height: 1;
}

body.modal-open {
  overflow: hidden;
}

@keyframes modalEnter {
  from {
    opacity: 0;
    transform: translateY(16px) scale(0.98);
  }

  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

.quiz {
  display: grid;
  /* Rows stay at their content height. The form is a grid item beside the
     description column, so it inherits that column's height — and without this
     the spare space is dealt out between the progress bar and the question,
     leaving a 150px hole in the middle of the test. */
  align-content: start;
  gap: 16px;
}

.question {
  padding: 18px;
  border: 1px solid var(--theme-glow);
  border-radius: 8px;
  background: var(--surface);
}

.question p {
  margin-bottom: 14px;
  font-weight: 600;
}

/* One question at a time -------------------------------------------------- */

/* Only applied once quiz-flow.js has taken over. Without JavaScript the class
   is never added and every question stays visible, so the form still works. */
.quiz-flow .question {
  display: none;
}

.quiz-flow .question.is-current {
  display: block;
  animation: questionIn 240ms ease-out;
}

/* The submit button is redundant in the flow: answering the last question
   submits. It stays for the no-JavaScript form. */
.quiz-flow button[type="submit"] {
  display: none;
}

@keyframes questionIn {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* No bottom margin: the bar is a row of the form's grid, so the form's own gap
   already separates it from the question below. */
.quiz-progress {
  margin-bottom: 0;
}

.quiz-progress-track {
  overflow: hidden;
  height: 6px;
  border-radius: 999px;
  background: var(--theme-soft);
}

.quiz-progress-fill {
  display: block;
  width: 0;
  height: 100%;
  border-radius: 999px;
  background: var(--theme);
  transition: width 280ms ease;
}

.quiz-progress-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 10px;
  min-height: 44px;
}

.quiz-progress-label {
  order: -1;
  margin-bottom: 0;
  margin-right: auto;
  color: var(--muted);
  font-size: 0.875rem;
  font-variant-numeric: tabular-nums;
}

.quiz-back,
.quiz-next {
  /* Sized to 44px rather than left to the text, which renders them about 34px
     tall — too small to tap reliably on a phone. `nowrap` keeps "See my result"
     on one line at 375px. */
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 6px 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--muted);
  cursor: pointer;
  font-size: 0.875rem;
  white-space: nowrap;
}

.quiz-next {
  border-color: var(--theme);
  color: var(--theme);
  font-weight: 600;
}

.quiz-next::after {
  margin-left: 6px;
  content: "→";
}

.quiz-next:hover {
  background: var(--theme);
  color: var(--on-theme);
}

.quiz-next:focus-visible {
  outline: 2px solid var(--theme);
  outline-offset: 2px;
}

.quiz-next[hidden] {
  display: none;
}

.quiz-back::before {
  margin-right: 6px;
  content: "←";
}

.quiz-back:hover {
  border-color: var(--theme);
  color: var(--ink);
}

.quiz-back:focus-visible {
  outline: 2px solid var(--theme);
  outline-offset: 2px;
}

.quiz-back[hidden] {
  display: none;
}

.scale {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 8px;
}

.scale label {
  display: grid;
  min-height: 64px;
  place-items: center;
  gap: 3px;
  padding: 8px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface-2);
  color: var(--muted);
  cursor: pointer;
  font-weight: 600;
  text-align: center;
}

.scale input {
  position: absolute;
  opacity: 0;
}

.scale label:has(input:checked) {
  border-color: var(--theme);
  background: var(--theme);
  color: var(--on-theme);
}

.scale-number {
  font-size: 1.05rem;
  line-height: 1;
}

.scale-text {
  font-size: 0.75rem;
  line-height: 1.15;
}

.share {
  margin-top: 26px;
  padding-top: 22px;
  border-top: 1px solid var(--line);
}

.share[hidden] {
  display: none;
}

.share-title {
  margin-bottom: 12px;
  font-weight: 600;
}

.share-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.share-actions .button {
  padding: 10px 16px;
  font-size: 0.85rem;
}

.share-actions .button[hidden] {
  display: none;
}

.share-status {
  margin-top: 12px;
  color: var(--muted);
  font-weight: 700;
}

.share-status[hidden] {
  display: none;
}

.question.unanswered {
  border-color: var(--danger);
  box-shadow: 0 0 0 2px var(--danger-glow);
}

.form-error {
  margin: 4px 0 -4px;
  padding: 12px 14px;
  border: 1px solid var(--danger);
  border-radius: 8px;
  background: var(--danger-soft);
  color: var(--danger-ink);
  font-weight: 700;
}

.choices {
  display: grid;
  gap: 8px;
}

.choices .choice {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface-2);
  color: var(--muted);
  cursor: pointer;
  font-weight: 600;
  line-height: 1.35;
}

.choices .choice::before {
  content: "";
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  border: 2px solid var(--line);
  border-radius: 50%;
  background: var(--surface);
}

.choices .choice:hover {
  border-color: var(--theme);
}

.choices input {
  position: absolute;
  opacity: 0;
}

.choices .choice:has(input:checked) {
  border-color: var(--theme);
  background: var(--theme);
  color: var(--on-theme);
  font-weight: 600;
}

/* A small kick when an answer is picked, so the choice registers as an action
   rather than as a colour change. */
.scale label:has(input:checked),
.choices .choice:has(input:checked) {
  animation: pickPop 320ms cubic-bezier(0.2, 0.9, 0.3, 1.4);
}

@keyframes pickPop {
  0% {
    transform: scale(1);
  }
  40% {
    transform: scale(1.04);
  }
  100% {
    transform: scale(1);
  }
}

.choices .choice:has(input:checked)::before {
  border-color: var(--on-theme);
  background: var(--on-theme);
  box-shadow: inset 0 0 0 3px var(--theme);
}

.choices .choice:has(input:focus-visible) {
  outline: 2px solid var(--theme);
  outline-offset: 2px;
}

/* Sits under the result in the same column, so the modal ends the way a test's
   own page does — with somewhere to go next rather than a dead stop. */
.next-tests {
  grid-column: 2;
  margin-top: 22px;
}

.next-tests h3 {
  margin-bottom: 14px;
}

.next-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 180px), 1fr));
  gap: 10px;
  margin-bottom: 16px;
}

.next-card {
  display: grid;
  gap: 4px;
  align-content: start;
  padding: 16px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background:
    linear-gradient(165deg, var(--theme-soft) 0%, transparent 60%),
    var(--surface);
  cursor: pointer;
  font-weight: 600;
  transition:
    transform 200ms cubic-bezier(0.2, 0.8, 0.3, 1),
    border-color 160ms ease,
    box-shadow 160ms ease;
}

.next-icon {
  margin-bottom: 4px;
  font-size: 24px;
  line-height: 1;
}

.next-card small {
  color: var(--muted);
  font-size: 0.8125rem;
  font-weight: 400;
}

.next-card:hover {
  border-color: var(--theme);
  box-shadow:
    0 18px 34px -18px var(--theme-glow),
    var(--shadow-sm);
  transform: translateY(-4px);
}

.next-card:focus-visible {
  outline: 2px solid var(--theme);
  outline-offset: 2px;
}

.next-all {
  display: inline-flex;
  min-height: 46px;
  align-items: center;
  color: var(--theme);
  font-weight: 600;
}

.next-all:hover {
  text-decoration: underline;
}

.result {
  grid-column: 2;
  /* Clears the sticky header when the result is scrolled to on a test's own
     page. Inside the modal, script.js scrolls the panel by measurement. */
  scroll-margin-top: 88px;
  display: grid;
  grid-template-columns: 150px minmax(0, 1fr);
  gap: 28px;
  align-items: center;
  padding: 28px;
  border-radius: 20px;
  /* The category colour, mixed into the dark panel rather than laid over it:
     enough colour to feel like this test's result, dark enough that white text
     keeps its contrast in both palettes. */
  background:
    radial-gradient(120% 130% at 0% 0%, var(--theme-glow) 0%, transparent 62%),
    linear-gradient(
      150deg,
      color-mix(in srgb, var(--theme) 30%, var(--invert-bg)) 0%,
      var(--invert-bg) 64%
    );
  box-shadow: 0 30px 60px -30px var(--theme-glow);
  color: var(--invert-ink);
  animation: resultIn 520ms cubic-bezier(0.2, 0.8, 0.3, 1);
}

@keyframes resultIn {
  from {
    opacity: 0;
    transform: translateY(14px) scale(0.985);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.result p,
.result .section-kicker {
  color: var(--invert-muted);
}

.score-breakdown {
  display: grid;
  gap: 10px;
  margin-top: 18px;
}

.score-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 8px 12px;
  align-items: center;
  color: var(--invert-soft);
  font-size: 0.9rem;
}

.score-row strong {
  color: var(--invert-ink);
}

.score-bar {
  grid-column: 1 / -1;
  height: 8px;
  overflow: hidden;
  border-radius: 999px;
  background: var(--invert-track);
}

.score-bar span {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--theme);
}

.result-visual {
  position: relative;
  display: grid;
  width: 150px;
  height: 150px;
  place-items: center;
}

.result-visual svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);
}

.result-visual circle {
  fill: none;
  stroke: var(--invert-track-2);
  stroke-width: 11;
  stroke-linecap: round;
}

#scoreRing {
  stroke: var(--theme);
  stroke-dasharray: 301.59;
  stroke-dashoffset: 301.59;
  transition: stroke-dashoffset 500ms ease;
}

/* The score is the headline of the result, so it is sized like one. */
#scoreValue {
  position: relative;
  font-size: clamp(1.75rem, 1.4rem + 1.2vw, 2.375rem);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.03em;
  line-height: 1;
  text-align: center;
}

.safety {
  /* A touch softer than the result panel so the two do not read as one block. */
  --invert-bg: #1f2826;
  background: var(--invert-bg);
  color: var(--invert-ink);
}

.safety p {
  max-width: 900px;
  margin-bottom: 0;
  color: var(--invert-muted);
}

.site-footer {
  justify-content: space-between;
  gap: 20px;
  padding: 26px var(--gutter);
  border-top: 1px solid var(--line);
}

@media (max-width: 1000px) {
  .hero,
  .intro,
  .section-heading,
  .quiz-section {
    grid-template-columns: 1fr;
  }

  /* Below the headline the three numbers work better as a strip than as a
     stacked list: it is shorter, and it leaves the test grid nearer the fold. */
  .hero-panel {
    align-self: start;
    max-width: none;
    grid-template-columns: repeat(3, 1fr);
  }

  .hero-panel div {
    align-items: flex-start;
    flex-direction: column;
    gap: 2px;
    padding: 14px;
  }

  .filters {
    justify-content: flex-start;
  }

  .result,
  .next-tests {
    grid-column: auto;
  }

  .modal-panel .quiz-section {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 640px) {
  /* The header stays one row on a phone. Stacking it made a 120px sticky bar
     that followed the reader down the page. */
  .site-header {
    gap: 12px;
    min-height: 60px;
    padding: 10px 20px;
  }

  .top-nav {
    gap: 16px;
    font-size: 0.875rem;
  }

  .scale {
    grid-template-columns: 1fr;
  }

  .scale label {
    min-width: 0;
  }

  .result {
    grid-template-columns: 1fr;
  }

  .site-footer {
    align-items: flex-start;
    flex-direction: column;
  }
}

/* ==========================================================================
   Library refresh
   Each card now carries its own category colour instead of inheriting the
   page-wide theme, so the grid is scannable at a glance rather than monotone.
   ========================================================================== */

.test-card[data-category="personality"] {
  --theme: #6e4a7e;
  --theme-soft: #f1e9f5;
  --theme-glow: rgba(110, 74, 126, 0.2);
}

.test-card[data-category="wellbeing"] {
  --theme: #24733a;
  --theme-soft: #e9f7ed;
  --theme-glow: rgba(36, 115, 58, 0.2);
}

.test-card[data-category="relationships"] {
  --theme: #b04a43;
  --theme-soft: #fff0ed;
  --theme-glow: rgba(176, 74, 67, 0.22);
}

.test-card[data-category="career"] {
  --theme: #1f6795;
  --theme-soft: #e7f2fa;
  --theme-glow: rgba(31, 103, 149, 0.2);
}

.test-card[data-category="fun"] {
  --theme: #a94f18;
  --theme-soft: #fff1df;
  --theme-glow: rgba(169, 79, 24, 0.22);
}

.test-card {
  display: flex;
  min-height: 0;
  flex-direction: column;
  padding: 24px 22px 22px;
}

/* Every test carries its own mark. It is decoration rather than information —
   the title says what the test is — so it stays out of the accessibility tree. */
.card-icon {
  display: grid;
  width: 54px;
  height: 54px;
  align-self: flex-start;
  margin-bottom: 16px;
  border-radius: 17px;
  background: var(--surface);
  box-shadow:
    inset 0 0 0 1.5px var(--theme-glow),
    0 6px 16px var(--theme-glow);
  font-size: 27px;
  line-height: 1;
  place-items: center;
  transition: transform 240ms cubic-bezier(0.2, 0.8, 0.3, 1);
}

.test-card:hover .card-icon,
.test-card:focus-visible .card-icon {
  transform: rotate(-9deg) scale(1.09);
}

.test-card .tag {
  align-self: flex-start;
  margin-bottom: 14px;
  padding: 4px 9px;
  border-radius: 6px;
  background: var(--theme-soft);
  font-size: 0.6875rem;
}

.test-card h3 {
  max-width: none;
  margin-bottom: 8px;
  font-size: 1.1875rem;
  font-weight: 650;
  letter-spacing: -0.015em;
  line-height: 1.25;
}

.test-card p {
  margin-bottom: 0;
  color: var(--muted);
  font-size: 0.9375rem;
  line-height: 1.5;
}

.test-card .card-meta {
  margin-top: auto;
}

/* The same mark the card carries, leading the test's own page. */
.quiz-icon {
  display: grid;
  width: 64px;
  height: 64px;
  margin-bottom: 18px;
  border-radius: 20px;
  background: var(--surface);
  box-shadow:
    inset 0 0 0 1.5px var(--theme-glow),
    0 10px 24px var(--theme-glow);
  font-size: 32px;
  line-height: 1;
  place-items: center;
}

/* The old label sat under every card and added nothing but height. */
.test-card::after,
.test-card.fun-card::after {
  content: none;
}

.test-card:hover {
  border-color: var(--theme);
  box-shadow:
    0 22px 44px -18px var(--theme-glow),
    var(--shadow-sm);
  transform: translateY(-6px) rotate(-0.6deg);
}

/* Breaks the grid every eleventh card, so the eye has somewhere to land rather
   than scanning 58 identical rectangles. Only where two columns fit. */
@media (min-width: 780px) {
  .test-card:nth-child(11n + 1) {
    grid-column: span 2;
  }

  .test-card:nth-child(11n + 1) .card-icon {
    width: 72px;
    height: 72px;
    border-radius: 22px;
    font-size: 36px;
  }

  .test-card:nth-child(11n + 1) h3 {
    font-size: 1.625rem;
  }

  .test-card:nth-child(11n + 1) p {
    max-width: 52ch;
    font-size: 1.0312rem;
  }
}

.test-card:focus-visible {
  outline: 2px solid var(--theme);
  outline-offset: 2px;
}

/* The method page ---------------------------------------------------------- */

.method-hero {
  grid-template-columns: 1fr;
}

/* Running prose, held near 65 characters so the page reads rather than scans. */
.method-copy {
  max-width: 68ch;
}

.method-copy h2 {
  margin-bottom: 12px;
}

.method-copy p {
  color: var(--ink-soft);
}

.method-group {
  margin-top: 40px;
}

.method-group h3 {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 6px;
  font-size: 1.375rem;
}

.method-count {
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--theme-soft);
  color: var(--theme);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.method-group > p {
  max-width: 68ch;
  color: var(--muted);
}

/* The table is wider than a phone. It scrolls inside its own box rather than
   pushing the page sideways. */
.method-table {
  overflow-x: auto;
  margin-top: 20px;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--surface);
}

.method-table table {
  width: 100%;
  min-width: 560px;
  border-collapse: collapse;
  text-align: left;
}

.method-table th,
.method-table td {
  padding: 14px 18px;
  vertical-align: top;
}

.method-table thead th {
  border-bottom: 1px solid var(--line);
  color: var(--muted);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.method-table tbody tr + tr th,
.method-table tbody tr + tr td {
  border-top: 1px solid var(--line);
}

.method-table tbody th {
  width: 34%;
  font-size: 0.9375rem;
  font-weight: 650;
}

.method-table tbody th a {
  color: var(--theme);
}

.method-table tbody th a:hover {
  text-decoration: underline;
}

.method-table td {
  color: var(--muted);
  font-size: 0.875rem;
  line-height: 1.55;
}

/* Search and result count ------------------------------------------------- */

.library-controls {
  display: grid;
  gap: 14px;
  justify-items: end;
}

.search {
  position: relative;
  width: min(320px, 100%);
}

.search input {
  width: 100%;
  padding: 12px 16px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink);
  font-size: 0.95rem;
  transition: border-color 160ms ease, box-shadow 160ms ease;
}

.search input:focus {
  border-color: var(--theme);
  box-shadow: 0 0 0 4px var(--theme-glow);
  outline: none;
}

.search input::-webkit-search-cancel-button {
  cursor: pointer;
}

.library-count {
  margin: 0 0 18px;
  color: var(--muted);
  font-size: 0.9rem;
  font-weight: 700;
}

.filter {
  border-radius: 999px;
}

@media (max-width: 1000px) {
  .library-controls {
    justify-items: stretch;
  }

  .search {
    width: 100%;
  }
}

/* ==========================================================================
   Dark mode
   Follows the reader's system setting. Only tokens are redefined here — every
   rule above already reads from them, so nothing needs a second declaration.
   The accents are lightened rather than reused: the light-mode greens and
   plums are far too dark to read against a dark page.
   ========================================================================== */

@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;
    --ink: #e9efed;
    --ink-soft: #c8d3d0;
    --muted: #93a29f;
    --line: #2c3936;
    --paper: #101615;
    --surface: #18211f;
    --surface-2: #202a28;
    --teal: #6ec3ca;

    --on-ink: #101615;
    --on-theme: #0e1413;

    --surface-veil: rgba(255, 255, 255, 0.05);

    --header-bg: rgba(16, 22, 21, 0.9);
    --header-line: rgba(255, 255, 255, 0.09);

    --backdrop: rgba(0, 0, 0, 0.72);
    --panel-edge: rgba(255, 255, 255, 0.1);

    --danger: #e2776a;
    --danger-soft: rgba(226, 119, 106, 0.14);
    --danger-ink: #f0a89e;
    --danger-glow: rgba(226, 119, 106, 0.2);

    /* Raised above the page rather than inverted — a dark panel on a dark page
       would lose the separation the light design gets for free. */
    --invert-bg: #232e2c;
    --invert-ink: #f4f8f7;
    --invert-muted: rgba(244, 248, 247, 0.72);
    --invert-soft: rgba(244, 248, 247, 0.82);
    --invert-track: rgba(255, 255, 255, 0.12);
    --invert-track-2: rgba(255, 255, 255, 0.14);

    --shadow-sm: 0 12px 28px rgba(0, 0, 0, 0.35);
    --shadow-modal: 0 32px 90px rgba(0, 0, 0, 0.6);

    --theme-soft: rgba(110, 195, 202, 0.14);
    --theme-glow: rgba(110, 195, 202, 0.26);
  }

  .safety {
    --invert-bg: #1b2422;
  }

  /* Category accents, lightened. Applied to the page theme and to the cards,
     which carry their own colour independently of the page. */
  body[data-active-category="personality"],
  .test-card[data-category="personality"],
.next-card[data-category="personality"] {
    --theme: #b992cc;
    --theme-soft: rgba(185, 146, 204, 0.15);
    --theme-glow: rgba(185, 146, 204, 0.3);
  }

  body[data-active-category="wellbeing"],
  .test-card[data-category="wellbeing"],
.next-card[data-category="wellbeing"] {
    --theme: #6fc98a;
    --theme-soft: rgba(111, 201, 138, 0.15);
    --theme-glow: rgba(111, 201, 138, 0.3);
  }

  body[data-active-category="relationships"],
  .test-card[data-category="relationships"],
.next-card[data-category="relationships"] {
    --theme: #ec9a92;
    --theme-soft: rgba(236, 154, 146, 0.15);
    --theme-glow: rgba(236, 154, 146, 0.3);
  }

  body[data-active-category="career"],
  .test-card[data-category="career"],
.next-card[data-category="career"] {
    --theme: #7cb8e2;
    --theme-soft: rgba(124, 184, 226, 0.15);
    --theme-glow: rgba(124, 184, 226, 0.3);
  }

  body[data-active-category="fun"],
  .test-card[data-category="fun"],
.next-card[data-category="fun"] {
    --theme: #f0a367;
    --theme-soft: rgba(240, 163, 103, 0.15);
    --theme-glow: rgba(240, 163, 103, 0.3);
  }

  /* The filter pills keep a category tint, raised so it stays visible. */
  .filter[data-filter="personality"] {
    border-color: rgba(185, 146, 204, 0.45);
  }

  .filter[data-filter="wellbeing"] {
    border-color: rgba(111, 201, 138, 0.45);
  }

  .filter[data-filter="relationships"] {
    border-color: rgba(236, 154, 146, 0.45);
  }

  .filter[data-filter="career"] {
    border-color: rgba(124, 184, 226, 0.45);
  }

  .filter[data-filter="fun"] {
    border-color: rgba(240, 163, 103, 0.45);
  }
}

/* ==========================================================================
   Reduced motion
   Some people get genuinely unwell from animation, and this site is taken by
   people already reporting stress and burnout. Honour the system setting.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  /* The cards lift on hover; without motion the border and shadow still
     signal the hover, so only the movement is dropped. */
  .test-card:hover,
  .test-card:focus-visible,
  .next-card:hover {
    transform: none;
  }

  .test-card:hover .card-icon,
  .test-card:focus-visible .card-icon {
    transform: none;
  }

  .hero-blob {
    animation: none;
  }

  .result {
    animation: none;
  }
}
