# Account pages

> Sign in, password reset, one-time login, change password, change email and the sign-in-to-continue state, each in one centred auth card.

- Recipe: R7
- Page kind: utility
- Serves: /user/login, /user/password, /user/reset/{uid}/{timestamp}/{hash}, /user/{uid}/password, /user/{uid}/email, 403 (anonymous)
- Base page: /user/login
- Components: auth-card (https://brand.honorsociety.org/components/auth-card/), form (https://brand.honorsociety.org/components/form/), form-note (https://brand.honorsociety.org/components/form-note/), confirmation-panel (https://brand.honorsociety.org/components/confirmation-panel/), button (https://brand.honorsociety.org/components/button/), callout (https://brand.honorsociety.org/components/callout/), heading (https://brand.honorsociety.org/components/heading/), band (https://brand.honorsociety.org/components/band/)
- HTML page: https://brand.honorsociety.org/recipes/r7-account-pages/

## Overview

**Serves:** /user/login, /user/password, the one-time login page /user/reset/{uid}/{timestamp}/{hash}, /user/{uid}/password, /user/{uid}/email, and the access-denied page for a visitor. **Base page:** /user/login. **Page kind:** utility. [All recipes](/recipes/)

**How to use this recipe:** it shows a proven page shape, not a fixed template. Start from the closest recipe, choose the components that fit the content, combine them as needed and leave out what does not fit. Only the component rules are fixed: grounds, one gold element per viewport, heading order, marks and the rules on each component page.

**Layout, every screen:** one white band, one [Auth card](/components/auth-card/) in the centre (at most 560px), one quiet line under it where the screen needs one. The site header, menu and footer stay as they are.

**Card order:** head (H1 at the h2 size, intro), an optional notice or form alert, the form ending in one full-width gold button, a hairline, the support note.

**Components:** auth-card, form (fields, password field with the eye toggle, form alert), form-note (form link, divider, support note), confirmation-panel, button (`--block`), callout (`--info` for the signed-in notice), heading, band.

**Rules:**

- The card heading is the page `h1`. The template prints no page head and no second title on these routes. The card is the head band of these screens: it holds the one `h1`.
- One gold element per card: the submit button. Every other route is a `.hs-form-link`, and the heading has no gold rule.
- `Honor Society®` on the first visible reference of each screen, `Honor Society` after it. The header logo does not count.
- Give every field its `autocomplete`: `username` on the sign-in email, `email` on every other email field, `current-password` on a password the member already has, `new-password` on a new one. Email fields take `type="email"`.
- Keep the Drupal form whole: the field `name` attributes, the hidden `form_build_id`, `form_id` and `form_token`, and every element another module adds. The snippets show the hidden fields as placeholders.
- No `target="_blank"`. The help center opens in the same tab.
- This page loads no script, so the eye toggles stay hidden here, as they do without `password.js`. Try them on the [Auth card](/components/auth-card/) page.

## Sign in

`/user/login`, for a visitor. Form `user_login`.

```html
<!-- BAND: the route's content area. The template prints no page head and no title here: the card holds the H1. -->
<section class="hs-band" data-section="sign-in" aria-labelledby="si-h">
  <div class="hs-container">
    <div class="hs-auth">
      <div class="hs-auth__card">
        <header class="hs-auth__head">
          <h1 class="hs-heading hs-heading--h2" id="si-h">Honor Society&reg; login</h1>
          <p class="hs-auth__intro">Welcome back. Sign in to your account.</p>
        </header>
        <!-- Drupal status messages (for example after sign-out) print here as callouts, under the head. -->
        <form class="hs-form" action="/user/login" method="post" id="user-login" accept-charset="UTF-8">
          <div class="hs-field">
            <label class="hs-label" for="edit-name">Email address</label>
            <input class="hs-control" id="edit-name" name="name" type="email" autocomplete="username" spellcheck="false" autocapitalize="none" maxlength="254" required>
          </div>
          <div class="hs-field hs-password">
            <label class="hs-label" for="edit-pass">Password</label>
            <div class="hs-password__input">
              <input class="hs-control" id="edit-pass" name="pass" type="password" autocomplete="current-password" maxlength="128" required>
              <button class="hs-password__toggle" type="button" aria-label="Show password" aria-pressed="false" aria-controls="edit-pass" hidden>
                <svg class="hs-password__icon hs-password__icon--show" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M2 12s3.6-7 10-7 10 7 10 7-3.6 7-10 7S2 12 2 12z"/><circle cx="12" cy="12" r="3"/></svg><svg class="hs-password__icon hs-password__icon--hide" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10.6 5.1A10.4 10.4 0 0 1 12 5c6.4 0 10 7 10 7a17.6 17.6 0 0 1-2.6 3.5M6.6 6.6C3.7 8.5 2 12 2 12s3.6 7 10 7a9.9 9.9 0 0 0 5.4-1.6"/><path d="M9.9 9.9a3 3 0 0 0 4.2 4.2"/><path d="M3 3l18 18"/></svg>
              </button>
            </div>
            <p class="hs-hint"><a class="hs-form-link" href="/user/password" data-ph-capture-attribute-cta="reset-password" data-ph-capture-attribute-cta-loc="sign-in">Forgot your password?</a></p>
          </div>
          <!-- Hidden fields: printed by Form API, never hand-written. -->
          <input type="hidden" name="form_build_id" value="form-PLACEHOLDER">
          <input type="hidden" name="form_id" value="user_login">
          <button class="hs-button hs-button--block" id="edit-submit" name="op" value="Sign in" type="submit" data-ph-capture-attribute-cta="sign-in" data-ph-capture-attribute-cta-loc="sign-in">Sign in</button>
        </form>
        <hr class="hs-form-divider">
        <p class="hs-form-note"><strong>Need help signing in?</strong> Visit our <a class="hs-form-link" href="https://support.honorsociety.org/hc/en-us" data-ph-capture-attribute-cta="help-center" data-ph-capture-attribute-cta-loc="sign-in">Help Center</a> or <a class="hs-form-link" href="https://support.honorsociety.org/hc/en-us/requests/new" data-ph-capture-attribute-cta="support-request" data-ph-capture-attribute-cta-loc="sign-in">contact Honor Society support</a>.</p>
      </div>
      <p class="hs-auth__alt">New to Honor Society? <a class="hs-form-link" href="/join" data-ph-capture-attribute-cta="join" data-ph-capture-attribute-cta-loc="sign-in">Join now</a></p>
    </div>
  </div>
</section>
```

## Sign in, failed

The same page after a wrong email address or password. The form alert sits under the head and takes focus; the email field keeps its value and shows the error; the password field is empty.

```html
<section class="hs-band" data-section="sign-in" aria-labelledby="sf-h">
  <div class="hs-container">
    <div class="hs-auth">
      <div class="hs-auth__card">
        <header class="hs-auth__head">
          <h1 class="hs-heading hs-heading--h2" id="sf-h">Honor Society&reg; login</h1>
          <p class="hs-auth__intro">Welcome back. Sign in to your account.</p>
        </header>
        <div class="hs-callout hs-callout--danger hs-form-alert" role="alert" tabindex="-1">
          <svg class="hs-callout__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="9"/><path d="M12 7.5v5.5"/><path d="M12 16.4v.1"/></svg>
          <div class="hs-callout__body">
            <p class="hs-callout__title">Your email address or password is not correct</p>
            <ul class="hs-form-alert__list">
              <li><a href="#edit-name--2">Check your email address and password, then sign in again.</a></li>
            </ul>
          </div>
        </div>
        <form class="hs-form" action="/user/login" method="post" id="user-login--2" accept-charset="UTF-8">
          <div class="hs-field">
            <label class="hs-label" for="edit-name--2">Email address</label>
            <input class="hs-control" id="edit-name--2" name="name" type="email" autocomplete="username" spellcheck="false" autocapitalize="none" maxlength="254" value="avery.example@example.com" aria-invalid="true" aria-describedby="edit-name--2-error" required>
            <p class="hs-field-error" id="edit-name--2-error">Check your email address and password.</p>
          </div>
          <div class="hs-field hs-password">
            <label class="hs-label" for="edit-pass--2">Password</label>
            <div class="hs-password__input">
              <input class="hs-control" id="edit-pass--2" name="pass" type="password" autocomplete="current-password" maxlength="128" required>
              <button class="hs-password__toggle" type="button" aria-label="Show password" aria-pressed="false" aria-controls="edit-pass--2" hidden>
                <svg class="hs-password__icon hs-password__icon--show" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M2 12s3.6-7 10-7 10 7 10 7-3.6 7-10 7S2 12 2 12z"/><circle cx="12" cy="12" r="3"/></svg><svg class="hs-password__icon hs-password__icon--hide" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10.6 5.1A10.4 10.4 0 0 1 12 5c6.4 0 10 7 10 7a17.6 17.6 0 0 1-2.6 3.5M6.6 6.6C3.7 8.5 2 12 2 12s3.6 7 10 7a9.9 9.9 0 0 0 5.4-1.6"/><path d="M9.9 9.9a3 3 0 0 0 4.2 4.2"/><path d="M3 3l18 18"/></svg>
              </button>
            </div>
            <p class="hs-hint"><a class="hs-form-link" href="/user/password" data-ph-capture-attribute-cta="reset-password" data-ph-capture-attribute-cta-loc="sign-in">Forgot your password?</a></p>
          </div>
          <input type="hidden" name="form_build_id" value="form-PLACEHOLDER">
          <input type="hidden" name="form_id" value="user_login">
          <button class="hs-button hs-button--block" name="op" value="Sign in" type="submit" data-ph-capture-attribute-cta="sign-in" data-ph-capture-attribute-cta-loc="sign-in">Sign in</button>
        </form>
        <hr class="hs-form-divider">
        <p class="hs-form-note"><strong>Need help signing in?</strong> Visit our <a class="hs-form-link" href="https://support.honorsociety.org/hc/en-us" data-ph-capture-attribute-cta="help-center" data-ph-capture-attribute-cta-loc="sign-in">Help Center</a> or <a class="hs-form-link" href="https://support.honorsociety.org/hc/en-us/requests/new" data-ph-capture-attribute-cta="support-request" data-ph-capture-attribute-cta-loc="sign-in">contact Honor Society support</a>.</p>
      </div>
      <p class="hs-auth__alt">New to Honor Society? <a class="hs-form-link" href="/join" data-ph-capture-attribute-cta="join" data-ph-capture-attribute-cta-loc="sign-in">Join now</a></p>
    </div>
  </div>
</section>
```

## Reset password request

`/user/password`, for a visitor. Form `user_pass`.

```html
<section class="hs-band" data-section="reset-password" aria-labelledby="rp-h">
  <div class="hs-container">
    <div class="hs-auth">
      <div class="hs-auth__card">
        <header class="hs-auth__head">
          <h1 class="hs-heading hs-heading--h2" id="rp-h">Reset your password</h1>
          <p class="hs-auth__intro">Enter the email address you use to sign in. We will email you a link to set a new password.</p>
        </header>
        <form class="hs-form" action="/user/password" method="post" id="user-pass" accept-charset="UTF-8">
          <div class="hs-field">
            <label class="hs-label" for="edit-name--3">Email address</label>
            <input class="hs-control" id="edit-name--3" name="name" type="email" autocomplete="email" spellcheck="false" autocapitalize="none" maxlength="254" required>
          </div>
          <input type="hidden" name="form_build_id" value="form-PLACEHOLDER">
          <input type="hidden" name="form_id" value="user_pass">
          <button class="hs-button hs-button--block" name="op" value="Email me a reset link" type="submit" data-ph-capture-attribute-cta="reset-email" data-ph-capture-attribute-cta-loc="reset-password">Email me a reset link</button>
        </form>
        <hr class="hs-form-divider">
        <p class="hs-form-note"><strong>Need help signing in?</strong> Visit our <a class="hs-form-link" href="https://support.honorsociety.org/hc/en-us" data-ph-capture-attribute-cta="help-center" data-ph-capture-attribute-cta-loc="reset-password">Help Center</a> or <a class="hs-form-link" href="https://support.honorsociety.org/hc/en-us/requests/new" data-ph-capture-attribute-cta="support-request" data-ph-capture-attribute-cta-loc="reset-password">contact Honor Society&reg; support</a>.</p>
      </div>
      <p class="hs-auth__alt">Remembered your password? <a class="hs-form-link" href="/user/login" data-ph-capture-attribute-cta="sign-in" data-ph-capture-attribute-cta-loc="reset-password">Sign in</a></p>
    </div>
  </div>
</section>
```

## Reset password, signed in

`/user/password` for a member who is signed in. Same form; there is no email field, because the link goes to the account’s own address.

```html
<section class="hs-band" data-section="reset-password" aria-labelledby="rn-h">
  <div class="hs-container">
    <div class="hs-auth">
      <div class="hs-auth__card">
        <header class="hs-auth__head">
          <h1 class="hs-heading hs-heading--h2" id="rn-h">Reset your password</h1>
          <p class="hs-auth__intro">We will email you a link to set a new password. Know your current password? <a class="hs-form-link" href="/user/1234/password" data-ph-capture-attribute-cta="change-password" data-ph-capture-attribute-cta-loc="reset-password">Change your password</a> instead.</p>
        </header>
        <aside class="hs-callout hs-callout--info">
          <svg class="hs-callout__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="9"/><path d="M12 11v5.5"/><path d="M12 7.6v.1"/></svg>
          <div class="hs-callout__body">
            <p class="hs-callout__title">You are signed in as <span class="hs-auth__account">avery.example@example.com</span>.</p>
            <p><a class="hs-form-link" href="/user/logout?destination=user/password" data-ph-capture-attribute-cta="sign-out" data-ph-capture-attribute-cta-loc="reset-password">Sign out</a> to reset another account.</p>
          </div>
        </aside>
        <form class="hs-form" action="/user/password" method="post" id="user-pass--2" accept-charset="UTF-8">
          <input type="hidden" name="form_build_id" value="form-PLACEHOLDER">
          <input type="hidden" name="form_token" value="PLACEHOLDER">
          <input type="hidden" name="form_id" value="user_pass">
          <button class="hs-button hs-button--block" name="op" value="Email me a reset link" type="submit" data-ph-capture-attribute-cta="reset-email" data-ph-capture-attribute-cta-loc="reset-password">Email me a reset link</button>
        </form>
        <hr class="hs-form-divider">
        <p class="hs-form-note"><strong>Need help signing in?</strong> Visit our <a class="hs-form-link" href="https://support.honorsociety.org/hc/en-us" data-ph-capture-attribute-cta="help-center" data-ph-capture-attribute-cta-loc="reset-password">Help Center</a> or <a class="hs-form-link" href="https://support.honorsociety.org/hc/en-us/requests/new" data-ph-capture-attribute-cta="support-request" data-ph-capture-attribute-cta-loc="reset-password">contact Honor Society&reg; support</a>.</p>
      </div>
    </div>
  </div>
</section>
```

## Reset email sent

The state after a reset request. The [Confirmation panel](/components/confirmation-panel/) replaces the form.

```html
<section class="hs-band" data-section="reset-sent" aria-labelledby="rs-h">
  <div class="hs-container">
    <div class="hs-auth">
      <div class="hs-auth__card">
        <div class="hs-confirm">
          <svg class="hs-confirm__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><rect x="3.5" y="5.5" width="17" height="13" rx="2"/><path d="m4 7 8 6 8-6"/></svg>
          <h1 class="hs-heading hs-heading--h2" id="rs-h">Check your email</h1>
          <!-- The address comes from the session, never from the URL. "24 hours" is printed from user_password_reset_timeout. -->
          <p class="hs-confirm__text">We sent a link to set a new password to <strong>avery.example@example.com</strong>. The link works once and expires in 24 hours.</p>
        </div>
        <hr class="hs-form-divider">
        <p class="hs-form-note"><strong>Did not get the email?</strong> Check your spam folder, or <a class="hs-form-link" href="/user/password" data-ph-capture-attribute-cta="reset-password" data-ph-capture-attribute-cta-loc="reset-sent">send the link again</a>.</p>
      </div>
      <p class="hs-auth__alt"><a class="hs-form-link" href="/user/login" data-ph-capture-attribute-cta="sign-in" data-ph-capture-attribute-cta-loc="reset-sent">Back to sign in</a></p>
    </div>
  </div>
</section>
```

## One-time login

The page the emailed link opens: `/user/reset/{uid}/{timestamp}/{hash}`. Form `user_pass_reset`. It names the member’s email address, never the username.

```html
<section class="hs-band" data-section="one-time-login" aria-labelledby="ol-h">
  <div class="hs-container">
    <div class="hs-auth">
      <div class="hs-auth__card">
        <header class="hs-auth__head">
          <h1 class="hs-heading hs-heading--h2" id="ol-h">Set a new password</h1>
          <p class="hs-auth__intro">This link signs you in to the account for <strong>avery.example@example.com</strong>. Then you choose a new password.</p>
          <!-- Date and time: the link's expiry, from the timestamp plus user_password_reset_timeout, in the site time zone. -->
          <p class="hs-auth__intro">The link works once and expires on October 15, 2026 at 3:20 pm.</p>
        </header>
        <form class="hs-form" action="/user/reset/1234/1760450400/PLACEHOLDER-HASH/login" method="post" id="user-pass-reset" accept-charset="UTF-8">
          <input type="hidden" name="form_build_id" value="form-PLACEHOLDER">
          <input type="hidden" name="form_id" value="user_pass_reset">
          <button class="hs-button hs-button--block" name="op" value="Sign in and set a new password" type="submit" data-ph-capture-attribute-cta="one-time-login" data-ph-capture-attribute-cta-loc="one-time-login">Sign in and set a new password</button>
        </form>
        <hr class="hs-form-divider">
        <p class="hs-form-note"><strong>Need help signing in?</strong> Visit our <a class="hs-form-link" href="https://support.honorsociety.org/hc/en-us" data-ph-capture-attribute-cta="help-center" data-ph-capture-attribute-cta-loc="one-time-login">Help Center</a> or <a class="hs-form-link" href="https://support.honorsociety.org/hc/en-us/requests/new" data-ph-capture-attribute-cta="support-request" data-ph-capture-attribute-cta-loc="one-time-login">contact Honor Society&reg; support</a>.</p>
      </div>
    </div>
  </div>
</section>
```

## Change password

`/user/{uid}/password`, the member’s own account. Form `password_policy_password_tab`, altered by `hs_user_account_password_form_alter()`. The meter and the rules are the site’s `HsUser\PasswordRules`.

```html
<section class="hs-band" data-section="account-password" aria-labelledby="cp-h">
  <div class="hs-container">
    <div class="hs-auth">
      <div class="hs-auth__card">
        <header class="hs-auth__head">
          <h1 class="hs-heading hs-heading--h2" id="cp-h">Change password</h1>
        </header>
        <form class="hs-form" action="/user/1234/password" method="post" id="password-policy-password-tab" accept-charset="UTF-8">
          <div class="hs-field hs-password">
            <label class="hs-label" for="edit-current-pass">Current password</label>
            <div class="hs-password__input">
              <input class="hs-control" id="edit-current-pass" name="current_pass" type="password" autocomplete="current-password" maxlength="128" required>
              <button class="hs-password__toggle" type="button" aria-label="Show password" aria-pressed="false" aria-controls="edit-current-pass" hidden>
                <svg class="hs-password__icon hs-password__icon--show" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M2 12s3.6-7 10-7 10 7 10 7-3.6 7-10 7S2 12 2 12z"/><circle cx="12" cy="12" r="3"/></svg><svg class="hs-password__icon hs-password__icon--hide" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10.6 5.1A10.4 10.4 0 0 1 12 5c6.4 0 10 7 10 7a17.6 17.6 0 0 1-2.6 3.5M6.6 6.6C3.7 8.5 2 12 2 12s3.6 7 10 7a9.9 9.9 0 0 0 5.4-1.6"/><path d="M9.9 9.9a3 3 0 0 0 4.2 4.2"/><path d="M3 3l18 18"/></svg>
              </button>
            </div>
            <p class="hs-hint"><a class="hs-form-link" href="/user/password" data-ph-capture-attribute-cta="reset-password" data-ph-capture-attribute-cta-loc="account-password">Forgot your password?</a></p>
          </div>
          <div class="hs-field hs-password">
            <label class="hs-label" for="edit-pass-new">New password</label>
            <div class="hs-password__input">
              <input class="hs-control" id="edit-pass-new" name="pass[pass1]" type="password" autocomplete="new-password" maxlength="128" aria-describedby="edit-pass-new-rules" required>
              <button class="hs-password__toggle" type="button" aria-label="Show password" aria-pressed="false" aria-controls="edit-pass-new" hidden>
                <svg class="hs-password__icon hs-password__icon--show" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M2 12s3.6-7 10-7 10 7 10 7-3.6 7-10 7S2 12 2 12z"/><circle cx="12" cy="12" r="3"/></svg><svg class="hs-password__icon hs-password__icon--hide" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10.6 5.1A10.4 10.4 0 0 1 12 5c6.4 0 10 7 10 7a17.6 17.6 0 0 1-2.6 3.5M6.6 6.6C3.7 8.5 2 12 2 12s3.6 7 10 7a9.9 9.9 0 0 0 5.4-1.6"/><path d="M9.9 9.9a3 3 0 0 0 4.2 4.2"/><path d="M3 3l18 18"/></svg>
              </button>
            </div>
            <div class="hs-meter">
              <span class="hs-meter__fill"></span>
              <span class="hs-meter__label hs-visually-hidden" aria-live="polite"></span>
            </div>
            <ul class="hs-password__rules" id="edit-pass-new-rules">
              <li class="hs-password__rule" data-rule="length" data-min="8">8+ characters</li>
              <li class="hs-password__rule" data-rule="letter" data-min="1">1 letter</li>
              <li class="hs-password__rule" data-rule="digit" data-min="1">1 number</li>
            </ul>
          </div>
          <div class="hs-field hs-password">
            <label class="hs-label" for="edit-pass-confirm">Confirm new password</label>
            <div class="hs-password__input">
              <input class="hs-control" id="edit-pass-confirm" name="pass[pass2]" type="password" autocomplete="new-password" maxlength="128" required>
              <button class="hs-password__toggle" type="button" aria-label="Show password" aria-pressed="false" aria-controls="edit-pass-confirm" hidden>
                <svg class="hs-password__icon hs-password__icon--show" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M2 12s3.6-7 10-7 10 7 10 7-3.6 7-10 7S2 12 2 12z"/><circle cx="12" cy="12" r="3"/></svg><svg class="hs-password__icon hs-password__icon--hide" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10.6 5.1A10.4 10.4 0 0 1 12 5c6.4 0 10 7 10 7a17.6 17.6 0 0 1-2.6 3.5M6.6 6.6C3.7 8.5 2 12 2 12s3.6 7 10 7a9.9 9.9 0 0 0 5.4-1.6"/><path d="M9.9 9.9a3 3 0 0 0 4.2 4.2"/><path d="M3 3l18 18"/></svg>
              </button>
            </div>
          </div>
          <input type="hidden" name="form_build_id" value="form-PLACEHOLDER">
          <input type="hidden" name="form_token" value="PLACEHOLDER">
          <input type="hidden" name="form_id" value="password_policy_password_tab">
          <button class="hs-button hs-button--block" name="op" value="Save password" type="submit" data-ph-capture-attribute-cta="password_save" data-ph-capture-attribute-cta-loc="account-password">Save password</button>
        </form>
      </div>
      <p class="hs-auth__alt"><a class="hs-form-link" href="/user/1234" data-ph-capture-attribute-cta="profile" data-ph-capture-attribute-cta-loc="account-password">Back to your profile</a></p>
    </div>
  </div>
</section>
```

## Change email

`/user/{uid}/email`, the member’s own account. Form `hs_user_account_email_form`. Copy as on the site today.

```html
<section class="hs-band" data-section="account-email" aria-labelledby="ce-h">
  <div class="hs-container">
    <div class="hs-auth">
      <div class="hs-auth__card">
        <header class="hs-auth__head">
          <h1 class="hs-heading hs-heading--h2" id="ce-h">Change email</h1>
          <p class="hs-auth__intro">Your email address is <strong>avery.example@example.com</strong>. It is also how you sign in.</p>
          <p class="hs-auth__intro">Your email address is not on your public profile.</p>
        </header>
        <form class="hs-form" action="/user/1234/email" method="post" id="hs-user-account-email-form" accept-charset="UTF-8">
          <div class="hs-field">
            <label class="hs-label" for="edit-mail">New email address</label>
            <input class="hs-control" id="edit-mail" name="mail" type="email" autocomplete="email" spellcheck="false" autocapitalize="none" maxlength="254" required>
          </div>
          <div class="hs-field hs-password">
            <label class="hs-label" for="edit-current-pass--2">Current password</label>
            <div class="hs-password__input">
              <input class="hs-control" id="edit-current-pass--2" name="current_pass" type="password" autocomplete="current-password" maxlength="128" aria-describedby="edit-current-pass--2-hint" required>
              <button class="hs-password__toggle" type="button" aria-label="Show password" aria-pressed="false" aria-controls="edit-current-pass--2" hidden>
                <svg class="hs-password__icon hs-password__icon--show" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M2 12s3.6-7 10-7 10 7 10 7-3.6 7-10 7S2 12 2 12z"/><circle cx="12" cy="12" r="3"/></svg><svg class="hs-password__icon hs-password__icon--hide" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M10.6 5.1A10.4 10.4 0 0 1 12 5c6.4 0 10 7 10 7a17.6 17.6 0 0 1-2.6 3.5M6.6 6.6C3.7 8.5 2 12 2 12s3.6 7 10 7a9.9 9.9 0 0 0 5.4-1.6"/><path d="M9.9 9.9a3 3 0 0 0 4.2 4.2"/><path d="M3 3l18 18"/></svg>
              </button>
            </div>
            <p class="hs-hint" id="edit-current-pass--2-hint">For your security, confirm the change with your password.</p>
            <p class="hs-hint"><a class="hs-form-link" href="/user/password" data-ph-capture-attribute-cta="reset-password" data-ph-capture-attribute-cta-loc="account-email">Forgot your password?</a></p>
          </div>
          <input type="hidden" name="form_build_id" value="form-PLACEHOLDER">
          <input type="hidden" name="form_token" value="PLACEHOLDER">
          <input type="hidden" name="form_id" value="hs_user_account_email_form">
          <button class="hs-button hs-button--block" name="op" value="Save email" type="submit" data-ph-capture-attribute-cta="email_save" data-ph-capture-attribute-cta-loc="account-email">Save email</button>
        </form>
      </div>
      <p class="hs-auth__alt"><a class="hs-form-link" href="/user/1234" data-ph-capture-attribute-cta="profile" data-ph-capture-attribute-cta-loc="account-email">Back to your profile</a></p>
    </div>
  </div>
</section>
```

## Sign in to continue

The access-denied page for a visitor (403). One button to the sign-in page that keeps the destination, so the member returns to the page they asked for.

```html
<section class="hs-band" data-section="sign-in-to-continue" aria-labelledby="dn-h">
  <div class="hs-container">
    <div class="hs-auth">
      <div class="hs-auth__card">
        <header class="hs-auth__head">
          <h1 class="hs-heading hs-heading--h2" id="dn-h">Sign in to continue</h1>
          <p class="hs-auth__intro">This page is for Honor Society&reg; members. After you sign in, you return to this page.</p>
        </header>
        <!-- href: url('user/login', ['query' => drupal_get_destination()]). The destination is the denied path, URL-encoded. -->
        <a class="hs-button hs-button--block" href="/user/login?destination=my-membership" data-ph-capture-attribute-cta="sign-in" data-ph-capture-attribute-cta-loc="sign-in-to-continue">Sign in</a>
        <hr class="hs-form-divider">
        <p class="hs-form-note"><strong>Need help signing in?</strong> Visit our <a class="hs-form-link" href="https://support.honorsociety.org/hc/en-us" data-ph-capture-attribute-cta="help-center" data-ph-capture-attribute-cta-loc="sign-in-to-continue">Help Center</a> or <a class="hs-form-link" href="https://support.honorsociety.org/hc/en-us/requests/new" data-ph-capture-attribute-cta="support-request" data-ph-capture-attribute-cta-loc="sign-in-to-continue">contact Honor Society support</a>.</p>
      </div>
      <p class="hs-auth__alt">New to Honor Society? <a class="hs-form-link" href="/join" data-ph-capture-attribute-cta="join" data-ph-capture-attribute-cta-loc="sign-in-to-continue">Join now</a></p>
    </div>
  </div>
</section>
```

## Notes

**Copy on /user/login:**

- The H1 reads “Honor Society® login”: it is the first visible reference on the page.
- Every link opens in the same tab, as on the rest of the site.
- The card heading is the one `h1`, and the template prints no title on these routes.
- Two exceptions to house rules, by design: “Join now” (not a verb plus a noun) keeps the join route short and secondary, and the login page carries no `Start Free Membership`, because it does not promote free membership.

**Copy on the other screens** is new, in the same voice. It names the result (“Check your email”), what a link does and its limits (works once, the expiry), and the address it went to.

**Drupal form IDs:**

- Sign in, `user/login`: `user_login` (core). Altered by `user_registration` (welcome-back `em` prefill) and `user_profile_enhancements` (old suffix).
- Reset request, `user/password`: `user_pass` (core). Altered by `user_profile_enhancements` (old suffix).
- One-time login, `user/reset/%/%/%`: `user_pass_reset` (core).
- Change password, `user/%user/password`: `password_policy_password_tab` (contrib), restyled by `hs_user_account_password_form_alter()`.
- Change email, `user/%user/email`: `hs_user_account_email_form` (`hs_user`).
- Sign in to continue, any denied path: no form; the `hs_core` template `hs-core-403.tpl.php`, visitor branch.

The sidebar `user_login_block` is a different form ID. Leave it out of this restyle.

**What the Drupal build must preserve:**

- Hidden fields and tokens: `form_build_id`, `form_id`, and `form_token` on every form a signed-in member submits. Render the form with `drupal_render_children()` so every child another module adds still prints (honeypot, CAPTCHA, SSO controls).
- Field names: `name` and `pass` on `user_login`, `name` on `user_pass`, `current_pass`, `pass` and `mail` on the account forms. Change only `#title`, `#attributes` and the theme wrapper.
- Email sign-in: `email_registration` resolves an email address in `name` to the account. Set `type="email"` through the `hs_user_form_input` theme (`#hs_input_type`), as the change email form does; Form API textfields print `type="text"`.
- Flood control: `user_login_authenticate_validate()` and `flood_control` limit failed attempts. Keep the validators. Rewrite their message in this voice without numbers the page cannot check: “This account is locked after too many failed sign-ins. Try again later, or reset your password.”
- SSO handoff: `user_registration_user_login()` pushes the account to the Laravel membership app, sets the login cookies and redirects (the Membership hub, or back to an internal `?destination`). Submit the form normally through `user_login_submit()`, so `hook_user_login()` runs. No AJAX sign-in.
- Destination redirects: keep `?destination=` on the form action. The 403 button builds its link with `drupal_get_destination()`. External destinations are ignored by `drupal_goto()`.
- Reset confirmation: core `user_pass_submit()` redirects to `/user/login` with a status message. To show “Check your email”, redirect to the reset page with a flag and keep the address in `$_SESSION`. Never put the address in the URL.
- Account enumeration: core `user_pass_validate()` says when no account has the address. Keep it (support load) or replace it with one neutral message for every address. Product decision; the sent state above works for both.
- Expiry: the one-time link expires after `user_password_reset_timeout` (core default 86400 seconds, 24 hours). Print the confirmation’s “24 hours” and the one-time page’s date and time from that variable.
- Old suffix: remove the help line and the second “Forgot your password?” that the `user_login` and `user_pass` alters in `user_profile_enhancements` add; the card replaces them.
- Messages: status and error messages for these routes print inside the card, under the head, as callouts. A form error uses the form alert.
- Change password today has one new-password field with show and hide, and no confirm field (`hs_user_password`). This recipe adds “Confirm new password”: the change password screen keeps it, with the eye toggle on every password field.
- Change email: a verification step is planned. The new address will need a link from an email before it replaces the old one. The page will then show the confirmation panel with the new address. The email itself is out of scope here.

**SEO for /user/login:**

- Title: `Honor Society Login | Member Sign In`. Set it for this route only, with no second automatic “| Honor Society” suffix.
- Description: `Sign in to your Honor Society account to manage your membership. Reset your password or visit our Help Center for account support.`
- Canonical: `https://www.honorsociety.org/user/login`, absolute and single.
- Keep the current robots policy for `/user/login`. No FAQ schema, no review markup, no promotional bands. Every link and line of copy is server-rendered. The `/user/{uid}/*` pages are private.

**The hs_mcp validator** does not apply: these are system routes and module forms, not editor pages.

**Missing components:** none. Round 4 added the auth card, the form link, divider and support note, the confirmation panel and the full-width button, and made the eye toggle the one password toggle.
