/*
 * HUMANPLACE.
 *
 * Near black on near white, one accent, and type doing almost all the work.
 * The restraint is the point: the product's claim is that it tells you
 * something true about your livelihood, and a page covered in gradients and
 * floating cards undercuts that before a word is read.
 *
 * Motion is on entry only, short, and switched off entirely for anyone who has
 * asked their system to stop animating things.
 */

:root {
  --ink:      #0A0A0B;
  --ink-soft: #52525B;
  --ink-faint:#A1A1AA;
  --page:     #FBFBFC;
  --surface:  #FFFFFF;
  --line:     #E7E7EA;

  /*
   * The brand red. It owns the PLACE in HUMANPLACE, the live field behind the
   * hero, and the measurement bars, and it appears nowhere else: a second
   * unrelated thing in this red would stop the wordmark meaning anything.
   *
   * Green and amber stay semantic. A score is not better for being on brand,
   * and a shrinking market has to be allowed to look like one.
   */
  --blood:    #E01B24;
  --accent:   #0A0A0B;
  --warn:     #B45309;
  --good:     #15803D;

  --measure:  34rem;
  --ease:     cubic-bezier(0.22, 1, 0.36, 1);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ink:      #FAFAFA;
    --ink-soft: #A1A1AA;
    --ink-faint:#52525B;
    --page:     #09090B;
    --surface:  #121214;
    --line:     #26262A;
    --accent:   #FAFAFA;
    /* Lifted against a near-black ground, where the light-mode red reads brown
       and loses the whole point of it. */
    --blood:    #FF4D4D;
    --warn:     #FBBF24;
    --good:     #4ADE80;
  }
}
:root[data-theme="dark"] {
  --ink: #FAFAFA; --ink-soft: #A1A1AA; --ink-faint: #52525B;
  --page: #09090B; --surface: #121214; --line: #26262A;
  --accent: #FAFAFA; --blood: #FF4D4D; --warn: #FBBF24; --good: #4ADE80;
}

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

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

body {
  margin: 0;
  background: var(--page);
  color: var(--ink);
  font: 400 17px/1.6 ui-sans-serif, -apple-system, BlinkMacSystemFont,
        "SF Pro Text", "Segoe UI", system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

.wrap { width: 100%; max-width: 62rem; margin: 0 auto; padding: 0 clamp(16px, 5vw, 40px); }

.sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ------------------------------------------------------------------ type */

h1 {
  margin: 0;
  font-size: clamp(3rem, 9vw, 6.6rem);
  font-weight: 600;
  /* Large type is spaced for body copy by default, which reads slack at this
     size. The bigger it is, the tighter it gets. */
  letter-spacing: -0.05em;
  line-height: 0.98;
  text-wrap: balance;
}

/*
 * The word the company is named after, in the colour it is named in. An em
 * because it is emphasis in the sentence, not a style hook bolted onto a span,
 * and it is set upright because the italic a browser would give it is not the
 * emphasis meant here.
 */
h1 em { color: var(--blood); font-style: normal; }

h2 {
  margin: 0 0 0.6rem;
  font-size: clamp(1.8rem, 4vw, 2.9rem);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.15;
  text-wrap: balance;
}

p { margin: 0 0 1.1rem; max-width: var(--measure); }

.lede {
  margin-top: 1.8rem;
  font-size: clamp(1.2rem, 2.6vw, 1.65rem);
  line-height: 1.45;
  color: var(--ink-soft);
  letter-spacing: -0.018em;
  max-width: 30rem;
}

.fine { font-size: 0.85rem; color: var(--ink-faint); margin: 0; }

/* ------------------------------------------------------------------ bar */

.bar {
  position: sticky; top: 0; z-index: 40;
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem;
  padding: 1rem clamp(16px, 5vw, 40px);
  background: color-mix(in srgb, var(--page) 82%, transparent);
  backdrop-filter: saturate(180%) blur(16px);
  -webkit-backdrop-filter: saturate(180%) blur(16px);
  border-bottom: 1px solid transparent;
  transition: border-color 0.3s var(--ease);
}
.bar.scrolled { border-bottom-color: var(--line); }

.wordmark {
  /* HUMAN and PLACE are one word. Splitting PLACE into its own span gave the
     flex row somewhere to break and the mark came apart onto two lines. */
  white-space: nowrap;
  font-weight: 650;
  font-size: 0.95rem;
  letter-spacing: 0.14em;
  color: var(--ink);
  text-decoration: none;
}
.wordmark.small { letter-spacing: 0.12em; font-size: 0.8rem; }

/* The half of the name the product is actually about. */
.wordmark .place { color: var(--blood); }

.bar nav { display: flex; align-items: center; gap: 1.4rem; }
.bar nav a {
  font-size: 0.9rem; color: var(--ink-soft); text-decoration: none;
  transition: color 0.2s var(--ease);
}
.bar nav a:hover { color: var(--ink); }
.bar nav a.ghost {
  color: var(--page); background: var(--ink);
  padding: 0.5rem 1rem; border-radius: 99px; font-weight: 550;
}
.bar nav a.ghost:hover { opacity: 0.85; color: var(--page); }

@media (max-width: 30rem) { .bar nav a[href="#how"] { display: none; } }

/* ----------------------------------------------------------------- hero */

.hero { padding: clamp(5rem, 16vh, 9rem) 0 clamp(4rem, 10vh, 7rem); }

/* ------------------------------------------------------------------ ask */

.ask {
  position: relative;
  display: flex; align-items: center; gap: 0.5rem;
  margin: 2.6rem 0 1.1rem;
  max-width: 34rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 99px;
  padding: 0.4rem 0.4rem 0.4rem 1.3rem;
  transition: border-color 0.25s var(--ease), box-shadow 0.25s var(--ease);
}
.ask:focus-within {
  border-color: var(--ink-faint);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--blood) 14%, transparent);
}

