Page recipe R7
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.
- 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, Form, Form link, divider and support note, Confirmation panel, Button, Callout, Heading, Band and container
- Markdown
- /recipes/r7-account-pages.md
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
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 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 oneh1. - 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 Societyafter it. The header logo does not count.- Give every field its
autocomplete:usernameon the sign-in email,emailon every other email field,current-passwordon a password the member already has,new-passwordon a new one. Email fields taketype="email". - Keep the Drupal form whole: the field
nameattributes, the hiddenform_build_id,form_idandform_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 page.
Sign in
/user/login, for a visitor. Form user_login.
Honor Society® login
Welcome back. Sign in to your account.
Need help signing in? Visit our Help Center or contact Honor Society support.
New to Honor Society? Join now
Page HTML (37 lines)
<!-- 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® 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.
Honor Society® login
Welcome back. Sign in to your account.
Your email address or password is not correct
Need help signing in? Visit our Help Center or contact Honor Society support.
New to Honor Society? Join now
Page HTML (44 lines)
<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® 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.
Reset your password
Enter the email address you use to sign in. We will email you a link to set a new password.
Need help signing in? Visit our Help Center or contact Honor Society® support.
Remembered your password? Sign in
Page HTML (24 lines)
<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® 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.
Reset your password
We will email you a link to set a new password. Know your current password? Change your password instead.
Need help signing in? Visit our Help Center or contact Honor Society® support.
Page HTML (27 lines)
<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® support</a>.</p>
</div>
</div>
</div>
</section>Reset email sent
The state after a reset request. The Confirmation panel replaces the form.
Check your email
We sent a link to set a new password to avery.example@example.com. The link works once and expires in 24 hours.
Did not get the email? Check your spam folder, or send the link again.
Page HTML (17 lines)
<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.
Set a new password
This link signs you in to the account for avery.example@example.com. Then you choose a new password.
The link works once and expires on October 15, 2026 at 3:20 pm.
Need help signing in? Visit our Help Center or contact Honor Society® support.
Page HTML (21 lines)
<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® 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.
Change password
Page HTML (55 lines)
<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.
Change email
Your email address is avery.example@example.com. It is also how you sign in.
Your email address is not on your public profile.
Page HTML (35 lines)
<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.
Sign in to continue
This page is for Honor Society® members. After you sign in, you return to this page.
Need help signing in? Visit our Help Center or contact Honor Society support.
New to Honor Society? Join now
Page HTML (17 lines)
<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® 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 byuser_registration(welcome-backemprefill) anduser_profile_enhancements(old suffix). - Reset request,
user/password:user_pass(core). Altered byuser_profile_enhancements(old suffix). - One-time login,
user/reset/%/%/%:user_pass_reset(core). - Change password,
user/%user/password:password_policy_password_tab(contrib), restyled byhs_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_coretemplatehs-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, andform_tokenon every form a signed-in member submits. Render the form withdrupal_render_children()so every child another module adds still prints (honeypot, CAPTCHA, SSO controls). - Field names:
nameandpassonuser_login,nameonuser_pass,current_pass,passandmailon the account forms. Change only#title,#attributesand the theme wrapper. - Email sign-in:
email_registrationresolves an email address innameto the account. Settype="email"through thehs_user_form_inputtheme (#hs_input_type), as the change email form does; Form API textfields printtype="text". - Flood control:
user_login_authenticate_validate()andflood_controllimit 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 throughuser_login_submit(), sohook_user_login()runs. No AJAX sign-in. - Destination redirects: keep
?destination=on the form action. The 403 button builds its link withdrupal_get_destination(). External destinations are ignored bydrupal_goto(). - Reset confirmation: core
user_pass_submit()redirects to/user/loginwith 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_loginanduser_passalters inuser_profile_enhancementsadd; 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.