
  /* UNTIL brand system: navy on bone, Tungsten Semibold display, DIN 2014 body.
     No green, no yellow, no em dashes, no emoji.
     Palette follows the UNTIL Design System (claude.ai/design) and S3.3 Colour
     Palette in the Brand Strategy Workspace. This file previously ran a Blue 800
     dark ground citing BRAND-USAGE.md; see the :root note below for why it moved. */
  /* font-display: swap — without it the browser hides all text until the .otf
     files land (~200KB over a cold serverless start), so the first screen shows
     a blank page rather than the question. Swap renders in the fallback and
     upgrades when the brand font arrives. */
  @font-face { font-family: "Tungsten"; src: url("/fonts/Tungsten-Semibold.otf") format("opentype"); font-weight: 600; font-display: swap; }
  @font-face { font-family: "DIN 2014"; src: url("/fonts/DIN-2014-Regular.otf") format("opentype"); font-weight: 400; font-display: swap; }
  @font-face { font-family: "DIN 2014"; src: url("/fonts/DIN-2014-Bold.otf") format("opentype"); font-weight: 700; font-display: swap; }
  /* ---------------------------------------------------------------------
     Navy on bone, per the UNTIL Design System and the brand strategy.

     S3.3 Colour Palette in the Brand Strategy Workspace specifies the
     structure: the neutral base is "the canvas everything lives on ... likely
     warm off-white", the primary must be "WCAG AA accessible on white", and
     the dark is "deep contrast for type and structure". That describes a light
     canvas with navy ink. A dark ground appears nowhere in the brand work.

     It matters for this product in particular: the quiz is ~120 questions of
     continuous reading on a phone, often in a daylit club, and the
     Practitioner Card is meant to be screenshotted and shared — it should look
     like until.co.uk.

     The payoff panels stay navy (inverted-panel block below), so the reveals
     keep their ceremony. The design system asks for exactly that rhythm:
     "alternate bone -> navy -> bone for chapter rhythm".
     --------------------------------------------------------------------- */
  :root {
    --bg: #F5F1EA;        /* Bone — the canvas */
    --bg-deep: #EDE6D8;   /* Cream — warmer surface */
    --card: #FFFFFF;      /* Paper. Cards and inputs "feel filled in" */
    --card2: #FFFFFF;
    --text: #020417;      /* Navy — primary ink, straight off the logo */
    --muted: #5B607A;     /* Secondary copy */
    --accent: #020417;    /* Navy. CTAs are navy on bone, not a bright fill */
    --accent-text: #F5F1EA;
    --line: rgba(2, 4, 23, 0.18);
    --line-dim: rgba(2, 4, 23, 0.10);   /* the brand's hairline */
    --active: #2F3D80;    /* Navy 500 — hover / active */
    --clay: #C9A98A;      /* Warm accent, sparingly, on navy panels only */
    --sage: #5A6B4A;      /* Moss */
    --radius: 10px;
  }
  * { box-sizing: border-box; margin: 0; padding: 0; }
  body {
    background: var(--bg); color: var(--text);
    font-family: "DIN 2014", "Segoe UI", Helvetica, sans-serif;
    min-height: 100vh; display: flex; justify-content: center;
  }
  #app { width: 100%; max-width: 520px; padding: 20px 16px 60px; }
  /* The right-hand slot carries the round name, and round names are long
     ("Would you rather: business edition"). With only space-between holding
     them apart, it ran straight into the logo at 320px — zero gap, wrapping to
     two lines against a 16px wordmark. The logo needs its clearspace: the
     design system asks for the height of the cap U on every side.
     So: a real gap, the wordmark refuses to shrink, and the label is capped at
     just over half the width and right-aligned so it wraps away from the logo
     rather than into it. */
  header { padding: 18px 0 6px; display: flex; align-items: center;
           justify-content: space-between; gap: 20px; }
  .logo { flex: 0 0 auto; }
  .logo img { height: 16px; display: block; }
  .step-ind { color: var(--muted); font-size: 11px; font-weight: 700;
              letter-spacing: .12em; text-transform: uppercase;
              text-align: right; max-width: 58%; line-height: 1.25; }
  /* clamp, because a fixed 52px overflowed the welcome headline on a 320px
     phone — the narrow end of the range this quiz is actually taken on. */
  h1 { font-family: "Tungsten", "Arial Narrow", sans-serif; font-weight: 600;
       font-size: clamp(38px, 13vw, 52px); line-height: .95; margin: 20px 0 10px;
       text-transform: uppercase; letter-spacing: 0; }
  h2 { font-family: "Tungsten", "Arial Narrow", sans-serif; font-weight: 600;
       font-size: 34px; line-height: 1; margin: 20px 0 8px; text-transform: uppercase; }
  p.lead { color: var(--muted); font-size: 15px; line-height: 1.55; }
  .card {
    background: var(--card); border: 1px solid var(--line-dim);
    border-radius: var(--radius); padding: 18px; margin: 14px 0;
  }
  .card h3 { font-family: "Tungsten", "Arial Narrow", sans-serif; font-weight: 600;
             font-size: 26px; text-transform: uppercase; margin-bottom: 4px; }
  .card p { color: var(--muted); font-size: 13.5px; line-height: 1.45; }
  .badge { display: inline-block; font-size: 10px; font-weight: 700; letter-spacing: .18em;
           text-transform: uppercase; padding: 4px 11px; border-radius: 99px;
           background: transparent; color: var(--muted); border: 1px solid var(--line); margin-top: 10px; }
  .badge.done { color: var(--accent-text); background: var(--accent); border-color: var(--accent); }
  button, .btn {
    appearance: none; border: 0; cursor: pointer;
    font-family: "DIN 2014", sans-serif; font-weight: 700; font-size: 13px;
    letter-spacing: .08em; text-transform: uppercase;
    border-radius: 8px; padding: 15px 18px; width: 100%; min-height: 48px;
    background: var(--accent); color: var(--accent-text); margin-top: 12px;
  }
  button.secondary { background: transparent; color: var(--text); border: 1px solid var(--line); }
  button:disabled { opacity: .4; cursor: default; }
  label { display: block; font-size: 11px; font-weight: 700; letter-spacing: .18em;
          text-transform: uppercase; color: var(--muted); margin: 16px 0 6px; }
  /* 16px is a hard floor on form controls, not a design preference.
     iOS Safari zooms the whole page in when you focus a field smaller than 16px,
     and it never zooms back out — so tapping the name box on the first screen
     leaves the quiz zoomed for the rest of the session and the person has to
     pinch it back themselves. Reported on an iPhone 17 Pro Max at 15px.
     The other "fix" for this is maximum-scale=1 or user-scalable=no in the
     viewport tag. Do not do that: it takes pinch-zoom away from everyone, which
     is a WCAG failure and undoes the accessibility work in this same file. */
  input[type=text], input[type=email], select, textarea {
    width: 100%; background: var(--card2); color: var(--text);
    border: 1px solid var(--line-dim); border-radius: 8px; padding: 12px;
    font-family: "DIN 2014", sans-serif; font-size: 16px;
  }
  textarea { min-height: 74px; resize: vertical; }

  /* Saving between rounds. A submit is not a quick write: it stores the answers,
     recomputes the whole profile, and writes brain files out to GitHub, so on a
     cold serverless start it can run to several seconds. A static "Saving…"
     heading reads as a frozen app, and people back out and lose the round.
     Motion is the whole point — it says the thing is still working.
     A CSS ring rather than a GIF: no binary asset in a repo that already carries
     licensed fonts, sharp at any pixel density, and it uses the brand palette. */
  .saving { text-align: center; padding: 46px 0 30px; }
  .spinner { width: 42px; height: 42px; margin: 0 auto 24px; border-radius: 50%;
             border: 3px solid var(--line-dim); border-top-color: var(--accent);
             animation: spin .8s linear infinite; }
  /* Both @keyframes stay at the top level. Safari does not reliably register a
     @keyframes nested inside @media, and when the name fails to resolve the
     element simply sits there — which is exactly what happened on an iPhone with
     Reduce Motion switched on: the ring rendered and never turned. Nesting it was
     tidier to read and quietly broken on the one browser most of these
     practitioners are using. */
  @keyframes spin { to { transform: rotate(360deg); } }
  @keyframes pulse { 50% { opacity: .3; } }
  /* Continuous rotation is a motion-sickness trigger for some people, so under a
     reduced-motion preference it pulses instead. Still clearly alive. */
  @media (prefers-reduced-motion: reduce) {
    .spinner { animation: pulse 1.6s ease-in-out infinite; }
  }
  /* Whose answer this is: personal, clients, business, or how they coach.
     Practitioner quiz only. Sits directly above the question so it reads as part
     of the question rather than as page chrome. */
  .lens { color: var(--accent); font-size: 11px; font-weight: 700;
          letter-spacing: 2px; text-transform: uppercase; margin: 26px 0 0; }
  .lens + .q { margin-top: 6px; }
  .card .lens { margin: 0 0 6px; }
  .q { margin: 24px 0 14px; }
  .q .qt { font-family: "Tungsten", "Arial Narrow", sans-serif; font-weight: 600;
           font-size: 30px; line-height: 1.02; text-transform: uppercase; margin-bottom: 13px; }
  .opts { display: flex; flex-direction: column; gap: 8px; }
  .opt {
    background: var(--card2); border: 1.5px solid var(--line-dim); border-radius: 8px;
    padding: 13px 14px; cursor: pointer; font-size: 14.5px; line-height: 1.35;
    min-height: 44px;
  }
  .opt.sel { border-color: var(--accent); background: var(--card); color: var(--accent); }
  .likert { display: flex; gap: 6px; }
  .likert .opt { flex: 1; text-align: center; padding: 12px 2px; font-size: 14px; font-weight: 700;
                 min-height: 48px; display: flex; align-items: center; justify-content: center; }
  .lk-ends { display: flex; justify-content: space-between; color: var(--muted);
             font-size: 10px; letter-spacing: 2px; text-transform: uppercase; margin-top: 6px; }
  .chips { display: flex; flex-wrap: wrap; gap: 8px; }
  .chip {
    background: transparent; border: 1.5px solid var(--line); border-radius: 99px;
    padding: 10px 16px; cursor: pointer; font-size: 13.5px; color: var(--text);
    min-height: 44px; display: inline-flex; align-items: center;
  }
  .chip.sel { border-color: var(--accent); background: var(--accent); color: var(--accent-text); font-weight: 700; }
  .duel { display: flex; gap: 10px; }
  .duel .who {
    flex: 1; background: var(--card2); border: 2px solid var(--line-dim); border-radius: var(--radius);
    padding: 18px 10px 14px; text-align: center; cursor: pointer;
  }
  .duel .who.sel { border-color: var(--accent); background: var(--card); }
  .avatar {
    width: 64px; height: 64px; border-radius: 50%; margin: 0 auto 10px;
    display: flex; align-items: center; justify-content: center;
    font-family: "Tungsten", sans-serif; font-weight: 600; font-size: 26px; color: var(--text);
  }
  /* The illustrated version: a wide tile rather than an avatar bubble, so the
     card reads as a picture of the idea instead of a chip with initials in it. */
  .avatar.art {
    width: 100%; height: 76px; border-radius: 10px; background: var(--bg-deep);
    border: 1px solid var(--line-dim);
  }
  .avatar.art svg {
    width: 38px; height: 38px; fill: none; stroke: var(--accent);
    stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round;
  }
  /* Selected state lives with the other selected states at the foot of this file,
     so it reads against the bone palette rather than fighting it. */
  .who .nm { font-weight: 700; font-size: 14px; }
  .who .tag { color: var(--muted); font-size: 11.5px; margin-top: 3px; }
  .dontknow { text-align: center; color: var(--muted); font-size: 12px; letter-spacing: .12em;
              text-transform: uppercase; margin-top: 12px; cursor: pointer;
              text-decoration: underline; text-underline-offset: 3px;
              min-height: 44px; display: flex; align-items: center; justify-content: center; }
  .dontknow.sel { color: var(--accent); }
  .progress { height: 4px; background: var(--card2); border-radius: 99px; margin: 12px 0 4px; overflow: hidden; }
  .progress i { display: block; height: 100%; background: var(--accent); border-radius: 99px; transition: width .25s; }
  .progress.big { height: 8px; margin: 16px 0 10px; }
  .slider-val { font-family: "Tungsten", sans-serif; font-weight: 600; font-size: 64px;
                color: var(--accent); text-align: center; margin: 18px 0 8px; }
  input[type=range] { width: 100%; accent-color: var(--active); height: 34px; }
  .pov { border-color: var(--accent); }
  .pov .arch { font-family: "Tungsten", sans-serif; font-weight: 600; font-size: 42px;
               line-height: .95; text-transform: uppercase; margin: 8px 0; color: var(--accent); }
  .axisrow { margin: 12px 0; }
  .axisrow .lbls { display: flex; justify-content: space-between; font-size: 10px;
                   letter-spacing: 2px; text-transform: uppercase; color: var(--muted); margin-bottom: 5px; }
  .axisbar { height: 6px; background: var(--card2); border-radius: 99px; position: relative; }
  .axisbar i { position: absolute; top: -4px; width: 14px; height: 14px; border-radius: 50%;
               background: var(--accent); transform: translateX(-50%); }
  .footnote { color: var(--muted); font-size: 12px; margin-top: 26px; line-height: 1.5; }
  .probe-quote { margin: 22px 0 0; padding: 12px 14px; border-left: 2px solid var(--accent);
                 background: var(--card2); border-radius: 0 8px 8px 0; color: var(--muted);
                 font-size: 14px; font-style: italic; line-height: 1.45; }
  /* Practitioner Card — the shareable artefact */
  #pcard {
    /* Navy, not the old Blue 700-900 ramp. This is the artefact people
       screenshot, so it is the one surface that most needs to look like the
       brand. Kept as a gradient rather than a flat fill because it reads as a
       membership card rather than a panel; the range is narrow enough that the
       design system's "flat colour, not gradients" rule still holds in spirit. */
    background: linear-gradient(160deg, #131C4D 0%, #050925 55%, #020417 100%);
    border: 1px solid var(--line); border-radius: 14px;
    padding: 24px 22px 16px; margin: 16px 0;
    box-shadow: 0 18px 40px rgba(1, 3, 14, .55);
  }
  .pcard-top { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; }
  .pcard-top img { height: 13px; }
  .pcard-top span { color: var(--muted); font-size: 10px; font-weight: 700;
                    letter-spacing: .18em; text-transform: uppercase; }
  /* clamp: a long single-word surname pushed this 28px outside the card at
     320px, and a name has no space to wrap at. See the small-phone block. */
  .pcard-name { font-family: "Tungsten", "Arial Narrow", sans-serif; font-weight: 600;
                font-size: clamp(32px, 11vw, 46px); line-height: .95; text-transform: uppercase; }
  .pcard-disc { color: var(--muted); font-size: 10px; font-weight: 700;
                letter-spacing: 3px; text-transform: uppercase; margin-top: 4px; }
  .pcard-arch { font-family: "Tungsten", sans-serif; font-weight: 600; font-size: 30px;
                text-transform: uppercase; color: var(--accent); margin-top: 16px; line-height: .95; }
  .pcard-match { color: var(--muted); font-size: 12.5px; margin-top: 4px; line-height: 1.4; }
  .pcard-divider { height: 1px; background: var(--line-dim); margin: 14px 0; }
  .pcard-grid { display: flex; flex-direction: column; gap: 7px; }
  .pcard-grid b { display: block; color: var(--muted); font-size: 10px; font-weight: 700;
                  letter-spacing: .18em; text-transform: uppercase; margin-bottom: 1px; }
  .pcard-grid span { font-size: 14px; }
  .pcard-quote { margin-top: 12px; color: var(--text); font-size: 14px; font-style: italic; line-height: 1.45; }
  .pcard-foot { display: flex; align-items: center; gap: 10px; color: var(--muted);
                font-size: 10px; letter-spacing: 2px; text-transform: uppercase; }
  .pcard-foot .conf { flex: 1; height: 4px; background: var(--card2); border-radius: 99px; overflow: hidden; }
  .pcard-foot .conf i { display: block; height: 100%; background: var(--accent); }
  .pcard-locked { margin-top: 12px; text-align: center; color: var(--muted); font-size: 10px;
                  font-weight: 700; letter-spacing: 3px; text-transform: uppercase; }
  #pcard .axisrow { margin: 8px 0; }
  .locked-line { margin-top: 34px; text-align: center; color: var(--muted); font-size: 10px;
                 font-weight: 700; letter-spacing: 3px; text-transform: uppercase; }
  a { color: var(--accent); }
  .consent { display: flex; gap: 10px; align-items: flex-start; margin-top: 16px; }
  .consent input { width: 20px; height: 20px; margin-top: 2px; accent-color: var(--active); }
  .consent span { font-size: 13px; color: var(--muted); line-height: 1.5; }

  /* Predict-then-reveal. The lead line sets up the guess; the reveal card
     shows underneath the identity so the result lands first. */
  .predict-lead { color: var(--accent); font-size: 12px; font-weight: 700;
    letter-spacing: .08em; text-transform: uppercase; margin: 26px 0 2px; }
  .opt.predict-opt { display: flex; flex-direction: column; gap: 3px; align-items: flex-start; }
  .opt.predict-opt b { color: var(--text); font-size: 15px; font-weight: 700; }
  .opt.predict-opt span { color: var(--muted); font-size: 12.5px; line-height: 1.35; }
  .opt.predict-opt.sel b { color: var(--accent); }
  .card.reveal { border-color: var(--accent); }
  .card.reveal.miss { border-style: dashed; }
  .reveal-t { color: var(--accent) !important; font-size: 12px !important;
    font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
  .reveal-b { color: var(--text) !important; font-size: 14.5px !important;
    line-height: 1.5 !important; margin-top: 6px; }
  .reveal-b b { color: var(--accent); }

  /* ---------------------------------------------------------------------
     Keyboard, focus and press states.

     Every answer control in this quiz is a <div> with an onclick — options,
     chips, duel cards, the "no idea" link. That made the whole thing
     mouse-or-touch only: no tab stop, no focus ring, nothing announced to a
     screen reader, and no way to finish a round from a keyboard. The JS side
     gives them role/tabindex/aria-pressed; this is the visible half.

     :focus-visible rather than :focus, so a mouse click doesn't leave a ring
     behind but a Tab key does. The ring is an outline with an offset rather
     than a border change, because borders here already carry the selected
     state and the two must stay tellable apart.
     --------------------------------------------------------------------- */
  :where(.opt, .chip, .who, .dontknow, button, a, input, select, textarea):focus-visible {
    outline: 3px solid var(--accent);
    outline-offset: 2px;
    border-radius: 8px;
  }
  /* Inputs get the brand's 2pt ring on focus, per the design system. */
  input[type=text]:focus, input[type=email]:focus, select:focus, textarea:focus {
    outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent);
  }

  /* Hover and press. The design system asks for a small, unshowy response:
     no scale, no bounce. Pointer-only, so a touch device doesn't get a hover
     state stuck on after a tap. */
  @media (hover: hover) {
    .opt:hover, .chip:hover, .who:hover { border-color: var(--line); }
    button:hover:not(:disabled) { filter: brightness(1.08); }
  }
  .opt:active, .chip:active, .who:active, button:not(:disabled):active {
    transform: translateY(1px);
  }
  .opt, .chip, .who, button { transition: border-color var(--dur, 140ms) ease,
                                          background-color 140ms ease,
                                          transform 60ms ease; }

  /* Someone tabbing through should be able to skip the logo and land on the
     first real control, and any keyboard user needs to see where they are. */
  @media (prefers-reduced-motion: reduce) {
    .opt, .chip, .who, button, .progress i { transition: none; }
    .opt:active, .chip:active, .who:active, button:active { transform: none; }
  }

  /* ---------------------------------------------------------------------
     Inverted panels — bone -> navy -> bone.

     The questions want a light canvas for readability. The payoffs want
     weight: the archetype landing, the predict-then-reveal comparison, and
     the Practitioner Card are the moments people screenshot. The design
     system's own rhythm rule covers exactly this, so those panels invert to
     navy rather than losing their ceremony to a white page.

     Done by re-declaring the tokens inside the panel, so everything nested
     picks up the inverted values without a parallel set of rules.
     --------------------------------------------------------------------- */
  .card.pov, .card.reveal, #pcard {
    --card: #020417;
    --card2: #0A1138;           /* navy-800, the design system's own step */
    --text: #F5F1EA;
    --muted: rgba(245, 241, 234, 0.68);
    --accent: #C9A98A;          /* clay — the warm note, on navy only */
    --line: rgba(245, 241, 234, 0.22);
    --line-dim: rgba(245, 241, 234, 0.16);
    background: var(--card);
    border-color: var(--line-dim);
    color: var(--text);
  }
  .card.pov p, .card.reveal p, #pcard p { color: var(--muted); }
  .card.pov .arch, #pcard .pcard-arch { color: var(--accent); }
  .card.reveal { border-color: var(--accent); }
  /* The axis dials sit inside the card, so their track needs the inverted line */
  .card.pov .axisbar, #pcard .axisbar { background: rgba(245, 241, 234, 0.16); }
  .card.pov .axisbar i, #pcard .axisbar i { background: var(--accent); }

  /* On bone, a card is white with a hairline and no shadow at rest — the design
     system is explicit that shadows only appear on hover. */
  .card { box-shadow: none; }
  @media (hover: hover) {
    .card:hover { box-shadow: 0 8px 20px rgba(2,4,23,0.08), 0 2px 6px rgba(2,4,23,0.05); }
    .card.pov:hover, .card.reveal:hover, #pcard:hover { box-shadow: none; }
  }

  /* Selected states. On a light canvas a selected option reads as navy ink on a
     tinted fill rather than as a glowing border. */
  .opt.sel { border-color: var(--text); background: rgba(2, 4, 23, 0.05); color: var(--text); font-weight: 700; }
  .chip.sel { border-color: var(--text); background: var(--text); color: #F5F1EA; }
  .duel .who.sel { border-color: var(--text); background: rgba(2, 4, 23, 0.05); }
  /* The illustrated tile inverts when chosen, the same move as .chip.sel. My first
     version of this was written for the old dark ground and set a navy fill with a
     navy stroke — invisible once the palette went to bone. */
  .who.sel .avatar.art { background: var(--text); border-color: var(--text); }
  .who.sel .avatar.art svg { stroke: #F5F1EA; }
  .badge.done { color: #F5F1EA; background: var(--text); border-color: var(--text); }
  .progress { background: rgba(2, 4, 23, 0.10); }
  .progress i { background: var(--text); }
  .axisbar { background: rgba(2, 4, 23, 0.10); }
  .axisbar i { background: var(--text); }
  .slider-val { color: var(--text); }
  .predict-lead { color: var(--muted); }
  .lens { color: var(--muted); }
  .spinner { border-color: rgba(2, 4, 23, 0.12); border-top-color: var(--text); }
  .probe-quote { border-left-color: var(--text); background: var(--bg-deep); }
  /* The card artefact keeps its own navy gradient; only the border needs redoing. */
  #pcard { border-color: rgba(245, 241, 234, 0.22); }

  /* ---------------------------------------------------------------------
     Small-phone fit.

     Found at 320px: a practitioner with a long single-word surname pushed
     .pcard-name 28px outside the card. Tungsten is condensed but 46px is still
     46px, and a name is one unbreakable token — it cannot wrap at a space that
     isn't there. That lands on the Practitioner Card, which is the thing people
     screenshot, so it is the worst possible place for it.

     Two guards: the display name scales with the viewport, and any element
     carrying text somebody typed is allowed to break a word rather than
     overflow. break-word, not anywhere, so ordinary words still wrap normally
     and only genuinely unbreakable ones are split.
     --------------------------------------------------------------------- */
  .pcard-name, .pcard-quote, .pcard-grid span, .pcard-disc,
  .probe-quote, .card p, .opt, p.lead, .reveal-b, .arch, .qt, h1, h2 {
    overflow-wrap: break-word;
  }