.ask input {
  flex: 1; min-width: 0;
  border: 0; outline: 0; background: transparent;
  color: var(--ink);
  /* Never below 16px: under that, Safari on iOS zooms the page in on focus and
     leaves it zoomed, which shoves the rest of the page off screen. */
  font: inherit; font-size: clamp(16px, 1.3vw, 18px);
  padding: 0.95rem 0;
}
.ask input::placeholder { color: var(--ink-faint); }

.ask button {
  flex: none;
  width: 50px; height: 50px;
  display: grid; place-items: center;
  border: 0; border-radius: 99px;
  background: var(--ink); color: var(--page);
  cursor: pointer;
  transition: transform 0.2s var(--ease), opacity 0.2s var(--ease);
}
.ask button:hover { transform: translateX(2px); }
.ask button:active { transform: scale(0.94); }
.ask.busy button { opacity: 0.4; pointer-events: none; }

.ask.big { max-width: 34rem; margin-inline: auto; }

/* -------------------------------------------------------------- suggest */

.suggest {
  position: absolute; top: calc(100% + 0.5rem); left: 0; right: 0; z-index: 30;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 18px;
  padding: 0.35rem;
  box-shadow: 0 1px 2px rgb(0 0 0 / 0.04), 0 12px 32px rgb(0 0 0 / 0.10);
  overflow: hidden;
}
.suggest button {
  display: block; width: 100%; text-align: left;
  border: 0; background: transparent; color: var(--ink);
  font: inherit; font-size: 0.95rem;
  padding: 0.7rem 0.9rem; border-radius: 12px; cursor: pointer;
}
.suggest button:hover, .suggest button[aria-selected="true"] {
  background: color-mix(in srgb, var(--ink) 6%, transparent);
}
.suggest .sub { display: block; font-size: 0.78rem; color: var(--ink-faint); }

/* --------------------------------------------------------------- result */

.result { padding: 0 0 clamp(3rem, 8vh, 5rem); }
.result[hidden] { display: none; }

/* scrollIntoView stops with the element's top at the top of the viewport, which
   is underneath the sticky bar. Without this the occupation's name lands behind
   the header the moment the report opens. */
#result { scroll-margin-top: 5rem; }

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 24px;
  padding: clamp(1.4rem, 4vw, 2.4rem);
}

.found { margin-bottom: 1.8rem; }
.found .eyebrow {
  font-size: 0.72rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--ink-faint); margin: 0 0 0.4rem;
}
.found h2 { font-size: clamp(2rem, 5vw, 3.1rem); }
.found .meta { color: var(--ink-soft); font-size: 0.95rem; margin: 0.4rem 0 0; }

/* The other matches. Quiet, because they are a correction and not a feature. */
.alts {
  display: flex; flex-wrap: wrap; align-items: baseline;
  gap: 0.35rem 0.7rem;
  margin: 1rem 0 0; max-width: none;
  font-size: 0.82rem; color: var(--ink-faint);
}
.alts button {
  border: 0; background: transparent; padding: 0;
  font: inherit; color: var(--ink-soft);
  text-decoration: underline; text-decoration-color: var(--line);
  text-underline-offset: 3px;
  cursor: pointer;
  transition: color 0.2s var(--ease), text-decoration-color 0.2s var(--ease);
}
.alts button:hover { color: var(--blood); text-decoration-color: var(--blood); }

.scores {
  display: grid; gap: 1px;
  grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr));
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: 20px;
  overflow: hidden;
}
.score { background: var(--surface); padding: 1.3rem 1.2rem 1.4rem; }
.score .n {
  font-size: clamp(2.8rem, 4.6vw, 3.6rem);
  font-weight: 600; letter-spacing: -0.05em; line-height: 1;
  font-variant-numeric: tabular-nums;
  display: block;
}
.score .k {
  display: block; margin-top: 0.45rem;
  font-size: 0.8rem; color: var(--ink-soft); letter-spacing: -0.005em;
}
.score .bar-track {
  /* A span is inline by default, which silently drops height, margin and width
     and left every bar a zero-by-zero box. The numbers rendered, the inline
     width was set, and nothing was drawn. */
  display: block;
  margin-top: 0.75rem; height: 3px; border-radius: 99px;
  background: color-mix(in srgb, var(--ink) 9%, transparent);
  overflow: hidden;
}
.score .bar-fill {
  /* Same reason as the track above: both are spans, and fixing only the
     outer one left the fill an inline box with no height inside a track that
     now had one. */
  display: block;
  height: 100%; border-radius: 99px;
  /* Neutral by default. A score without a verdict should not be wearing one,
     and red here has a job: it is the colour of work in the path of AI, which
     is a claim and not a decoration. */
  background: var(--ink-faint);
  width: 0; transition: width 0.9s var(--ease);
}
.score.good .n { color: var(--good); }
.score.good .bar-fill { background: var(--good); }
.score.risk .n { color: var(--blood); }
.score.risk .bar-fill { background: var(--blood); }

.caveat {
  margin: 1.1rem 0 0; font-size: 0.8rem; color: var(--ink-faint);
  max-width: 40rem; line-height: 1.5;
}

/* paths */
.paths { margin-top: 2.2rem; }
.paths h3 {
  font-size: 1.05rem; font-weight: 600; letter-spacing: -0.02em;
  margin: 0 0 0.9rem;
}
.path {
  display: flex; align-items: baseline; gap: 1rem; flex-wrap: wrap;
  padding: 1.05rem 0;
  border-top: 1px solid var(--line);
}
.path .t { font-weight: 550; letter-spacing: -0.015em; flex: 1 1 14rem; }
.path .d {
  font-size: 0.8rem; color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}
/* The only coloured thing in a row. A pay cut is not a failure, so it is stated
   in the same weight as a raise rather than flagged. */
.path .d.up   { color: var(--good); }
.path .d.down { color: var(--ink-soft); }

.path .tag {
  font-size: 0.7rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--ink-faint);
  border: 1px solid var(--line); border-radius: 99px;
  padding: 0.2rem 0.6rem;
}

