    /* One neutral identity, on purpose. This page is shared by a space game, a
       card game, a drag racer and a 1984 drug-dealing sim; branding it as any
       one of them would be wrong for the other four. */
    :root {
        --bg:        #12151a;
        --surface:   #1b2027;
        --surface-2: #232a33;
        --line:      #2f3742;
        --text:      #e6eaf0;
        --muted:     #9aa6b4;
        --accent:    #5ea9e0;
        --accent-dim:#2b4d66;
        --good:      #63c88e;
        --bad:       #e8836b;
        --warn:      #e0b055;
    }

    * { box-sizing: border-box; }

    body {
        margin: 0;
        min-height: 100vh;
        display: grid;
        place-items: center;
        padding: 1.5rem;
        background: var(--bg);
        color: var(--text);
        font: 15px/1.55 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    }

    .card {
        width: 100%;
        max-width: 26rem;
        background: var(--surface);
        border: 1px solid var(--line);
        border-radius: 10px;
        padding: 1.75rem;
    }

    h1 {
        margin: 0 0 .25rem;
        font-size: 1.3rem;
        font-weight: 600;
    }

    .sub {
        margin: 0 0 1.5rem;
        color: var(--muted);
        font-size: .9rem;
    }

    label {
        display: block;
        margin: 0 0 .3rem;
        font-size: .8rem;
        font-weight: 600;
        letter-spacing: .04em;
        text-transform: uppercase;
        color: var(--muted);
    }

    input, select, button {
        font: inherit;
        width: 100%;
    }

    input, select {
        padding: .6rem .7rem;
        margin-bottom: 1rem;
        background: var(--surface-2);
        border: 1px solid var(--line);
        border-radius: 6px;
        color: var(--text);
    }

    input:focus, select:focus, button:focus-visible, a:focus-visible {
        outline: 2px solid var(--accent);
        outline-offset: 1px;
    }

    button {
        padding: .65rem;
        border: 0;
        border-radius: 6px;
        background: var(--accent);
        color: #08131c;
        font-weight: 600;
        cursor: pointer;
    }

    button:hover { filter: brightness(1.08); }
    button[disabled] { opacity: .55; cursor: default; filter: none; }

    button.quiet {
        background: transparent;
        border: 1px solid var(--line);
        color: var(--text);
        font-weight: 500;
    }

    .links {
        display: flex;
        flex-wrap: wrap;
        gap: .25rem 1rem;
        margin-top: 1.1rem;
        padding-top: 1.1rem;
        border-top: 1px solid var(--line);
        font-size: .88rem;
    }

    a { color: var(--accent); text-decoration: none; }
    a:hover { text-decoration: underline; }

    .msg {
        padding: .65rem .8rem;
        border-radius: 6px;
        margin-bottom: 1rem;
        font-size: .9rem;
        border: 1px solid transparent;
    }

    .msg.bad  { background: #2c1a16; border-color: #5a3128; color: var(--bad); }
    .msg.good { background: #15291f; border-color: #2a4f3a; color: var(--good); }
    .msg.warn { background: #2a2415; border-color: #52472a; color: var(--warn); }

    .hidden { display: none; }

    .hint {
        margin: -.6rem 0 1rem;
        font-size: .82rem;
        color: var(--muted);
    }

    .who {
        padding: .8rem;
        background: var(--surface-2);
        border: 1px solid var(--line);
        border-radius: 6px;
        margin-bottom: 1.2rem;
        font-size: .92rem;
    }

    .who strong { color: var(--accent); }

    /* The nudge to set a nickname. Animated for the same reason the password
       helper is (A-11): a static prompt beside other UI gets tuned out.
       Colour-cycled rather than flashing on/off, so it reads as "interactive"
       rather than as an error or status indicator. */
    .who-namebtn {
        margin-left: .5rem;
        border: 1px solid var(--accent);
        border-radius: 5px;
        padding: .15rem .55rem;
        font: inherit;
        font-size: .8rem;
        color: #fff;
        cursor: pointer;
        background: var(--accent);
        animation: who-namebtn-pulse 1.6s ease-in-out infinite;
    }

    @keyframes who-namebtn-pulse {
        0%, 100% { opacity: 1; }
        50% { opacity: .6; }
    }

    @media (prefers-reduced-motion: reduce) {
        .who-namebtn { animation: none; }
    }

    /*
        Exactly two destinations after signing in: back to whichever game sent
        you here (if any), and back to the lab's front page. This used to list
        every registered game -- useful when there was no "you came from
        somewhere" signal to act on, but the ordinary sign-in redirect already
        carries ?return=<the game's URL>, so showing five other games' worth of
        links was just noise between someone and the one place they meant to
        go back to. Styled as real buttons (not text links) since these are the
        two most likely next clicks on the whole page.
    */
    .games { display: grid; gap: .5rem; margin-bottom: 1.2rem; }

    .games a {
        display: block;
        text-align: center;
        padding: .7rem .75rem;
        border-radius: 6px;
        font-weight: 600;
        text-decoration: none;
    }

    .games a.primary { background: var(--accent); color: #08131c; }
    .games a.primary:hover { filter: brightness(1.08); }

    .games a.secondary {
        background: var(--surface-2);
        border: 1px solid var(--line);
        color: var(--text);
    }
    .games a.secondary:hover { border-color: var(--accent-dim); }

    footer {
        margin-top: 1.25rem;
        font-size: .78rem;
        color: var(--muted);
        text-align: center;
    }
    /* The signup honeypot (A-16). Positioned off-screen rather than
       display:none, because some bots deliberately skip fields that are
       display:none -- and a trap a bot can detect is not a trap. Paired in the
       markup with aria-hidden and tabindex="-1" so a screen-reader user is
       never asked to fill in a field that would get them refused. */
    /* ---- The password helper (a shield beside every new-password field) ----

       Attached only to fields where somebody CHOOSES a password, never to the
       one where they type an existing one. On a sign-in form the advice is both
       useless and slightly insulting: the password already exists, and there is
       nothing to reconsider. */

    .pw-row {
        display: flex;
        align-items: center;
        gap: .5rem;
    }

    .pw-row input { flex: 1; min-width: 0; }

    .pw-help {
        flex: 0 0 auto;
        width: 42px;
        height: 42px;
        border-radius: 10px;
        border: 1px solid var(--line);
        background: var(--surface-2);
        cursor: pointer;
        display: grid;
        place-items: center;
        padding: 0;
        /* The animation is the whole point of it being noticed at all: a static
           icon beside a password box reads as decoration and never gets
           clicked. */
        animation: pw-breathe 2.6s ease-in-out infinite;
    }

    .pw-help:hover, .pw-help:focus-visible {
        border-color: var(--accent);
        animation-play-state: paused;
    }

    .pw-help svg { width: 24px; height: 24px; display: block; }

    /* The shield's fill sweeps through the palette rather than sitting on one
       colour, so it reads as "interactive" instead of "status indicator". A
       colour that stays put next to a form field looks like validation state,
       which is the one thing it must not be mistaken for. */
    .pw-help .shield {
        animation: pw-hue 8s linear infinite;
        transform-origin: center;
    }

    @keyframes pw-breathe {
        0%, 100% { transform: scale(1); }
        50%      { transform: scale(1.08); }
    }

    @keyframes pw-hue {
        0%   { fill: #6aa9ff; }
        25%  { fill: #7ee0c0; }
        50%  { fill: #ffd166; }
        75%  { fill: #ff8fa3; }
        100% { fill: #6aa9ff; }
    }

    /* Anybody who has asked their system not to animate things gets a still
       icon. The advice is the feature; the movement is only a way of pointing
       at it, and it is not worth making somebody feel unwell over. */
    @media (prefers-reduced-motion: reduce) {
        .pw-help, .pw-help .shield { animation: none; }
        .pw-help .shield { fill: #6aa9ff; }
    }

    .pw-note {
        display: none;
        margin: .6rem 0 0;
        padding: .8rem .9rem;
        background: var(--surface-2);
        border: 1px solid var(--line);
        border-left: 3px solid var(--accent);
        border-radius: 8px;
        font-size: .86rem;
        line-height: 1.5;
        color: var(--text);
    }
    .or-divider {
        display: flex;
        align-items: center;
        gap: .6rem;
        margin: 1rem 0;
        color: var(--muted);
        font-size: .8rem;
    }

    .or-divider::before, .or-divider::after {
        content: '';
        flex: 1;
        height: 1px;
        background: var(--line);
    }

    .btn-google {
        display: flex;
        align-items: center;
        justify-content: center;
        gap: .6rem;
        width: 100%;
        min-height: 44px;
        padding: .6rem 1rem;
        background: #fff;
        color: #3c4043;
        border: 1px solid var(--line);
        border-radius: 8px;
        font: inherit;
        font-weight: 500;
        text-decoration: none;
        box-sizing: border-box;
    }

    .btn-google:hover { background: #f8f8f8; }
    .btn-google svg { width: 20px; height: 20px; flex: 0 0 auto; }


    .pw-note.open { display: block; }
    .pw-note strong { color: var(--accent); }
    .pw-note ul { margin: .5rem 0 0; padding-left: 1.1rem; }
    .pw-note li { margin: .25rem 0; }
    .pw-note .pw-lead { margin: 0 0 .5rem; }
    .pw-note a { text-decoration: underline; }

    .hp-field {
        position: absolute;
        left: -9999px;
        width: 1px;
        height: 1px;
        overflow: hidden;
    }