/* ---------------------------------------------------------------- beats */

.beats { padding: clamp(3rem, 10vh, 7rem) 0; border-top: 1px solid var(--line); }
.beats .wrap { display: grid; gap: clamp(2.6rem, 7vw, 4.5rem); }

@media (min-width: 56rem) {
  .beats .wrap { grid-template-columns: 1fr 1fr; gap: 4rem 5rem; }
}

.beat .step {
  display: block;
  font-size: 0.72rem; letter-spacing: 0.16em;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
  margin-bottom: 0.9rem;
}
.beat p { color: var(--ink-soft); margin: 0; }

/* ---------------------------------------------------------------- level */

.level {
  padding: clamp(3rem, 10vh, 7rem) 0;
  border-top: 1px solid var(--line);
}
.level p { color: var(--ink-soft); }
.level .sources {
  font-size: 0.82rem; color: var(--ink-faint); margin-top: 1.8rem;
  max-width: 40rem;
}

/* ------------------------------------------------------------------ end */

.end {
  padding: clamp(4rem, 12vh, 8rem) 0;
  border-top: 1px solid var(--line);
  text-align: center;
}
.end h2 { font-size: clamp(2.2rem, 6vw, 3.8rem); }

footer {
  padding: 2.5rem 0 3.5rem;
  border-top: 1px solid var(--line);
}
footer .wrap {
  display: flex; justify-content: space-between; align-items: center;
  gap: 1rem; flex-wrap: wrap;
}

/* --------------------------------------------------------------- motion */

/*
 * One entry animation, applied on scroll by app.js. Deliberately small: an
 * eight pixel rise and a fade, which reads as the page settling rather than as
 * the page performing.
 */
/*
 * Gated on the .js class, which app.js sets on <html> as its first statement.
 *
 * Without that gate the hidden state is the default, and a script that 404s,
 * throws on an old browser, or is blocked by an extension leaves everything
 * below the hero permanently at zero opacity: present in the DOM, occupying
 * its full height, and invisible. An entrance animation is not worth a page
 * that can disappear.
 */
.js .reveal {
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
}
.js .reveal.in { opacity: 1; transform: none; }
.js .reveal[data-delay="1"] { transition-delay: 0.07s; }
.js .reveal[data-delay="2"] { transition-delay: 0.14s; }
.js .reveal[data-delay="3"] { transition-delay: 0.21s; }

@media (prefers-reduced-motion: reduce) {
  .js .reveal { opacity: 1; transform: none; transition: none; }
  .score .bar-fill { transition: none; }
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

/* -------------------------------------------------------------- openings */

.openings { margin-top: 2.4rem; }
.openings h3 {
  font-size: 1.05rem; font-weight: 600; letter-spacing: -0.02em;
  margin: 0 0 0.9rem;
}

/*
 * The location filter.
 *
 * Named .locate, not .place, because PLACE in the wordmark is a span with a
 * class too: the two collided and the half of the brand mark in red silently
 * became a flex container with a bottom margin, which put it on its own line.
 *
 * Smaller and squarer than the hero field. This is a filter on an answer
 * already given, not the question the page is built around.
 */
.locate {
  display: flex; gap: 0.5rem; flex-wrap: wrap;
  margin: 0 0 1.2rem;
}
.locate input {
  flex: 1 1 14rem; min-width: 0;
  background: var(--page);
  border: 1px solid var(--line); border-radius: 12px;
  color: var(--ink); font: inherit; font-size: 16px;
  padding: 0.6rem 0.9rem;
  transition: border-color 0.2s var(--ease);
}
.locate input:focus {
  outline: 0;
  border-color: var(--blood);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--blood) 12%, transparent);
}
.locate input::placeholder { color: var(--ink-faint); }
.locate button {
  flex: none;
  border: 1px solid var(--line); border-radius: 12px;
  background: var(--page); color: var(--ink);
  font: inherit; font-size: 0.9rem; font-weight: 550;
  padding: 0.6rem 1.1rem; cursor: pointer;
  transition: background 0.2s var(--ease), border-color 0.2s var(--ease);
}
.locate button:hover { background: color-mix(in srgb, var(--ink) 5%, transparent); }

/* A whole row is the link. A listing is one thing, and making only the title
   clickable means half the target area does nothing. */
.job {
  display: flex; align-items: baseline; gap: 0.5rem 1rem; flex-wrap: wrap;
  padding: 1.05rem 0;
  border-top: 1px solid var(--line);
  color: inherit; text-decoration: none;
  transition: opacity 0.2s var(--ease);
}
.job:hover { opacity: 0.6; }
.job .t { font-weight: 550; letter-spacing: -0.015em; flex: 1 1 16rem; }
.job .meta { font-size: 0.85rem; color: var(--ink-soft); }
.job .d {
  font-size: 0.8rem; color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------- the field */

.hero { position: relative; isolation: isolate; }

/*
 * Behind everything, bleeding past the hero's own box so the lattice is cut by
 * the viewport rather than by a container edge. A visible rectangle would read
 * as a widget; this reads as the page the words are sitting on.
 */
.field {
  /*
   * Height stated outright rather than left to the top and bottom insets.
   *
   * A canvas is a replaced element, so when its height is auto the browser
   * ignores the bottom inset and sizes it from the canvas element's own aspect
   * ratio. That ratio starts at 2:1, which happens to be near enough to a
   * desktop hero to look deliberate, and collapses to a 195 pixel band on a
   * phone: the animation was not missing on mobile, it was a sliver above the
   * headline.
   */
  position: absolute;
  top: -5rem; left: 0; right: 0;
  width: 100%;
  height: calc(100% + 7rem);
  z-index: -1;
  pointer-events: none;
  /*
   * Two masks, intersected: fade out at the bottom so the lattice does not
   * collide with the first section rule, and fade out on the left so it never
   * sits underneath the headline.
   *
   * The second one is not a refinement. On a dark background the dots read at
   * full strength and ran straight through the type, which made the one
   * sentence the page exists to deliver hard to read. The field belongs beside
   * the words, not behind them.
   */
  -webkit-mask-image:
    linear-gradient(to bottom, #000 62%, transparent 100%),
    linear-gradient(to right, transparent 28%, #000 52%);
          mask-image:
    linear-gradient(to bottom, #000 62%, transparent 100%),
    linear-gradient(to right, transparent 28%, #000 52%);
  -webkit-mask-composite: source-in;
          mask-composite: intersect;
}

/*
 * No room to put it beside anything on a phone: the text runs the full width.
 * So it goes quiet instead, and the bottom fade does the rest.
 */
@media (max-width: 52rem) {
  .field {
    opacity: 0.85;
    -webkit-mask-image: linear-gradient(to bottom, #000 40%, transparent 100%);
            mask-image: linear-gradient(to bottom, #000 40%, transparent 100%);
    -webkit-mask-composite: source-over;
            mask-composite: add;
  }
}

/* --------------------------------------------------------- the headline */

/*
 * Each line is clipped by its own box and slides up into it, which is a very
 * different feeling from the whole block fading: the type arrives as type.
 * The spans are what make it possible, so the markup carries them.
 */
h1 .line {
  display: block;
  overflow: hidden;
  /* Descenders get clipped by an exact-height overflow box, so the line is
     given room and pulled back by the same amount. */
  padding-bottom: 0.08em;
  margin-bottom: -0.08em;
}
.js h1 .line > span {
  display: block;
  transform: translateY(104%);
  transition: transform 0.95s var(--ease);
}
.js h1.in .line > span { transform: none; }
.js h1.in .line:nth-child(2) > span { transition-delay: 0.09s; }

/* The headline's own opacity animation would fight the slide. */
.js h1.reveal { opacity: 1; transform: none; }

/* ------------------------------------------------- rows arriving in order */

/*
 * Paths and job listings come in one after another rather than all at once.
 * The delay is set inline from the row's index, because the count is only
 * known at render time and a nth-child rule would cap out at whatever number
 * was guessed here.
 */
.js .card .path,
.js .card .job {
  opacity: 0;
  transform: translateY(6px);
  animation: rise 0.55s var(--ease) forwards;
}

@keyframes rise {
  to { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .js h1 .line > span { transform: none; transition: none; }
  .js .card .path,
  .js .card .job { opacity: 1; transform: none; animation: none; }
}

/* ------------------------------------------------------------- the divide */

.divide {
  padding: clamp(3.5rem, 11vh, 7rem) 0;
  border-top: 1px solid var(--line);
}
.divide > .wrap > p { color: var(--ink-soft); max-width: 38rem; }

.scales {
  display: grid; gap: 2.5rem;
  margin: 2.6rem 0 0;
}
@media (min-width: 52rem) {
  .scales { grid-template-columns: 1fr 1fr; gap: 3.5rem; }
}

.scale h3 {
  margin: 0 0 0.3rem;
  font-size: 0.75rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--ink-faint);
}
.scale-note {
  margin: 0 0 1.4rem;
  font-size: 0.8rem; color: var(--ink-faint); max-width: 24rem;
}

.scale .line {
  display: grid;
  grid-template-columns: 1fr 5.5rem 2rem;
  align-items: center;
  gap: 0.9rem;
  padding: 0.62rem 0;
}
.js .scale .line { opacity: 0; animation: rise 0.6s var(--ease) forwards; }

.scale .line .t { font-size: 0.95rem; letter-spacing: -0.012em; }
.scale .line .v {
  font-size: 0.85rem; text-align: right;
  font-variant-numeric: tabular-nums;
  color: var(--ink-soft);
}
.scale .track {
  height: 4px; border-radius: 99px;
  background: color-mix(in srgb, var(--ink) 8%, transparent);
  overflow: hidden;
}
.scale .fill {
  display: block; height: 100%; border-radius: 99px;
  width: 0;
  transition: width 1.1s var(--ease);
}

/* The one place two colors are used to mean opposite things, which is the
   whole argument of the section: red is the work in the path of it. */
#exposed .fill { background: var(--blood); }
#held .fill { background: var(--good); }
#exposed .line .v { color: var(--blood); }
#held .line .v { color: var(--good); }

@media (prefers-reduced-motion: reduce) {
  .js .scale .line { opacity: 1; animation: none; }
  .scale .fill { transition: none; }
}

/*
 * The two columns start their rows on the same line.
 *
 * A min-height on the note was the first attempt and it was eight pixels out:
 * the notes wrap differently at different widths and no fixed height is right
 * at every one of them. Subgrid makes the heading, the note and the rows share
 * the parent's row tracks, so the two columns are aligned by construction.
 */
@media (min-width: 52rem) {
  .scales { grid-template-rows: auto auto auto; }
  .scale { display: grid; grid-row: span 3; grid-template-rows: subgrid; gap: 0; }
}
.divide .sources { margin-top: 2.2rem; }

/* Still waiting on the job board. Pulsed rather than spun: the rest of the
   report is already readable and this is the one part still arriving. */
.caveat.loading { animation: breathe 1.6s ease-in-out infinite; }
@keyframes breathe { 50% { opacity: 0.45; } }
@media (prefers-reduced-motion: reduce) { .caveat.loading { animation: none; } }

/* --------------------------------------------------------- three paths */

.paths h3.section {
  font-size: 1.05rem; font-weight: 600; letter-spacing: -0.02em;
  margin: 0 0 1.2rem;
}

.trio { display: grid; gap: 1px; background: var(--line);
  border: 1px solid var(--line); border-radius: 20px; overflow: hidden; }
@media (min-width: 56rem) { .trio { grid-template-columns: repeat(3, 1fr); } }

.opt { background: var(--surface); padding: 1.3rem 1.25rem 1.5rem; }
.opt h3 {
  margin: 0 0 0.35rem;
  font-size: 0.95rem; font-weight: 650; letter-spacing: -0.015em;
}
.opt .why {
  margin: 0 0 1.1rem; max-width: none;
  font-size: 0.82rem; color: var(--ink-faint); line-height: 1.45;
}
.opt .note { margin: 0; font-size: 0.82rem; color: var(--ink-faint); max-width: none; }

/* An option is a target, so it gets a target's affordances: full width, a
   hover state, and a visible mark once it has been chosen. */
.option {
  display: block; width: 100%; text-align: left;
  border: 0; border-top: 1px solid var(--line);
  background: transparent; color: inherit; font: inherit;
  padding: 0.75rem 0; cursor: pointer;
  transition: opacity 0.2s var(--ease);
}
.opt .option:first-of-type { border-top: 0; }
.option:hover { opacity: 0.62; }
.option.picked .t { color: var(--blood); }
.option .t { display: block; font-weight: 550; letter-spacing: -0.015em; }
.option .meta {
  display: flex; flex-wrap: wrap; gap: 0.25rem 0.7rem;
  margin-top: 0.3rem;
  font-size: 0.78rem; color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}
.option .fit { color: var(--ink-soft); font-weight: 550; }

.js .opt .option { opacity: 0; animation: rise 0.5s var(--ease) forwards; }

.chiplabel {
  margin: 0.9rem 0 0.45rem; max-width: none;
  font-size: 0.7rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--ink-faint);
}
.chips { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.chip {
  font-size: 0.78rem; line-height: 1.3;
  padding: 0.3rem 0.6rem; border-radius: 8px;
  background: color-mix(in srgb, var(--good) 14%, transparent);
  color: var(--ink);
}
.chips.dim .chip { background: color-mix(in srgb, var(--blood) 12%, transparent); }

/* ------------------------------------------------------------- detail */

.detail {
  margin-top: 1.4rem;
  border: 1px solid var(--line); border-radius: 20px;
  background: var(--page);
}
.detail[hidden] { display: none; }
.detail-inner { position: relative; padding: clamp(1.2rem, 3vw, 1.9rem); }

.detail .close {
  position: absolute; top: 0.9rem; right: 1rem;
  border: 0; background: transparent; color: var(--ink-faint);
  font-size: 1.5rem; line-height: 1; cursor: pointer; padding: 0.2rem;
}
.detail .close:hover { color: var(--ink); }
.detail h3 {
  margin: 0 0 0.3rem;
  font-size: clamp(1.2rem, 2.6vw, 1.6rem); font-weight: 600; letter-spacing: -0.025em;
}
.detail .meta { color: var(--ink-soft); font-size: 0.9rem; margin: 0 0 1.2rem; }

.scores.small { border-radius: 14px; }
.scores.small .score { padding: 0.9rem 0.9rem 1rem; }
.scores.small .n { font-size: 1.8rem; }
.scores.small .k { font-size: 0.74rem; }
.scores.small .delta {
  display: block; margin-top: 0.3rem;
  font-size: 0.72rem; color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

.gap { display: grid; gap: 1.2rem 2rem; margin-top: 1.4rem; }
@media (min-width: 42rem) { .gap { grid-template-columns: 1fr 1fr; } }

.ghostbtn {
  margin-top: 1.3rem;
  border: 1px solid var(--line); border-radius: 12px;
  background: var(--surface); color: var(--ink);
  font: inherit; font-size: 0.88rem; font-weight: 550;
  padding: 0.65rem 1.1rem; cursor: pointer;
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease);
}
.ghostbtn:hover { border-color: var(--blood); color: var(--blood); }

.openings h3.section {
  font-size: 1.05rem; font-weight: 600; letter-spacing: -0.02em;
  margin: 0 0 0.9rem;
}

/* ------------------------------------------------- the question, as glass */

/*
 * The one thing on this page anybody has to do.
 *
 * It was a quiet outlined pill sitting under three lines of large type and it
 * lost every time. It is now a piece of glass: translucent, blurred behind,
 * lit from the top edge, with a slow sheen travelling across it and a red
 * halo breathing underneath. Everything here is on the pill itself rather
 * than around it, so it reads as an object on the page instead of a box
 * drawn on it.
 */
.cue {
  margin: 2.4rem 0 0.7rem;
  font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--blood);
}
.cue::after {
  content: '';
  display: inline-block;
  width: 1px; height: 0.85em;
  margin-left: 0.45em;
  vertical-align: -0.1em;
  background: var(--blood);
  animation: caret 1.1s steps(1) infinite;
}
@keyframes caret { 50% { opacity: 0; } }

/* Once somebody has started, the instruction has done its job and goes. */
.asking .cue { opacity: 0; transition: opacity 0.4s var(--ease); }

.ask {
  margin-top: 0;
  background: color-mix(in srgb, var(--surface) 72%, transparent);
  backdrop-filter: blur(18px) saturate(160%);
  -webkit-backdrop-filter: blur(18px) saturate(160%);
  border-color: color-mix(in srgb, var(--ink) 12%, transparent);
  box-shadow:
    /* The lit top edge that makes a flat pill look like a curved surface. */
    inset 0 1px 0 color-mix(in srgb, #fff 70%, transparent),
    0 1px 2px rgb(0 0 0 / 0.04),
    0 18px 40px -12px color-mix(in srgb, var(--blood) 22%, transparent);
  overflow: hidden;
}

/* The halo. Sits behind the glass and breathes. */
.ask::before {
  content: '';
  position: absolute; inset: -40%;
  z-index: -1;
  background: radial-gradient(
    50% 50% at 50% 50%,
    color-mix(in srgb, var(--blood) 34%, transparent),
    transparent 70%
  );
  filter: blur(26px);
  animation: halo 4.5s ease-in-out infinite;
  pointer-events: none;
}
@keyframes halo {
  0%, 100% { opacity: 0.45; transform: scale(0.94); }
  50%      { opacity: 0.85; transform: scale(1.04); }
}

/*
 * The sheen: a soft diagonal band of light travelling across the glass.
 *
 * Shaped like a reflection rather than a stripe, which is the difference
 * between glass and a loading skeleton. It pauses for most of the loop, so it
 * reads as an occasional catch of the light instead of a progress bar.
 */
.ask::after {
  content: '';
  position: absolute; top: 0; bottom: 0; left: 0;
  width: 45%;
  background: linear-gradient(
    105deg,
    transparent,
    color-mix(in srgb, #fff 62%, transparent) 42%,
    color-mix(in srgb, var(--blood) 16%, transparent) 58%,
    transparent
  );
  transform: translateX(-160%) skewX(-14deg);
  animation: sheen 6s cubic-bezier(0.4, 0, 0.2, 1) infinite;
  pointer-events: none;
}
@keyframes sheen {
  0%, 55%  { transform: translateX(-160%) skewX(-14deg); }
  85%, 100% { transform: translateX(340%) skewX(-14deg); }
}

.ask:focus-within {
  border-color: color-mix(in srgb, var(--blood) 55%, transparent);
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, #fff 70%, transparent),
    0 0 0 4px color-mix(in srgb, var(--blood) 16%, transparent),
    0 20px 46px -12px color-mix(in srgb, var(--blood) 34%, transparent);
}
.ask:focus-within::before { animation-duration: 2.6s; }

.ask input::placeholder {
  color: color-mix(in srgb, var(--ink) 42%, transparent);
}

/* The arrow earns its weight now the field has some. */
.ask button {
  box-shadow: 0 6px 16px -6px color-mix(in srgb, var(--blood) 60%, transparent);
}

@media (prefers-reduced-motion: reduce) {
  .ask::before, .ask::after, .cue::after { animation: none; }
  .ask::after { opacity: 0; }
}

/* ---------------------------------------------------------- the verdict */

/*
 * The first thing read and the largest thing on the card.
 *
 * Bordered on one edge in the colour of its own answer, so the call is legible
 * before a word of it is: red for leave, green for stay, neutral for the one
 * that says the work changes under you.
 */
.verdict {
  margin: 1.8rem 0 2rem;
  padding: 1.5rem 1.6rem 1.7rem;
  border-radius: 18px;
  border-left: 4px solid var(--ink-faint);
  background: color-mix(in srgb, var(--ink) 3%, transparent);
}
.verdict.move { border-left-color: var(--blood); background: color-mix(in srgb, var(--blood) 7%, transparent); }
.verdict.hold { border-left-color: var(--good); background: color-mix(in srgb, var(--good) 7%, transparent); }

.verdict .call {
  margin: 0.1rem 0 0.7rem;
  font-size: clamp(1.9rem, 4.6vw, 3rem);
  font-weight: 650; letter-spacing: -0.035em; line-height: 1.02;
}
.verdict.move .call { color: var(--blood); }
.verdict.hold .call { color: var(--good); }

.verdict .why {
  margin: 0; max-width: 42rem;
  font-size: clamp(1rem, 1.9vw, 1.12rem); line-height: 1.5;
  color: var(--ink);
}
.verdict .horizon {
  margin: 0.7rem 0 0; max-width: 42rem;
  font-size: 0.88rem; color: var(--ink-soft);
}

.bigcta {
  margin-top: 1.3rem;
  border: 0; border-radius: 99px;
  background: var(--ink); color: var(--page);
  font: inherit; font-size: 0.95rem; font-weight: 600;
  padding: 0.8rem 1.6rem; cursor: pointer;
  transition: transform 0.2s var(--ease), opacity 0.2s var(--ease);
}
.verdict.move .bigcta { background: var(--blood); color: #fff; }
.bigcta:hover { transform: translateY(-1px); opacity: 0.9; }
.bigcta:active { transform: scale(0.98); }

/* ------------------------------------------------------------- the era */

/*
 * The caption for the hero animation, in real type.
 *
 * It used to be drawn into the canvas as a marquee, which meant rasterised
 * text behind a figure: nothing selectable, nothing for a screen reader, and
 * the word and the drawing competing for the same pixels. Outside the canvas it
 * is crisp at any zoom and the illustration gets its space back.
 */
.era {
  position: absolute;
  z-index: 1;
  margin: 0;
  max-width: none;
  pointer-events: none;
  text-align: center;
  /* Under the scene, which sits in the right-hand column. The vertical
     position is set by app.js from where the drawing actually ends. */
  right: clamp(16px, 5vw, 40px);
  top: 0;
  width: 18rem;
  transition: opacity 0.18s var(--ease), transform 0.18s var(--ease),
    filter 0.18s var(--ease);
}

/* The turn: a short lift and blur, which is what the marquee was for. */
.era.turning {
  opacity: 0;
  transform: translateY(-6px);
  filter: blur(4px);
}

.era-year {
  display: block;
  font-size: clamp(1.9rem, 3.4vw, 2.8rem);
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1;
  /* Readable, not decorative. At a quarter opacity it was there and nobody
     could see it, on either ground. */
  color: color-mix(in srgb, var(--ink) 42%, transparent);
  font-variant-numeric: tabular-nums;
}

.era-word {
  display: block;
  margin-top: 0.35rem;
  font-size: 0.72rem;
  font-weight: 650;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--ink) 52%, transparent);
}

/* On a phone the scene sits in the band above the headline, so its caption
   goes there too rather than at the foot of the hero. */
@media (max-width: 52rem) {
  /* Beside the scene and vertically centred on it: middle right, with the
     drawing shifted left to leave the room. */
  .era {
    left: auto;
    right: clamp(14px, 4vw, 28px);
    width: 7rem;
    text-align: right;
    transform: none;
  }
  .era.turning { transform: translateY(-6px); }
  .era-year { font-size: 1.7rem; }
  .era-word { font-size: 0.6rem; letter-spacing: 0.12em; line-height: 1.5; }
}

@media (prefers-reduced-motion: reduce) {
  .era { transition: none; }
  .era.turning { opacity: 1; transform: none; filter: none; }
  @media (max-width: 52rem) {
    .era.turning { transform: none; }
  }
}

/* ------------------------------------------------------- personalising */

/*
 * The ask, placed where somebody has just been told their work is exposed.
 * That is the one moment they are motivated enough to spend fifteen seconds on
 * a form, and it was being spent on three generic chips.
 */
.personalise {
  margin: 1.8rem 0 2rem;
  padding: 1.4rem 1.5rem 1.6rem;
  border-radius: 18px;
  border: 1px solid var(--line);
  background: color-mix(in srgb, var(--ink) 3%, transparent);
}
.personalise.urgent {
  border-color: color-mix(in srgb, var(--blood) 40%, transparent);
  background: color-mix(in srgb, var(--blood) 6%, transparent);
}
.personalise h3 {
  margin: 0.1rem 0 0.6rem;
  font-size: clamp(1.2rem, 2.6vw, 1.6rem);
  font-weight: 650; letter-spacing: -0.025em; line-height: 1.15;
}
.personalise .why {
  margin: 0; max-width: 40rem;
  font-size: 0.95rem; line-height: 1.5; color: var(--ink-soft);
}
.personalise .bigcta { margin-top: 1.1rem; }
.personalise.urgent .bigcta { background: var(--blood); color: #fff; }

.toolgrid {
  display: flex; flex-wrap: wrap; gap: 0.45rem;
  margin-bottom: 1.2rem;
}

/* A tick target big enough for a thumb, and it has to read as pressed. */
.tool { cursor: pointer; }
.tool input { position: absolute; opacity: 0; pointer-events: none; }
.tool span {
  display: inline-block;
  font-size: 0.85rem; line-height: 1.3;
  padding: 0.5rem 0.8rem;
  border: 1px solid var(--line); border-radius: 99px;
  color: var(--ink-soft);
  transition: border-color 0.15s var(--ease), color 0.15s var(--ease),
    background 0.15s var(--ease);
}
.tool input:checked + span {
  border-color: color-mix(in srgb, var(--good) 60%, transparent);
  background: color-mix(in srgb, var(--good) 14%, transparent);
  color: var(--ink);
}
.tool input:focus-visible + span {
  outline: 2px solid var(--blood);
  outline-offset: 2px;
}

/* ========================================================== the account */

/*
 * The header control.
 *
 * Small, quiet, and last in the nav. The header's job is the wordmark and the
 * one question the site asks; an account menu with any visual weight would be
 * a product arranged around the few people who already pay rather than the
 * many who have not yet read anything.
 */
.account { display: inline-flex; align-items: center; min-height: 1.6rem; }

.linky {
  border: 0; background: none; padding: 0;
  font: inherit; font-size: 0.85rem; color: var(--ink-soft);
  cursor: pointer; text-align: left;
  transition: color 0.2s var(--ease);
}
.linky:hover { color: var(--blood); }

.acct { position: relative; }
.acct > summary {
  list-style: none; cursor: pointer;
  font-size: 0.85rem; color: var(--ink-soft);
  display: inline-flex; align-items: center; gap: 0.4rem;
  max-width: 11rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.acct > summary::-webkit-details-marker { display: none; }
.acct > summary:hover { color: var(--ink); }

/* The one place a non-brand colour earns its keep: subscribed or not is a
   state, not a piece of branding. */
.acct .dot {
  width: 0.4rem; height: 0.4rem; border-radius: 50%;
  background: var(--good); flex: none;
}

.acctmenu {
  position: absolute; right: 0; top: calc(100% + 0.5rem); z-index: 20;
  display: grid; gap: 0.55rem;
  min-width: 11rem; padding: 0.85rem 1rem;
  background: var(--surface);
  border: 1px solid var(--line); border-radius: 0.8rem;
  box-shadow: 0 12px 32px rgb(0 0 0 / 0.1);
}

/* ---------------------------------------------------------- signing in */

.signin { margin-top: 1.1rem; }
.signin .row { display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: center; }
.signin input {
  flex: 1 1 13rem; min-width: 0;
  font: inherit; font-size: 1rem;
  padding: 0.75rem 1rem;
  color: var(--ink); background: var(--page);
  border: 1px solid var(--line); border-radius: 99px;
}
.signin input:focus-visible { outline: 2px solid var(--blood); outline-offset: 1px; }
.signin .bigcta { margin-top: 0; flex: none; }

.sent { margin-top: 1.1rem; font-size: 0.95rem; color: var(--ink); }
.sent strong { font-weight: 600; }

/* An error in the place the explanation already was, rather than an alert. */
.caveat.bad { color: var(--blood); }

/* ------------------------------------------------------------ the price */

.getlist {
  margin: 1.1rem 0 0; padding: 0; list-style: none;
  display: grid; gap: 0.5rem;
  font-size: 0.93rem; color: var(--ink-soft);
}
.getlist li { padding-left: 1.1rem; position: relative; }
.getlist li::before {
  content: ''; position: absolute; left: 0; top: 0.52em;
  width: 0.38rem; height: 0.38rem; border-radius: 50%;
  background: var(--blood);
}

.prices {
  margin-top: 1.4rem;
  display: grid; gap: 0.7rem;
  grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr));
}

.price {
  display: grid; gap: 0.15rem; text-align: left;
  padding: 1.05rem 1.15rem;
  font: inherit; cursor: pointer;
  color: var(--ink); background: var(--surface);
  border: 1px solid var(--line); border-radius: 0.9rem;
  transition: border-color 0.2s var(--ease), transform 0.2s var(--ease);
}
.price:hover { border-color: var(--blood); transform: translateY(-1px); }
.price:active { transform: scale(0.99); }

/* The better-value option is marked rather than merely cheaper per week,
   because the per-week arithmetic is not something to make somebody do. */
.price.best { border-color: var(--ink); }
.price.best:hover { border-color: var(--blood); }

.price .amount {
  font-size: 1.6rem; font-weight: 600; letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}
.price .per { font-size: 0.9rem; font-weight: 550; }
.price .sub { font-size: 0.8rem; color: var(--ink-faint); }

/* ------------------------------------------------------------- the plan */

.detailcta {
  display: flex; flex-wrap: wrap; gap: 0.7rem; align-items: center;
  margin-top: 1.3rem;
}
.detailcta .bigcta, .detailcta .ghostbtn { margin-top: 0; }

.plan {
  margin-top: 1.6rem; padding-top: 1.6rem;
  border-top: 1px solid var(--line);
}
.plan h4 {
  margin: 0.35rem 0 0;
  font-size: 1.25rem; font-weight: 600; letter-spacing: -0.025em;
}
.phorizon { margin: 0.5rem 0 0; font-size: 0.93rem; color: var(--ink-soft); }

.plan h5 {
  margin: 0 0 0.6rem;
  font-size: 0.78rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.09em;
  color: var(--ink-faint);
}

.phases { margin-top: 1.5rem; display: grid; gap: 1.4rem; }

.plan ul {
  margin: 0; padding: 0; list-style: none;
  display: grid; gap: 0.75rem;
}
.plan li {
  display: grid; gap: 0.1rem;
  padding-left: 0.9rem;
  border-left: 2px solid var(--line);
}
.pname { font-size: 0.97rem; font-weight: 550; letter-spacing: -0.012em; }
.pgap { font-size: 0.85rem; color: var(--ink-soft); }
.pnote { margin: -0.25rem 0 0.7rem; font-size: 0.85rem; color: var(--ink-faint); }

/* The first phase is the one somebody is meant to act on this week. */
.phase:first-child li { border-left-color: var(--blood); }

.leadwith, .ptools, .bridge {
  margin-top: 1.7rem; padding-top: 1.4rem;
  border-top: 1px solid var(--line);
}

/* ------------------------------------------------- openings, ranked */

/*
 * The fit number, in the same row as the title.
 *
 * Reuses .job wholesale and adds two things: the score and the reasons for it.
 * A separate list style for ranked openings would have meant two kinds of job
 * row on one page, which reads as two different products.
 */
.job.ranked { align-items: center; }

.job .fit {
  flex: none;
  display: grid; place-items: center;
  width: 2.3rem; height: 2.3rem;
  font-size: 0.85rem; font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--blood);
  border: 1px solid currentColor; border-radius: 50%;
}

.job .why {
  flex: 1 1 100%;
  font-size: 0.8rem; color: var(--ink-faint);
  /* Clear of the badge, so the reasons line up with the title above them. */
  padding-left: 3.3rem;
}

@media (max-width: 30rem) {
  .job .why { padding-left: 0; }
}

/* ========================================================== the wall */

/*
 * Where the three paths would be.
 *
 * Built on .personalise rather than restyled from scratch, because it sits in
 * the same slot under the verdict and should read as the same component. The
 * only difference is that this one is asking for money, so it gets the ruled
 * top edge to separate it from the free half above it.
 */
.wall {
  margin-top: 2.2rem;
  padding: 1.9rem 0 0;
  border-top: 1px solid var(--line);
}
.wall h3 {
  margin: 0.4rem 0 0.7rem;
  font-size: 1.5rem; font-weight: 600; letter-spacing: -0.03em;
}
.wall .why { margin: 0; font-size: 1rem; color: var(--ink-soft); }
.wall .bigcta { margin-top: 1.3rem; }

/* The urgent variant matches the verdict above it: somebody who has just been
   told to start looking should not see the same restrained card as somebody
   told to hold their position. */
.wall.urgent h3 { color: var(--blood); }

@media (max-width: 40rem) {
  .wall h3 { font-size: 1.3rem; }
}

/* ========================================================= the resume */

.resume { margin-top: 1.6rem; padding-top: 1.6rem; border-top: 1px solid var(--line); }
.resume h4 {
  margin: 0.35rem 0 0;
  font-size: 1.25rem; font-weight: 600; letter-spacing: -0.025em;
}
.resume h5 {
  margin: 0 0 0.5rem;
  font-size: 0.78rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.09em;
  color: var(--ink-faint);
}
.resume .titles { margin: 0.7rem 0 0; }

.rsec { margin-top: 1.6rem; }
.rsec ul { margin: 0; padding: 0; list-style: none; display: grid; gap: 0.7rem; }
.rsec li { display: grid; gap: 0.1rem; padding-left: 0.9rem; border-left: 2px solid var(--line); }

/* The three sections are three different instructions, so the rule down the
   side carries the meaning: keep, demote, do not say. */
.rsec.lead  li { border-left-color: var(--good); }
.rsec.bury  li { border-left-color: var(--line); }
.rsec.avoid li { border-left-color: var(--blood); }

.rfoot { margin-top: 1.8rem; }
.rfoot .ghostbtn { margin-bottom: 0.9rem; }

/* The fallback when the clipboard is refused: the text, selectable. */
.rtext {
  margin-top: 1rem; padding: 1rem;
  background: var(--page); border: 1px solid var(--line); border-radius: 0.6rem;
  font: 0.8rem/1.5 ui-monospace, SFMono-Regular, Menlo, monospace;
  white-space: pre-wrap; overflow-x: auto;
  color: var(--ink-soft);
}

/* ------------------------------------------------- stay and adapt, free */

/*
 * The same advice the paid trio opens with, standing on its own for a reader
 * who has not paid. It sits above the wall so the free half ends on something
 * useful rather than on a price.
 */
.freestay { margin-top: 2.2rem; }
.freestay .why { margin: 0.5rem 0 0; font-size: 0.95rem; color: var(--ink-soft); }
.staysplit {
  margin-top: 1.3rem;
  display: grid; gap: 1.4rem;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
}
