/*
 * MD1812 Member Portal - front end styles.
 * Self-contained: no build step, no external fonts, no CDN.
 */

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

.md1812-portal {
	/*
	 * One Society, one palette.
	 *
	 * These were the portal's own colours until 1.16.0, and they were very
	 * nearly the website's: the old navy, #12233f, turned out to be
	 * hsl(217 56% 16%) against the site's hsl(217 100% 18%) — the same hue to
	 * within a tenth of a degree, with the saturation turned down. Nobody
	 * chose two navies; one was sampled and softened, which reads as slightly
	 * out of tune rather than as a deliberate contrast. The site's values are
	 * now the Society's values, here and on md1812.org alike.
	 *
	 * Gold survives, with a job: it marks the signed-in area and nothing else
	 * — the masthead rule, the office marks, the focus halo — so a member gets
	 * a quiet signal that they are inside while everything else matches the
	 * front of house. Crimson does what it does on the website: it is the
	 * colour of something you can act on.
	 */
	--md-ink: #00235c;
	--md-ink-soft: #053480;
	--md-gold: #b5893a;

	/*
	 * Gold you can read, as against gold you can merely see. The brand gold
	 * measures 3.19:1 on white - fine for a 3px rule or a ring, below the 4.5:1
	 * that words need. This darker gold is 4.92:1 and is what every piece of
	 * gold TEXT uses; the card view was still setting the brand value and had
	 * been failing quietly. If you find yourself putting --md-gold on type,
	 * you want this one.
	 */
	--md-gold-text: #8a6c2f;
	--md-gold-soft: #f3e8d2;
	--md-crimson: #8a0a0a;
	--md-paper: #faf8f4;
	--md-surface: #ffffff;
	--md-line: #e4ded3;
	--md-text: #434a56;
	--md-muted: #5f6875;
	--md-success: #216c4b;
	--md-error: #9b2226;

	/* 4px on the website, 10 here. Both move to 6. */
	--md-radius: 6px;
	--md-radius-control: 6px;

	--md-shadow: 0 1px 2px rgba(0, 35, 92, .06), 0 8px 24px rgba(0, 35, 92, .07);

	/*
	 * The website's own faces. The theme already asks Google for both on every
	 * page the portal renders, so this costs no extra request and no extra
	 * render delay — and the fallbacks behind them are the stacks the portal
	 * used before, so a future theme change degrades rather than breaks.
	 *
	 * Note the weights: the theme requests Nunito Sans at 400, 600 and 700
	 * only. Anything the portal sets to 500 would be synthesised by the
	 * browser, so the portal uses 600 where it wants emphasis.
	 */
	--md-font: "Nunito Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
	--md-serif: "Crimson Text", Georgia, "Iowan Old Style", "Times New Roman", serif;

	color: var(--md-text);
	font-family: var(--md-font);
	font-size: 16px;
	line-height: 1.6;
}

body.md1812-portal-body {
	margin: 0;
	background: var(--md-paper);
}

/*
 * The website's heading rhythm, so a member reading a page title in the portal
 * and one on md1812.org is reading the same typography at a different size.
 * Crimson Text is set at 400 with a two-per-cent negative track there; the
 * initials in a portrait are a monogram rather than a heading and keep their
 * own spacing, set where they are drawn.
 */
.md1812-portal .md1812-brand__name,
.md1812-portal .md1812-page-title,
.md1812-portal .md1812-card__title,
.md1812-portal .md1812-auth__title,
.md1812-portal .md1812-rowdoc__title,
.md1812-portal .md1812-doc__title,
.md1812-portal .md1812-member__name,
.md1812-portal .md1812-empty__title,
.md1812-portal .md1812-photo__name,
.md1812-portal .md1812-roster__heading {
	font-weight: 400;
	letter-spacing: -.02em;
}

/* Only the headings that stand alone take the tighter leading; a name in a
   list or a document title in a row wraps, and wants the room it already has. */
.md1812-portal .md1812-page-title,
.md1812-portal .md1812-card__title,
.md1812-portal .md1812-auth__title,
.md1812-portal .md1812-empty__title,
.md1812-portal .md1812-roster__heading {
	line-height: 1.15;
}

.md1812-portal .screen-reader-text {
	position: absolute !important;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

.md1812-shell {
	width: 100%;
	max-width: 1120px;
	margin: 0 auto;
	padding: 32px 20px 64px;
}

/* ---------- Masthead ---------- */

.md1812-masthead {
	background: var(--md-ink);
	color: #fff;
	border-bottom: 3px solid var(--md-gold);
}

.md1812-masthead__inner {
	max-width: 1120px;
	margin: 0 auto;
	padding: 14px 20px;
	display: flex;
	align-items: center;
	gap: 16px;
	flex-wrap: wrap;
}

.md1812-brand {
	display: flex;
	align-items: center;
	gap: 12px;
	text-decoration: none;
	color: #fff;
	margin-right: auto;
	/*
	 * Allowed to give way. Without this the brand refuses to be narrower than
	 * its longest line, and on a 360px telephone that pushed the menu button
	 * off the end of the row - where `flex-wrap` put it on a line of its own,
	 * at the left-hand edge. See the toggle below.
	 */
	min-width: 0;
}

.md1812-brand__logo {
	display: block;
	height: 62px;
	width: auto;
	max-width: 200px;
	flex: 0 0 auto;
}

.md1812-brand__text {
	display: flex;
	flex-direction: column;
	line-height: 1.25;
	min-width: 0;
}

.md1812-brand__name {
	font-family: var(--md-serif);
	font-size: 17px;
}

.md1812-brand__sub {
	font-size: 12px;
	letter-spacing: .09em;
	text-transform: uppercase;
	color: var(--md-gold);
}

.md1812-nav {
	display: flex;
	align-items: center;
	gap: 4px;
	flex-wrap: wrap;
}

.md1812-nav__link {
	color: rgba(255, 255, 255, .82);
	text-decoration: none;
	font-size: 14px;
	padding: 8px 12px;
	border-radius: 6px;
}

.md1812-nav__link:hover,
.md1812-nav__link:focus-visible {
	color: #fff;
	background: rgba(255, 255, 255, .1);
}

.md1812-nav__link.is-current {
	color: #fff;
	background: rgba(181, 137, 58, .25);
	box-shadow: inset 0 -2px 0 var(--md-gold);
}

.md1812-nav__link--signout {
	border: 1px solid rgba(255, 255, 255, .28);
	margin-left: 6px;
}

/*
 * The menu button, and which side it lives on.
 *
 * Craig, 17 Sep: "Can we move the hamburger menu to the right on mobile view?
 * A majority of people are right handed." It was already on the right at 390px
 * and wider - but the masthead wraps, and on a 360px screen the brand was too
 * wide to leave room, so the button dropped onto a second line and sat at the
 * LEFT edge, as far from a right thumb as the header can put it.
 *
 * Two rules keep it where it belongs rather than one: `margin-left: auto`
 * pushes it right whatever precedes it and whatever line it lands on, and
 * `flex-shrink: 0` with the brand's `min-width: 0` above means the brand
 * gives way first, so it never wraps in the first place.
 */
.md1812-nav-toggle {
	display: none;
	width: 42px;
	height: 38px;
	background: transparent;
	border: 1px solid rgba(255, 255, 255, .3);
	border-radius: 6px;
	cursor: pointer;
	position: relative;
	margin-left: auto;
	flex: 0 0 auto;
}

.md1812-nav-toggle__bar,
.md1812-nav-toggle__bar::before,
.md1812-nav-toggle__bar::after {
	position: absolute;
	left: 11px;
	width: 18px;
	height: 2px;
	background: #fff;
	content: "";
}

.md1812-nav-toggle__bar {
	top: 18px;
}

.md1812-nav-toggle__bar::before {
	top: -6px;
	left: 0;
}

.md1812-nav-toggle__bar::after {
	top: 6px;
	left: 0;
}

/* ---------- Typography and shared blocks ---------- */

.md1812-page-head {
	margin-bottom: 24px;
}

.md1812-page-title {
	font-family: var(--md-serif);
	font-size: 30px;
	line-height: 1.2;
	margin: 0 0 6px;
	color: var(--md-ink);
}

.md1812-page-sub,
.md1812-help {
	color: var(--md-muted);
	margin: 0 0 12px;
	font-size: 14px;
}

.md1812-muted {
	color: var(--md-muted);
}

.md1812-card {
	background: var(--md-surface);
	border: 1px solid var(--md-line);
	border-radius: var(--md-radius);
	padding: 20px;
	box-shadow: var(--md-shadow);
}

.md1812-card__title {
	font-family: var(--md-serif);
	font-size: 19px;
	margin: 0 0 12px;
	color: var(--md-ink);
}

.md1812-card__subtitle {
	font-size: 13px;
	text-transform: uppercase;
	letter-spacing: .07em;
	color: var(--md-muted);
	margin: 18px 0 8px;
}

.md1812-notice {
	border-radius: var(--md-radius);
	padding: 14px 16px;
	margin: 0 0 20px;
	border: 1px solid var(--md-line);
	background: var(--md-surface);
}

.md1812-notice p {
	margin: 0 0 8px;
}

.md1812-notice p:last-child {
	margin-bottom: 0;
}

.md1812-notice--error {
	border-color: #e7c3c4;
	background: #fdf3f3;
	color: var(--md-error);
}

.md1812-notice--success {
	border-color: #bfdcc9;
	background: #f2faf5;
	color: var(--md-success);
}

.md1812-notice--info {
	border-color: #cfd8e6;
	background: #f4f7fc;
}

/* ---------- Buttons and form controls ---------- */

.md1812-button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	padding: 10px 18px;
	border-radius: var(--md-radius-control);
	border: 1px solid var(--md-ink);
	background: var(--md-ink);
	color: #fff;
	font-size: 15px;
	font-family: inherit;
	line-height: 1.2;
	text-decoration: none;
	cursor: pointer;
	transition: background .15s ease, color .15s ease;
}

.md1812-button:hover,
.md1812-button:focus-visible {
	background: var(--md-ink-soft);
	color: #fff;
}

.md1812-button--ghost {
	background: transparent;
	color: var(--md-ink);
}

.md1812-button--ghost:hover,
.md1812-button--ghost:focus-visible {
	background: var(--md-gold-soft);
	color: var(--md-ink);
}

.md1812-button--block {
	width: 100%;
}

.md1812-button[disabled] {
	opacity: .6;
	cursor: not-allowed;
}

.md1812-field {
	margin-bottom: 16px;
}

.md1812-field--inline {
	display: flex;
	align-items: center;
}

.md1812-label {
	display: block;
	/* Said out loud. Until 1.16.0 the portal set no family here, so labels
	   silently took the theme's body font while the fields beside them took the
	   portal's — three faces on the sign-in screen, none of them chosen
	   together. They happen to agree now; they should not depend on it. */
	font-family: var(--md-font);
	font-size: 13px;
	font-weight: 600;
	letter-spacing: .02em;
	color: var(--md-ink);
	margin-bottom: 6px;
}

.md1812-required {
	color: var(--md-crimson);
}

.md1812-input,
.md1812-select {
	width: 100%;
	padding: 10px 12px;
	border: 1px solid var(--md-line);
	border-radius: var(--md-radius-control);
	background: #fff;
	font-size: 15px;
	font-family: inherit;
	color: var(--md-text);
}

/*
 * Themes style form controls with attribute selectors such as
 * input[type="search"], which outrank a single class and quietly win. The
 * GoDaddy Go theme also gives every control a bottom margin, which made the
 * search wrapper taller than the field itself and pushed the magnifier down
 * to its bottom edge. These rules restate the portal's own styling with
 * enough specificity to hold, whatever the active theme does.
 */
.md1812-portal .md1812-input,
.md1812-portal .md1812-select,
.md1812-portal textarea.md1812-input {
	margin: 0;
	padding: 10px 12px;
	width: 100%;
	max-width: none;
	height: auto;
	min-height: 0;
	border: 1px solid var(--md-line);
	border-radius: var(--md-radius-control);
	background-color: #fff;
	box-shadow: none;
	font-family: inherit;
	font-size: 15px;
	line-height: 1.45;
	color: var(--md-text);
	text-transform: none;
	letter-spacing: normal;
}

.md1812-portal .md1812-input--search {
	padding-left: 42px;
	padding-right: 42px;
	font-size: 16px;
}

/* Themes that null out the native arrow rarely put one back for our markup. */
.md1812-portal .md1812-select {
	appearance: none;
	-webkit-appearance: none;
	padding-right: 34px;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='none' stroke='%236a7382' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round' d='M1 1.5 6 6.5 11 1.5'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 12px center;
	background-size: 12px 8px;
}

/* Height now tracks the field, so the icon centres on the field. */
.md1812-search-wrap {
	display: flex;
	align-items: center;
}

/*
 * The same specificity problem applies to buttons. A theme's rule for the bare
 * `button` element supplies anything the portal leaves undeclared — the Go
 * theme's generous padding turned a 28px round clear button into a 72px oval.
 * Every button the portal draws therefore states its own box completely.
 */
.md1812-portal button {
	font-family: inherit;
	/* The Go theme sets 500 on every button through its own variable, and the
	   theme only asks Google for Nunito Sans at 400, 600 and 700 - so 500 was
	   being synthesised by the browser. State the weight the font actually
	   has. */
	font-weight: 600;
	text-transform: none;
	letter-spacing: normal;
	box-shadow: none;
}

.md1812-portal .md1812-button {
	width: auto;
	min-width: 0;
	height: auto;
	min-height: 0;
	padding: 10px 18px;
	border-radius: var(--md-radius-control);
	font-size: 15px;
	line-height: 1.2;
	background-color: var(--md-ink);
	border: 1px solid var(--md-ink);
	color: #fff;
}

.md1812-portal .md1812-button--ghost {
	background-color: transparent;
	color: var(--md-ink);
}

.md1812-portal .md1812-button--ghost:hover,
.md1812-portal .md1812-button--ghost:focus-visible {
	background-color: var(--md-gold-soft);
	color: var(--md-ink);
}

.md1812-portal .md1812-button--small {
	padding: 6px 12px;
	font-size: 13px;
}

.md1812-portal .md1812-button--block {
	width: 100%;
}

.md1812-portal .md1812-search-clear {
	width: 28px;
	min-width: 0;
	height: 28px;
	min-height: 0;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background-color: var(--md-line);
	color: var(--md-ink);
	font-size: 18px;
	line-height: 1;
}

.md1812-portal .md1812-viewswitch__button {
	width: auto;
	min-width: 0;
	height: auto;
	min-height: 0;
	padding: 7px 14px;
	border: 0;
	border-radius: 0;
	font-size: 13px;
	line-height: 1.3;
	letter-spacing: .02em;
	background-color: transparent;
	color: var(--md-muted);
}

.md1812-portal .md1812-viewswitch__button + .md1812-viewswitch__button {
	border-left: 1px solid var(--md-line);
}

.md1812-portal .md1812-viewswitch__button[aria-pressed="true"] {
	background-color: var(--md-ink);
	color: #fff;
}

.md1812-portal .md1812-nav-toggle {
	width: 42px;
	min-width: 0;
	height: 38px;
	min-height: 0;
	padding: 0;
	border-radius: 6px;
	background-color: transparent;
	border: 1px solid rgba(255, 255, 255, .3);
	/* Restated here too: this block exists because the theme outranks a bare
	   class on a <button>, and a box stated in one place and not the other is
	   how half a rule goes missing. */
	margin-left: auto;
	flex: 0 0 auto;
}

.md1812-input:focus,
.md1812-select:focus {
	outline: 2px solid var(--md-gold);
	outline-offset: 1px;
	border-color: var(--md-gold);
}

.md1812-input.is-invalid {
	border-color: var(--md-error);
	background: #fdf6f6;
}

.md1812-field-error {
	margin: 6px 0 0;
	font-size: 13px;
	color: var(--md-error);
	min-height: 0;
}

.md1812-field-error:empty {
	display: none;
}

.md1812-checkbox {
	display: flex;
	align-items: center;
	gap: 10px;
	font-size: 14px;
	cursor: pointer;
}

/*
 * Themes commonly hide the native tick box with
 * input[type="checkbox"] { opacity: 0 } and draw their own from a pseudo
 * element on markup the portal does not produce, which leaves the label with
 * nothing beside it - the Go theme on md1812.org does exactly this. The portal
 * therefore draws its own box and states every property the theme touches.
 * Do not simplify these rules to a single class selector.
 */
.md1812-portal .md1812-checkbox__input,
.md1812-portal input[type="checkbox"].md1812-checkbox__input {
	-webkit-appearance: none;
	appearance: none;
	opacity: 1;
	position: relative;
	flex: 0 0 20px;
	width: 20px;
	height: 20px;
	min-width: 20px;
	margin: 0;
	padding: 0;
	border: 2px solid #bdb5a6;
	border-radius: 4px;
	background: #fff;
	box-shadow: none;
	cursor: pointer;
	transition: background .15s ease, border-color .15s ease;
}

/*
 * Every state selector repeats input[type="checkbox"] so that it outranks the
 * base rule above, which carries that attribute itself. Dropping it here made
 * a ticked box paint exactly like an empty one - the member could tick it and
 * see nothing happen.
 */
.md1812-portal input[type="checkbox"].md1812-checkbox__input:hover {
	border-color: var(--md-ink);
}

.md1812-portal input[type="checkbox"].md1812-checkbox__input:checked {
	background: var(--md-ink);
	background-color: var(--md-ink);
	border-color: var(--md-ink);
}

.md1812-portal input[type="checkbox"].md1812-checkbox__input:checked::after {
	content: "";
	position: absolute;
	left: 5px;
	top: 1px;
	width: 5px;
	height: 10px;
	border: solid #fff;
	border-width: 0 2px 2px 0;
	transform: rotate(45deg);
}

/*
 * `appearance: none` takes the native half-ticked dash away with everything
 * else, and nothing here drew a replacement. The dues picker has always set
 * `indeterminate` when some but not all of the roll is ticked - and it painted
 * as a plain empty box, so the control said "nothing is selected" while fifty
 * of fifty-seven members were. It needs a state of its own, and repeats
 * input[type="checkbox"] for the reason given above.
 */
.md1812-portal input[type="checkbox"].md1812-checkbox__input:indeterminate {
	background: var(--md-ink);
	background-color: var(--md-ink);
	border-color: var(--md-ink);
}

.md1812-portal input[type="checkbox"].md1812-checkbox__input:indeterminate::after {
	content: "";
	position: absolute;
	left: 3px;
	top: 7px;
	width: 10px;
	height: 0;
	border: solid #fff;
	border-width: 0 0 2px;
	transform: none;
}

.md1812-portal input[type="checkbox"].md1812-checkbox__input:focus-visible {
	outline: 2px solid var(--md-gold);
	outline-offset: 2px;
}

/*
 * And the same again for radios, for the same reason and against the same
 * theme.
 *
 * The tick box above was rescued in 1.8.2; the radio was left native, and on
 * md1812.org the Go theme hides it exactly as it hides a checkbox. That left
 * the two controls that decide **who may read a document** - Members, or
 * Officers only - drawn as two labels with nothing beside them. Craig's
 * report, 16 Sep: the filing screen "doesn't allow me to select officer or
 * member". Clicking the words did still work, because the input sits inside
 * its label, but nothing on the screen ever changed to say so.
 *
 * Every rule repeats input[type="radio"] so it outranks the base rule, which
 * carries that attribute itself. Dropping it on a state selector is what once
 * made a ticked box paint exactly like an empty one.
 */
.md1812-radio {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	font-size: 14px;
	cursor: pointer;
}

.md1812-portal .md1812-radio__input,
.md1812-portal input[type="radio"].md1812-radio__input {
	-webkit-appearance: none;
	appearance: none;
	opacity: 1;
	position: relative;
	flex: 0 0 20px;
	width: 20px;
	height: 20px;
	min-width: 20px;
	margin: 2px 0 0;
	padding: 0;
	border: 2px solid #bdb5a6;
	border-radius: 50%;
	background: #fff;
	box-shadow: none;
	cursor: pointer;
	transition: border-color .15s ease;
}

.md1812-portal input[type="radio"].md1812-radio__input:hover {
	border-color: var(--md-ink);
}

.md1812-portal input[type="radio"].md1812-radio__input:checked {
	border-color: var(--md-ink);
}

/* The dot is drawn inside the ring rather than filling it, so the chosen one
   reads as chosen at a glance and not merely as darker. */
.md1812-portal input[type="radio"].md1812-radio__input:checked::after {
	content: "";
	position: absolute;
	left: 3px;
	top: 3px;
	width: 10px;
	height: 10px;
	border-radius: 50%;
	background: var(--md-ink);
}

.md1812-portal input[type="radio"].md1812-radio__input:focus-visible {
	outline: 2px solid var(--md-gold);
	outline-offset: 2px;
}

/*
 * A fieldset is the right element for a group of radios and it arrives with a
 * browser-drawn box, a default margin and a min-width that ignores flex. The
 * portal's fields are flat, so state all three rather than let one group on one
 * screen look like a form from 1999.
 */
.md1812-portal fieldset.md1812-field {
	border: 0;
	margin: 0 0 18px;
	padding: 0;
	min-width: 0;
}

.md1812-portal fieldset.md1812-field > legend {
	padding: 0;
	margin-bottom: 6px;
}

/* The line under a radio's own label: what that choice actually means. */
.md1812-radio__note {
	display: block;
	margin-top: 2px;
	font-size: 13px;
	line-height: 1.5;
	color: var(--md-muted);
}

.md1812-form__actions {
	display: flex;
	align-items: center;
	gap: 14px;
	margin-top: 8px;
	flex-wrap: wrap;
}

.md1812-form__status {
	font-size: 14px;
	color: var(--md-muted);
}

.md1812-form__status.is-ok,
.md1812-help.is-ok {
	color: var(--md-success);
	font-weight: 600;
}

.md1812-form__status.is-error,
.md1812-help.is-error {
	color: var(--md-error);
	font-weight: 600;
}

.md1812-form__status.is-ok::before,
.md1812-help.is-ok::before {
	content: "✓";
	margin-right: 6px;
}

/* ---------- Sign in ---------- */

.md1812-auth {
	display: flex;
	justify-content: center;
	padding: 24px 0 40px;
}

.md1812-auth__card {
	width: 100%;
	max-width: 420px;
	background: var(--md-surface);
	border: 1px solid var(--md-line);
	border-top: 4px solid var(--md-gold);
	border-radius: var(--md-radius);
	padding: 28px;
	box-shadow: var(--md-shadow);
}

.md1812-auth__crest {
	display: block;
	height: 104px;
	width: auto;
	max-width: 60%;
	margin: 0 auto 18px;
}

.md1812-auth__title {
	font-family: var(--md-serif);
	font-size: 26px;
	margin: 0 0 6px;
	color: var(--md-ink);
}

.md1812-auth__intro {
	color: var(--md-muted);
	font-size: 14px;
	margin: 0 0 20px;
}

.md1812-auth__links {
	margin: 18px 0 0;
	font-size: 14px;
	text-align: center;
	color: var(--md-muted);
}

.md1812-auth__links a {
	color: var(--md-ink);
}

/* ---------- Dashboard ---------- */

.md1812-welcome {
	margin-bottom: 24px;
}

.md1812-welcome__note {
	color: var(--md-muted);
}

/*
 * The dashboard grid is placed by hand rather than left to `auto-fit`.
 *
 * `repeat(auto-fit, minmax(280px, 1fr))` gave three equal columns of 347px at
 * the shell's full 1120px. The four cards are nowhere near equal in height -
 * the membership record runs to about 590px, the dues card to 340 and the
 * positions list to 175 - so the archive card wrapped onto a second row in
 * column one and left a void of roughly 850x540px of empty paper under the
 * other two. The cards that wanted width (the archive, whose titles wrapped to
 * two lines at 347px) were the ones squeezed, and the card with two lines in it
 * got a full column to itself.
 *
 * So: the membership record is the anchor and takes the wide column; dues and
 * positions stack in a rail beside it; the archive spans the full width
 * underneath, where it has room for two columns of entries. Slack is pushed to
 * the foot of the rail by the `min-content 1fr auto` rows, so the gap between
 * the two rail cards stays the same 20px as everywhere else rather than
 * stretching to absorb the difference.
 *
 * This only holds together because the dues card is rendered in every state -
 * see dashboard.php. A conditional card would leave a hole in the rail.
 */
.md1812-dash-grid {
	display: grid;
	grid-template-columns: 1fr;
	gap: 20px;
	align-items: start;
}

@media (min-width: 768px) {
	.md1812-dash-grid {
		grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
		grid-template-rows: min-content 1fr auto;
	}

	/*
	 * These two are stretched against the grid's `align-items: start` so the
	 * two columns finish on the same line.
	 *
	 * Whichever column is taller decides the height of the rail's second row,
	 * and the other column was then left short by the difference - measured on
	 * the live dashboard as a 10px step, which reads as a mistake rather than
	 * as two cards of different lengths. Stretching both ends of the span
	 * closes it in either direction: when the rail is the taller column the
	 * record card grows to meet it, and when the record is taller the positions
	 * card takes up the slack that would otherwise sit below it.
	 *
	 * The dues card is deliberately left alone - its row is sized
	 * `min-content`, so it is already exactly as tall as its own contents.
	 */
	.md1812-card--record {
		grid-column: 1;
		grid-row: 1 / span 2;
		align-self: stretch;
	}

	.md1812-card--dues {
		grid-column: 2;
		grid-row: 1;
	}

	.md1812-card--positions {
		grid-column: 2;
		grid-row: 2;
		align-self: stretch;
	}

	.md1812-card--recent {
		grid-column: 1 / -1;
	}
}

@media (min-width: 1024px) {
	.md1812-dash-grid {
		grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
	}

	/*
	 * Six entries in one column down the full width of the shell would be a
	 * very long thin card. Two columns keep it to the same height as the rail
	 * above it. Row flow fills left, right, left, right, so the last item in
	 * each column is one of the final two - hence the `-n+2` rather than
	 * `:last-child`, which would leave a stray rule under column one.
	 */
	.md1812-card--recent .md1812-recent {
		display: grid;
		grid-template-columns: repeat(2, minmax(0, 1fr));
		column-gap: 40px;
	}

	.md1812-card--recent .md1812-recent__item:nth-last-child(-n+2) {
		border-bottom: 0;
	}
}

.md1812-record {
	margin: 0 0 18px;
}

.md1812-record__row {
	display: flex;
	justify-content: space-between;
	gap: 16px;
	padding: 8px 0;
	border-bottom: 1px dotted var(--md-line);
}

.md1812-record__row:last-child {
	border-bottom: 0;
}

.md1812-record dt {
	font-size: 13px;
	color: var(--md-muted);
	margin: 0;
}

.md1812-record dd {
	margin: 0;
	font-size: 14px;
	text-align: right;
	font-weight: 600;
	color: var(--md-ink);
}

.md1812-positions,
.md1812-recent {
	list-style: none;
	margin: 0 0 18px;
	padding: 0;
}

.md1812-position {
	display: flex;
	justify-content: space-between;
	gap: 12px;
	padding: 9px 0;
	border-bottom: 1px dotted var(--md-line);
	font-size: 14px;
}

.md1812-position:last-child {
	border-bottom: 0;
}

.md1812-position__title {
	font-weight: 600;
	color: var(--md-ink);
}

.md1812-position.is-current .md1812-position__title::after {
	content: "•";
	color: var(--md-gold);
	margin-left: 6px;
}

.md1812-position__term {
	color: var(--md-muted);
	white-space: nowrap;
}

.md1812-recent__item {
	padding: 9px 0;
	border-bottom: 1px dotted var(--md-line);
}

.md1812-recent__item:last-child {
	border-bottom: 0;
}

.md1812-recent__link {
	display: block;
	color: var(--md-ink);
	font-weight: 600;
	font-size: 15px;
	text-decoration: none;
}

.md1812-recent__link:hover {
	text-decoration: underline;
}

.md1812-recent__meta {
	display: block;
	font-size: 13px;
	color: var(--md-muted);
}

/* ---------- Archive filters ---------- */

.md1812-filters {
	background: var(--md-surface);
	border: 1px solid var(--md-line);
	border-radius: var(--md-radius);
	padding: 20px;
	margin-bottom: 24px;
	box-shadow: var(--md-shadow);
}

.md1812-search-wrap {
	position: relative;
}

.md1812-search-icon {
	position: absolute;
	left: 13px;
	top: 50%;
	transform: translateY(-50%);
	width: 19px;
	height: 19px;
	color: var(--md-muted);
	pointer-events: none;
}

.md1812-search-wrap:focus-within .md1812-search-icon {
	color: var(--md-ink);
}

.md1812-input--search {
	padding-left: 40px;
	padding-right: 40px;
	font-size: 16px;
}

.md1812-search-clear {
	position: absolute;
	right: 8px;
	top: 50%;
	transform: translateY(-50%);
	width: 28px;
	height: 28px;
	border: 0;
	border-radius: 50%;
	background: var(--md-line);
	color: var(--md-ink);
	font-size: 18px;
	line-height: 1;
	cursor: pointer;
}

.md1812-filters__row {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
	gap: 14px;
	margin-top: 6px;
}

.md1812-filters__row .md1812-field {
	margin-bottom: 0;
}

.md1812-filters__foot {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	margin-top: 16px;
	padding-top: 14px;
	border-top: 1px solid var(--md-line);
	flex-wrap: wrap;
}

.md1812-results-count {
	margin: 0;
	font-size: 14px;
	color: var(--md-muted);
}

/* ---------- Filter foot tools ---------- */

.md1812-filters__tools {
	display: flex;
	align-items: center;
	gap: 12px;
	flex-wrap: wrap;
}

.md1812-viewswitch {
	display: inline-flex;
	border: 1px solid var(--md-line);
	border-radius: var(--md-radius-control);
	overflow: hidden;
	background: var(--md-surface);
}

.md1812-viewswitch__button {
	appearance: none;
	border: 0;
	background: transparent;
	font-family: inherit;
	font-size: 13px;
	letter-spacing: .02em;
	color: var(--md-muted);
	padding: 7px 14px;
	cursor: pointer;
}

.md1812-viewswitch__button + .md1812-viewswitch__button {
	border-left: 1px solid var(--md-line);
}

.md1812-viewswitch__button[aria-pressed="true"] {
	background: var(--md-ink);
	color: #fff;
}

.md1812-viewswitch__button:focus-visible {
	outline: 2px solid var(--md-gold);
	outline-offset: -2px;
}

/* ---------- Results ---------- */

.md1812-results {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(258px, 1fr));
	gap: 18px;
}

/* The list view is a single block rather than a card grid. The frame is
   clipped to the radius so the header band and the last row meet the border
   cleanly at every corner. */
.md1812-results[data-md1812-view="table"] {
	display: block;
	overflow: hidden;
	background: var(--md-surface);
	border: 1px solid var(--md-line);
	border-radius: var(--md-radius);
	box-shadow: var(--md-shadow);
}

/* ---------- List view ---------- */

.md1812-table {
	width: 100%;
	border-collapse: collapse;
	font-size: 14.5px;
	table-layout: fixed;
}

.md1812-table thead th {
	text-align: left;
	font-size: 11px;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--md-muted);
	font-weight: 600;
	padding: 12px 16px;
	border-bottom: 1px solid var(--md-line);
	background: var(--md-paper);
	white-space: nowrap;
}

.md1812-table td {
	padding: 13px 16px;
	border-bottom: 1px solid var(--md-line);
	vertical-align: middle;
	/* break-word, not anywhere: only a word that cannot fit on its own line is
	   broken, so ordinary titles are not split mid-word. */
	overflow-wrap: break-word;
}

/* The container supplies the closing line, so the final row must not draw a
   second one a pixel above it. */
.md1812-table tbody tr:last-child td {
	border-bottom: 0;
}

.md1812-table tbody tr:hover {
	background: #fbfaf7;
}

/*
 * Themes style bare table elements, which beats a class on specificity for
 * anything the portal does not declare. The GoDaddy Go theme draws a 2px rule
 * on the top, left and right of every cell and gives the table a bottom
 * margin, so grid lines appeared through the list and the frame stopped short
 * of its own closing border. Everything the list needs is restated here.
 */
.md1812-portal .md1812-table {
	margin: 0;
	border: 0;
	width: 100%;
	background: transparent;
	border-collapse: collapse;
}

.md1812-portal .md1812-table th,
.md1812-portal .md1812-table td {
	border: 0;
	border-bottom: 1px solid var(--md-line);
	background-image: none;
	/* The Go theme sets word-break: break-all on table cells, which chops
	   ordinary words mid-character — "Memoria / l Buoy Deployment". */
	word-break: normal;
	overflow-wrap: break-word;
}

.md1812-portal .md1812-table thead th {
	background-color: var(--md-paper);
}

.md1812-portal .md1812-table tbody tr {
	background-color: transparent;
}

.md1812-portal .md1812-table tbody tr:hover {
	background-color: #fbfaf7;
}

/* `td` alone left the rule under a row header standing when the rest of the
   row's had gone, so the last row of every roster section ended in a short line
   under the first column and nothing under the other four. */
.md1812-portal .md1812-table tbody tr:last-child th,
.md1812-portal .md1812-table tbody tr:last-child td {
	border-bottom: 0;
}

/* Fixed layout, so every column is declared here and the table can never grow
   wider than its frame. The title carries the most information and gets the
   room. */
.md1812-table th:nth-child(1) { width: 50%; }
.md1812-table th:nth-child(2) { width: 21%; }
.md1812-table th:nth-child(3) { width: 15%; }
.md1812-table th:nth-child(4) { width: 14%; }

.md1812-td-date {
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
}

/* Description and file size share the second line; the description gives way
   first so the size is never the thing that gets truncated. */
.md1812-rowdoc__sub {
	display: flex;
	align-items: baseline;
	gap: 10px;
	min-width: 0;
}

.md1812-rowdoc__sub .md1812-rowdoc__excerpt {
	flex: 1 1 auto;
	min-width: 0;
}

/* The passage from inside the document that matched the search. */
.md1812-rowdoc__snippet,
.md1812-doc__snippet {
	display: block;
	margin-top: 6px;
	padding: 7px 10px;
	border-left: 3px solid var(--md-gold);
	background: var(--md-gold-soft);
	border-radius: 0 4px 4px 0;
	font-size: 13px;
	line-height: 1.5;
	color: #5c4a26;
}

.md1812-mark-hit {
	background: #f0c96a;
	color: #3f3110;
	padding: 0 2px;
	border-radius: 2px;
	font-weight: 600;
}

.md1812-rowdoc__meta {
	flex: 0 0 auto;
	font-size: 12.5px;
	color: var(--md-muted);
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
}

.md1812-td-actions {
	text-align: right;
	white-space: nowrap;
}

.md1812-rowdoc {
	display: flex;
	align-items: center;
	gap: 12px;
	min-width: 0;
}

.md1812-rowdoc__text {
	display: flex;
	flex-direction: column;
	gap: 2px;
	min-width: 0;
}

/* Title and access chip share a line; without this the chip becomes a flex
   item of the column and stretches the whole width of the cell. */
.md1812-rowdoc__head {
	display: flex;
	align-items: center;
	gap: 8px;
	flex-wrap: wrap;
}

.md1812-rowdoc__title {
	font-family: var(--md-serif);
	font-size: 15.5px;
	color: var(--md-ink);
	text-decoration: none;
	line-height: 1.3;
}

.md1812-rowdoc__title:hover {
	text-decoration: underline;
}

.md1812-rowdoc__excerpt {
	font-size: 13px;
	color: var(--md-muted);
	display: -webkit-box;
	-webkit-line-clamp: 1;
	line-clamp: 1;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.md1812-mark {
	flex: 0 0 auto;
	width: 38px;
	height: 38px;
	border-radius: 6px;
	overflow: hidden;
	background: linear-gradient(140deg, #16294a, #2b4573);
	display: flex;
	align-items: center;
	justify-content: center;
}

.md1812-mark img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.md1812-mark--type {
	font-family: var(--md-mono, ui-monospace, Menlo, Consolas, monospace);
	font-size: 9.5px;
	letter-spacing: .04em;
	/* Not --md-gold: against the light end of the badge's navy gradient that
	   measures 3.0:1, well under the 4.5:1 this small text needs. This lighter
	   gold measures 5.7:1 there and 8.6:1 at the dark end. */
	color: #e2c489;
	font-weight: 600;
}

.md1812-button--small {
	padding: 6px 12px;
	font-size: 13px;
}

.md1812-doc {
	display: flex;
	flex-direction: column;
	background: var(--md-surface);
	border: 1px solid var(--md-line);
	border-radius: var(--md-radius);
	overflow: hidden;
	box-shadow: var(--md-shadow);
}

.md1812-doc__thumb {
	position: relative;
	display: block;
	height: 150px;
	background: linear-gradient(140deg, #16294a, #2b4573);
	overflow: hidden;
}

.md1812-doc__thumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.md1812-doc__ext {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	font-family: var(--md-serif);
	font-size: 24px;
	letter-spacing: .08em;
	color: var(--md-gold);
}

.md1812-doc__body {
	padding: 16px;
	display: flex;
	flex-direction: column;
	gap: 8px;
	flex: 1 1 auto;
}

.md1812-doc__title {
	margin: 0;
	font-family: var(--md-serif);
	font-size: 17px;
	line-height: 1.35;
}

.md1812-doc__title a {
	color: var(--md-ink);
	text-decoration: none;
}

.md1812-doc__title a:hover {
	text-decoration: underline;
}

.md1812-doc__meta {
	margin: 0;
	font-size: 13px;
	color: var(--md-muted);
}

.md1812-doc__excerpt {
	margin: 0;
	font-size: 14px;
	color: var(--md-text);
}

.md1812-doc__actions {
	margin-top: auto;
	padding: 0 16px 16px;
	display: flex;
	gap: 8px;
	flex-wrap: wrap;
}

.md1812-doc__actions .md1812-button {
	padding: 7px 13px;
	font-size: 14px;
}

.md1812-chips {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	margin: 0;
}

.md1812-chip {
	display: inline-block;
	padding: 3px 9px;
	border-radius: 999px;
	background: var(--md-gold-soft);
	color: #6b4d17;
	font-size: 12px;
	letter-spacing: .02em;
}

.md1812-chip--officer {
	background: #f5dcdc;
	color: var(--md-crimson);
}

.md1812-chip--member {
	background: #dfe7f3;
	color: var(--md-ink);
}


@media (max-width: 900px) {
	/* Below 900px the list stops being a table and becomes stacked records,
	   so nothing has to be scrolled sideways to be read. */
	.md1812-results[data-md1812-view="table"] {
		overflow-x: visible;
		background: transparent;
		border: 0;
		box-shadow: none;
	}

	.md1812-table {
		min-width: 0;
		display: block;
	}

	.md1812-table thead {
		position: absolute;
		width: 1px;
		height: 1px;
		overflow: hidden;
		clip: rect(0, 0, 0, 0);
	}

	.md1812-table tbody,
	.md1812-table tr,
	.md1812-table td {
		display: block;
		width: auto;
	}

	/* Percentage widths meant for real table columns would otherwise squeeze
	   these into a narrow strip once they become blocks. */
	.md1812-table th:first-child,
	.md1812-table th:nth-child(2),
	.md1812-table td.md1812-td-doc,
	.md1812-table td.md1812-td-cat {
		width: auto;
	}

	.md1812-table tr {
		background: var(--md-surface);
		border: 1px solid var(--md-line);
		border-radius: var(--md-radius);
		box-shadow: var(--md-shadow);
		margin-bottom: 14px;
		padding: 6px 4px;
	}

	.md1812-table tbody tr:hover {
		background: var(--md-surface);
	}

	.md1812-table td {
		border-bottom: 1px dotted var(--md-line);
		padding: 9px 12px;
		display: flex;
		justify-content: space-between;
		align-items: baseline;
		gap: 14px;
		text-align: right;
	}

	/* A cell with nothing in it would otherwise stack as a lone label. */
	.md1812-table td:empty {
		display: none;
	}

	.md1812-table td::before {
		content: attr(data-label);
		font-size: 11px;
		letter-spacing: .09em;
		text-transform: uppercase;
		color: var(--md-muted);
		text-align: left;
		flex: 0 0 auto;
	}

	.md1812-table td.md1812-td-doc,
	.md1812-table td.md1812-td-actions {
		display: block;
		text-align: left;
	}

	.md1812-table td.md1812-td-doc::before,
	.md1812-table td.md1812-td-actions::before {
		content: none;
	}

	.md1812-table td.md1812-td-actions {
		border-bottom: 0;
		display: flex;
		gap: 8px;
	}

	.md1812-table td.md1812-td-actions .md1812-button {
		flex: 1 1 auto;
		justify-content: center;
	}

	.md1812-rowdoc__excerpt {
		-webkit-line-clamp: 2;
		line-clamp: 2;
	}
}

/* ---------- Member directory ---------- */

.md1812-portrait {
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	overflow: hidden;
	background: var(--md-ink);
	border: 2px solid var(--md-gold);
}

.md1812-portrait img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.md1812-portrait__initials {
	font-family: var(--md-serif);
	color: var(--md-gold);
	line-height: 1;
}

.md1812-portrait--large {
	width: 72px;
	height: 72px;
}

.md1812-portrait--large .md1812-portrait__initials {
	font-size: 24px;
}

.md1812-portrait--small {
	width: 42px;
	height: 42px;
	border-width: 1px;
}

.md1812-portrait--small .md1812-portrait__initials {
	font-size: 15px;
}

.md1812-member {
	display: flex;
	flex-direction: column;
	gap: 14px;
	background: var(--md-surface);
	border: 1px solid var(--md-line);
	border-radius: var(--md-radius);
	padding: 18px;
	box-shadow: var(--md-shadow);
}

.md1812-member__head {
	display: flex;
	align-items: flex-start;
	gap: 14px;
	min-width: 0;
}

.md1812-member__ident {
	min-width: 0;
}

.md1812-member__name {
	font-family: var(--md-serif);
	/* Crimson Text has a smaller x-height than the Georgia this replaced, so
	   the same number reads a step quieter beside Nunito Sans. Optical, not
	   arithmetic. */
	font-size: 19.5px;
	line-height: 1.25;
	margin: 0 0 6px;
	color: var(--md-ink);
}

.md1812-member__role {
	display: flex;
	align-items: center;
	gap: 8px;
	flex-wrap: wrap;
	margin: 0 0 6px;
	font-size: 13px;
}

.md1812-member__office {
	margin: 0;
	font-size: 14px;
	font-weight: 600;
	color: var(--md-gold-text);
}

.md1812-member__contact {
	display: flex;
	flex-direction: column;
	gap: 3px;
	min-width: 0;
}

.md1812-contact {
	font-size: 14px;
	color: var(--md-ink);
	text-decoration: none;
	overflow-wrap: anywhere;
}

.md1812-contact:hover {
	text-decoration: underline;
}

.md1812-contact--none {
	color: var(--md-muted);
	font-style: italic;
}

.md1812-member__facts {
	margin: 0;
	padding-top: 12px;
	border-top: 1px dotted var(--md-line);
	display: flex;
	flex-direction: column;
	gap: 6px;
	font-size: 13px;
}

.md1812-member__facts div {
	display: flex;
	justify-content: space-between;
	gap: 12px;
}

.md1812-member__facts dt {
	color: var(--md-muted);
	margin: 0;
}

.md1812-member__facts dd {
	margin: 0;
	text-align: right;
	color: var(--md-ink);
	font-variant-numeric: tabular-nums;
}

/*
 * The ancestry row breaks the pattern of the facts above it on purpose.
 *
 * Those are one short value each and read well as label-left, value-right. An
 * ancestor is a full name with a rank and a pair of dates, and a member may
 * have fourteen of them, so pushed to the right they wrap into a ragged column
 * against the card edge. This row stacks instead: label, then the list beneath
 * it, aligned left like the prose it is.
 */
/* Prefixed with the parent, and not for tidiness: the rule it has to beat is
   `.md1812-member__facts div { display: flex }` at (0,1,1), which a lone class
   at (0,1,0) loses to. Unprefixed, this block did nothing at all and the label
   went on sitting beside the list in a column two words wide. */
.md1812-member__facts .md1812-member__ancestry {
	display: block;
}

.md1812-member__facts .md1812-member__ancestry dd {
	text-align: left;
	margin-top: 3px;
	font-variant-numeric: normal;
}

.md1812-member__anclist {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 2px;
}

/* The ancestor a member joined on, set apart from the supplementals proved
   afterwards - a distinction the Society keeps, and the reason the list is
   never sorted. */
.md1812-member__anclist li:first-child {
	font-weight: 600;
}

.md1812-member__ancnote {
	display: block;
	margin-top: 4px;
	font-size: 12px;
	color: var(--md-muted);
}

/*
 * Member, Membership, Contact, State no., Joined. The name column carries the
 * portrait and the positions held, so it takes the room; the two number
 * columns are sized to their content rather than to a share of the table,
 * which is what closes the gaps between them.
 */
.md1812-table--members th:nth-child(1) { width: 33%; }
.md1812-table--members th:nth-child(2) { width: 13%; }
.md1812-table--members th:nth-child(3) { width: 30%; }
.md1812-table--members th:nth-child(4) { width: 11%; }
.md1812-table--members th:nth-child(5) { width: 13%; }

/*
 * With the edit column, six shares rather than five - and its own modifier
 * rather than an extra rule, because the five above already add up to 100% and
 * a sixth column added to them gets nothing. That is not hypothetical: it is
 * exactly what happened, and the "Edit record" link rendered in a zero-width
 * cell that spilled 400px off the right-hand edge of the page.
 *
 * The column is only in the markup when the viewer can edit somebody, so an
 * ordinary member reading the directory still gets the five-column layout.
 */
.md1812-table--members-edit th:nth-child(1) { width: 30%; }
.md1812-table--members-edit th:nth-child(2) { width: 12%; }
.md1812-table--members-edit th:nth-child(3) { width: 26%; }
.md1812-table--members-edit th:nth-child(4) { width: 10%; }
.md1812-table--members-edit th:nth-child(5) { width: 12%; }
.md1812-table--members-edit th:nth-child(6) { width: 10%; }

/* Tighter than the archive: five columns of short values read better close
   together than spread across the full width. */
.md1812-portal .md1812-table--members th,
.md1812-portal .md1812-table--members td {
	padding-left: 10px;
	padding-right: 10px;
}

/*
 * The results frame clips to a 10px radius, so a cell flush with its left edge
 * had the round portrait sliced down one side. The outer columns keep a little
 * breathing room; only the gaps between columns are tightened.
 */
.md1812-portal .md1812-table--members th:first-child,
.md1812-portal .md1812-table--members td:first-child {
	padding-left: 14px;
}

.md1812-portal .md1812-table--members th:last-child,
.md1812-portal .md1812-table--members td:last-child {
	padding-right: 14px;
}

/* Positions held, under the name: plainly a different kind of fact from the
   name above it, and from the membership beside it. */
.md1812-role {
	display: block;
	color: var(--md-gold-text);
	font-size: 13px;
	line-height: 1.45;
	margin-top: 1px;
}

.md1812-role--past {
	color: var(--md-muted);
}

/* Standing above, dues below. Ordinary standing is quiet; anything other than
   Active is not, because that is the row someone is looking for. */
.md1812-membership {
	display: block;
	font-size: 13px;
	line-height: 1.4;
}

.md1812-membership__standing {
	display: block;
	color: var(--md-muted);
}

.md1812-membership__standing.is-notable {
	color: var(--md-error);
	font-weight: 600;
}

.md1812-membership__type {
	display: block;
	color: var(--md-text);
}

/* An email long enough to need two lines breaks after the @, never mid-word. */
.md1812-contact {
	overflow-wrap: anywhere;
}

.md1812-directory__note {
	margin-top: 28px;
}

.md1812-skeleton--member {
	display: flex;
	align-items: center;
	gap: 14px;
	padding: 18px;
	border: 1px solid var(--md-line);
	border-radius: var(--md-radius);
	background: var(--md-surface);
}

.md1812-skeleton--member .md1812-skeleton__badge {
	width: 72px;
	height: 72px;
	border-radius: 50%;
}

.md1812-skeleton--member .md1812-skeleton__body {
	flex: 1 1 auto;
	padding: 0;
}

/* ---------- Loading skeletons (AC 3.4) ---------- */

.md1812-skeleton {
	background: var(--md-surface);
	border: 1px solid var(--md-line);
	border-radius: var(--md-radius);
	overflow: hidden;
}

.md1812-skeleton__thumb,
.md1812-skeleton__line {
	background: linear-gradient(90deg, #eceae5 25%, #f6f4f0 37%, #eceae5 63%);
	background-size: 400% 100%;
	animation: md1812-shimmer 1.3s ease infinite;
}

.md1812-skeleton__thumb {
	height: 150px;
}

/* Skeleton rows for the list view. */
.md1812-rows--skeleton {
	display: flex;
	flex-direction: column;
}

.md1812-skeleton--row {
	display: flex;
	align-items: center;
	gap: 12px;
	padding: 12px 14px;
	border: 0;
	border-bottom: 1px solid var(--md-line);
	border-radius: 0;
}

.md1812-skeleton--row:last-child {
	border-bottom: 0;
}

.md1812-skeleton--row .md1812-skeleton__body {
	flex: 1 1 auto;
	padding: 0;
}

.md1812-skeleton--row .md1812-skeleton__line:last-child {
	margin-bottom: 0;
}

.md1812-skeleton__badge {
	width: 38px;
	height: 38px;
	border-radius: 6px;
	flex: 0 0 auto;
	background: linear-gradient(90deg, #eceae5 25%, #f6f4f0 37%, #eceae5 63%);
	background-size: 400% 100%;
	animation: md1812-shimmer 1.3s ease infinite;
}

/* The empty panel supplies its own frame, so the list container drops its own. */
.md1812-results.is-empty {
	background: transparent;
	border: 0;
	box-shadow: none;
	overflow: visible;
}

.md1812-skeleton__body {
	padding: 16px;
}

.md1812-skeleton__line {
	height: 12px;
	border-radius: 4px;
	margin-bottom: 10px;
}

.md1812-skeleton__line--title {
	height: 17px;
	width: 78%;
}

.md1812-skeleton__line--short {
	width: 45%;
	margin-bottom: 0;
}

@keyframes md1812-shimmer {
	0% {
		background-position: 100% 50%;
	}

	100% {
		background-position: 0 50%;
	}
}

@media (prefers-reduced-motion: reduce) {
	.md1812-skeleton__thumb,
	.md1812-skeleton__line {
		animation: none;
	}
}

/* ---------- Empty state (AC 3.5) ---------- */

.md1812-empty {
	grid-column: 1 / -1;
	text-align: center;
	padding: 48px 24px;
	border: 1px dashed var(--md-line);
	border-radius: var(--md-radius);
	background: var(--md-surface);
}

.md1812-empty__mark {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 56px;
	height: 56px;
	border-radius: 50%;
	background: var(--md-gold-soft);
	color: var(--md-gold);
	font-size: 26px;
	margin-bottom: 14px;
}

.md1812-empty__title {
	font-family: var(--md-serif);
	font-size: 21px;
	margin: 0 0 6px;
	color: var(--md-ink);
}

.md1812-empty__body {
	margin: 0 auto 18px;
	max-width: 42ch;
	color: var(--md-muted);
	font-size: 15px;
}

/* ---------- Pagination ---------- */

.md1812-pagination {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 12px;
	margin-top: 28px;
	flex-wrap: wrap;
}

.md1812-pagination:empty {
	margin: 0;
}

.md1812-pagination__status {
	font-size: 14px;
	color: var(--md-muted);
}

/* ---------- Single document ---------- */

.md1812-breadcrumb {
	margin: 0 0 12px;
	font-size: 14px;
}

.md1812-breadcrumb a {
	color: var(--md-ink);
	text-decoration: none;
}

.md1812-document__meta {
	display: flex;
	align-items: center;
	gap: 10px;
	color: var(--md-muted);
	font-size: 14px;
	margin: 0 0 20px;
	flex-wrap: wrap;
}

.md1812-viewer {
	background: var(--md-surface);
	border: 1px solid var(--md-line);
	border-radius: var(--md-radius);
	overflow: hidden;
	margin-bottom: 22px;
	box-shadow: var(--md-shadow);
}

.md1812-viewer__image,
.md1812-viewer__media {
	display: block;
	width: 100%;
	height: auto;
	background: #101a2c;
}

.md1812-viewer__frame {
	display: block;
	width: 100%;
	height: 72vh;
	min-height: 420px;
	border: 0;
}

.md1812-viewer__placeholder {
	padding: 44px 20px;
	text-align: center;
	color: var(--md-muted);
}

.md1812-filetype {
	display: inline-block;
	font-family: var(--md-serif);
	font-size: 30px;
	color: var(--md-gold);
	letter-spacing: .08em;
}

.md1812-document__body {
	background: var(--md-surface);
	border: 1px solid var(--md-line);
	border-radius: var(--md-radius);
	padding: 22px;
	margin-bottom: 22px;
}

.md1812-document__aside {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
	gap: 18px;
}

/*
 * A row of buttons is a row, not two words in a paragraph.
 *
 * Download and "Open in a new tab" sat inside a <p> separated by nothing but
 * the newline between them in the template. That collapses to a single text
 * space - measured at 4px - so side by side they read as one smudged control,
 * and the moment the card is too narrow to hold both they stack **touching**,
 * with no vertical gap at all. At 320px that is a navy button sitting directly
 * on a white one, and a thumb cannot tell them apart.
 *
 * The gap belongs to the container, the way it does in .md1812-form__actions
 * and everywhere else in this stylesheet. Use this class for any two adjacent
 * buttons rather than relying on whitespace.
 */
.md1812-buttonrow {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px;
	margin: 0;
}

/*
 * Narrow enough that a row of two would wrap anyway: make them full width and
 * equal instead of leaving one long button under a short one. Buttons are
 * inline-flex and already centre their own label, so this only has to hand
 * them the width.
 */
@media (max-width: 480px) {
	.md1812-buttonrow > .md1812-button {
		flex: 1 1 100%;
	}
}

/* Its own margin, rather than whatever the theme gives a <p>. */
.md1812-document__edit {
	margin: 0 0 20px;
}

/* ---------- Profile ---------- */

.md1812-profile__grid {
	display: grid;
	grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
	gap: 22px;
	align-items: start;
}

/* ---------- Profile photograph ---------- */

.md1812-photo {
	display: flex;
	align-items: center;
	gap: 20px;
	flex-wrap: wrap;
	margin-bottom: 8px;
}

.md1812-photo.is-busy {
	opacity: .6;
	pointer-events: none;
}

.md1812-photo__frame {
	position: relative;
	width: 112px;
	height: 112px;
	flex: 0 0 auto;
	border-radius: 50%;
	overflow: hidden;
	background: var(--md-ink);
	border: 3px solid var(--md-gold);
	display: flex;
	align-items: center;
	justify-content: center;
}

.md1812-photo__image {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.md1812-photo__initials {
	font-family: var(--md-serif);
	font-size: 34px;
	letter-spacing: .04em;
	color: var(--md-gold);
}

.md1812-photo__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px;
	min-width: 0;
}

.md1812-photo__actions .md1812-help {
	flex: 1 0 100%;
	margin: 0;
}

/* The file input is driven by its label, which is styled as a button. */
.md1812-photo__input {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

.md1812-photo__input:focus-visible + .md1812-button,
.md1812-photo__actions label:focus-within {
	outline: 2px solid var(--md-gold);
	outline-offset: 2px;
}

.md1812-photo--compact {
	gap: 14px;
	margin-bottom: 16px;
	padding-bottom: 16px;
	border-bottom: 1px dotted var(--md-line);
}

.md1812-photo--compact .md1812-photo__frame {
	width: 76px;
	height: 76px;
	border-width: 2px;
}

.md1812-photo--compact .md1812-photo__initials {
	font-size: 24px;
}

.md1812-photo__name {
	font-family: var(--md-serif);
	font-size: 17px;
	color: var(--md-ink);
	flex: 1 0 100%;
}

.md1812-card__title--spaced {
	margin-top: 28px;
	padding-top: 20px;
	border-top: 1px solid var(--md-line);
}

/* ---------- Toasts (AC 4.2) ---------- */

.md1812-toast-stack {
	position: fixed;
	right: 20px;
	bottom: 20px;
	display: flex;
	flex-direction: column;
	gap: 10px;
	z-index: 9999;
	pointer-events: none;
}

.md1812-toast {
	min-width: 240px;
	max-width: 360px;
	padding: 13px 16px;
	border-radius: 10px;
	background: var(--md-ink);
	color: #fff;
	font-size: 14px;
	font-family: var(--md-font);
	box-shadow: 0 10px 30px rgba(18, 35, 63, .25);
	opacity: 0;
	transform: translateY(10px);
	transition: opacity .28s ease, transform .28s ease;
	pointer-events: auto;
}

.md1812-toast.is-visible {
	opacity: 1;
	transform: translateY(0);
}

.md1812-toast--success {
	background: var(--md-success);
}

.md1812-toast--error {
	background: var(--md-error);
}

@media (prefers-reduced-motion: reduce) {
	.md1812-toast {
		transition: none;
	}
}

/* ---------- Footer ---------- */

.md1812-footer {
	border-top: 1px solid var(--md-line);
	background: var(--md-surface);
	color: var(--md-muted);
	font-size: 13px;
	text-align: center;
	padding: 20px;
}

.md1812-footer p {
	margin: 0;
}

/* ---------- Responsive (AC 4.3) ---------- */

@media (max-width: 767px) {
	.md1812-shell {
		padding: 22px 16px 48px;
	}

	.md1812-page-title {
		font-size: 25px;
	}

	.md1812-nav-toggle {
		display: block;
	}

	/*
	 * `flex-wrap` wraps before it shrinks: a flex line is filled, and only the
	 * items that landed on it are then squeezed. So the brand, asking for its
	 * full 273px, kept line one to itself and pushed the menu button onto line
	 * two - and `min-width: 0` could not help, because nothing was being asked
	 * to shrink in the first place.
	 *
	 * A basis of zero makes the brand ask for nothing, so it never causes the
	 * wrap; it then grows into whatever the button leaves and its own text
	 * wraps inside that. The nav asks for a whole line, which is what it wants
	 * anyway when open.
	 */
	.md1812-brand {
		flex: 1 1 0;
	}

	.md1812-nav {
		flex-basis: 100%;
		display: none;
		width: 100%;
		flex-direction: column;
		align-items: stretch;
		gap: 2px;
		padding-top: 10px;
		border-top: 1px solid rgba(255, 255, 255, .16);
		margin-top: 10px;
	}

	.md1812-nav.is-open {
		display: flex;
	}

	.md1812-nav__link {
		padding: 11px 12px;
	}

	.md1812-nav__link--signout {
		margin-left: 0;
		margin-top: 6px;
		text-align: center;
	}

	.md1812-dash-grid,
	.md1812-profile__grid,
	.md1812-document__aside {
		grid-template-columns: 1fr;
	}

	.md1812-results {
		grid-template-columns: 1fr;
	}

	.md1812-filters__foot {
		align-items: flex-start;
	}

	.md1812-filters__tools {
		width: 100%;
		justify-content: space-between;
	}

	.md1812-filters__row {
		grid-template-columns: 1fr;
	}

	.md1812-record__row,
	.md1812-position {
		flex-direction: column;
		gap: 2px;
	}

	.md1812-record dd {
		text-align: left;
	}

	.md1812-viewer__frame {
		height: 60vh;
		min-height: 320px;
	}

	.md1812-toast-stack {
		left: 16px;
		right: 16px;
		bottom: 16px;
	}

	.md1812-toast {
		max-width: none;
	}
}

@media (max-width: 420px) {
	.md1812-brand__name {
		font-size: 15px;
	}

	.md1812-brand__logo {
		height: 48px;
	}

	.md1812-auth__crest {
		height: 84px;
	}

	.md1812-doc__actions {
		flex-direction: column;
	}

	.md1812-doc__actions .md1812-button {
		width: 100%;
	}
}


/* ---------- Leadership roster ---------- */

.md1812-roster__section {
	margin-bottom: 28px;
}

.md1812-roster__heading {
	font-family: var(--md-serif);
	font-size: 20px;
	color: var(--md-ink);
	margin: 0 0 10px;
	padding-bottom: 6px;
	border-bottom: 2px solid var(--md-gold);
}

/*
 * Every section of the roster is its own table, and with an automatic layout
 * each one sized its columns to its own contents: the directors carry a term,
 * the past presidents carry a year, the officers carry neither, so the
 * telephone column began at a different place in every section and the numbers
 * wandered by ninety pixels down the page. A fixed layout with the same five
 * widths in every table makes the columns line up as one roster, which is what
 * it is.
 */
.md1812-portal .md1812-table--roster {
	table-layout: fixed;
	width: 100%;
}

.md1812-portal .md1812-table--roster th,
.md1812-portal .md1812-table--roster td {
	padding: 8px 10px;
	vertical-align: top;
	font-size: 14px;
}

/* By position, not by class: the two contact columns share a class but hold
   very different things - a telephone number is a fixed width, an email
   address can run to thirty-six characters. */
.md1812-portal .md1812-table--roster tr > *:nth-child(1) { width: 27%; }
.md1812-portal .md1812-table--roster tr > *:nth-child(2) { width: 20%; }
.md1812-portal .md1812-table--roster tr > *:nth-child(3) { width: 13%; }
.md1812-portal .md1812-table--roster tr > *:nth-child(4) { width: 14%; }
.md1812-portal .md1812-table--roster tr > *:nth-child(5) { width: 26%; }

/* A fixed column cannot grow, so the one address on the roll that is longer
   than its column has to be allowed to break rather than spill over the edge. */
.md1812-portal .md1812-table--roster .md1812-roster__contact {
	overflow-wrap: anywhere;
}

.md1812-roster__title {
	text-align: left;
	font-weight: 600;
	color: var(--md-ink);
}

.md1812-roster__note {
	display: block;
	font-weight: 400;
	font-size: 12px;
	line-height: 1.4;
	color: var(--md-muted);
	margin-top: 2px;
}

/*
 * Where a position has more than one holder - the directors, the past
 * presidents - the title is printed against the first of them and the rest sit
 * under it. That reads correctly as a column, but it left every later row with
 * an empty `th scope="row"`, which is to say no row header at all for anyone
 * listening rather than looking. The title is now written on every row and the
 * repeats are hidden from the eye only; below 900px, where each row stands
 * alone as a card and needs to say what it is, they are shown.
 */
.md1812-roster__title-repeat {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	clip-path: inset(50%);
	white-space: nowrap;
}

.md1812-roster__name {
	white-space: nowrap;
}

.md1812-roster__term {
	color: var(--md-muted);
	white-space: nowrap;
}

.md1812-roster__contact a {
	color: var(--md-ink-soft);
}

.md1812-roster__tools {
	margin: 0 0 18px;
}

/*
 * The stacked roster.
 *
 * This block has to undo two things, and the first one is the reason the page
 * looked crushed on a telephone for as long as it did. The five column widths
 * above are written `.md1812-portal .md1812-table--roster tr > *:nth-child(N)`,
 * which weighs (0,3,1); a reset of `width: auto` on a list of elements weighs
 * only (0,2,1) and quietly lost, so a name, a telephone number and an email
 * address all went on stacking themselves inside a twenty-seven percent column
 * ninety-six pixels wide. `:nth-child(n)` matches every child and exists here
 * purely to carry the same weight as the rule it is cancelling. The same trap
 * caught the dues table; it is the house specificity bug.
 *
 * The second is that the portal's general table rules turn every table into
 * cards below this width, and those cards are built for label-and-value pairs:
 * each cell becomes a flex row with the column name in a `::before` and the
 * value pushed to the right. The roster has no column names to print - the
 * position, the person, the term and two ways to reach them read perfectly
 * well as plain lines - so it wants none of that, and inheriting it left every
 * value hard against the right edge of the card with a gutter beside it.
 */
@media (max-width: 900px) {
	.md1812-portal .md1812-table--roster {
		table-layout: auto;
	}

	.md1812-portal .md1812-table--roster,
	.md1812-portal .md1812-table--roster tbody,
	.md1812-portal .md1812-table--roster tr,
	.md1812-portal .md1812-table--roster tr > *:nth-child(n) {
		display: block;
		width: auto;
	}

	.md1812-portal .md1812-table--roster tr > *:nth-child(n) {
		text-align: left;
		padding: 0 14px;
		border-bottom: 0;
	}

	.md1812-portal .md1812-table--roster tr > *:nth-child(n)::before {
		content: none;
	}

	.md1812-portal .md1812-table--roster tr {
		padding: 12px 2px;
	}

	/* The template writes these cells with nothing between the tags precisely
	   so that this matches: a member with no telephone number should not be
	   given a blank line where one would be. */
	.md1812-portal .md1812-table--roster tr > *:nth-child(n):empty {
		display: none;
	}

	.md1812-portal .md1812-table--roster .md1812-roster__title {
		font-size: 11px;
		font-weight: 700;
		letter-spacing: .09em;
		text-transform: uppercase;
		color: var(--md-gold-text);
		margin-bottom: 3px;
	}

	.md1812-portal .md1812-table--roster .md1812-roster__title-repeat {
		position: static;
		width: auto;
		height: auto;
		overflow: visible;
		clip: auto;
		clip-path: none;
	}

	.md1812-portal .md1812-table--roster .md1812-roster__note {
		text-transform: none;
		letter-spacing: 0;
		font-weight: 400;
		margin-top: 4px;
	}

	.md1812-portal .md1812-table--roster .md1812-roster__name {
		white-space: normal;
		font-size: 16px;
		font-weight: 600;
		color: var(--md-ink);
	}

	.md1812-portal .md1812-table--roster .md1812-roster__term {
		white-space: normal;
		font-size: 13px;
		margin-top: 1px;
	}

	/* A telephone number and an email address are things to be tapped, so they
	   are given a row of their own with room around them rather than being set
	   as tightly as the lines above. */
	.md1812-portal .md1812-table--roster .md1812-roster__contact {
		margin-top: 6px;
	}

	.md1812-portal .md1812-table--roster .md1812-roster__contact a {
		display: inline-block;
		padding: 3px 0;
	}
}

@media print {
	.md1812-masthead,
	.md1812-portal-footer,
	.md1812-no-print,
	.md1812-page-sub {
		display: none !important;
	}

	.md1812-shell {
		padding: 0;
		max-width: none;
	}

	.md1812-roster__section {
		break-inside: avoid;
		page-break-inside: avoid;
	}

	.md1812-portal .md1812-table--roster th,
	.md1812-portal .md1812-table--roster td {
		padding: 3px 6px;
		font-size: 11px;
	}

	.md1812-roster__contact a {
		text-decoration: none;
		color: #000;
	}
}


/* ---------- Keyboard focus (WCAG 2.4.7 / Section 508) ---------- */

/*
 * Themes routinely remove the focus ring, or replace it with something that
 * cannot be seen: the Go theme leaves a focused button with no outline at all,
 * and the portal's own ghost buttons signalled focus with a pale cream fill
 * that is invisible against white. A member navigating by keyboard could reach
 * the "Next" button and have nothing at all tell them so.
 *
 * Every focusable thing in the portal therefore states its own ring, with
 * enough specificity to hold, and :focus-visible so a mouse click does not
 * leave a ring behind. Do not remove these rules to tidy the stylesheet.
 */
.md1812-portal a:focus-visible,
.md1812-portal button:focus-visible,
.md1812-portal input:focus-visible,
.md1812-portal select:focus-visible,
.md1812-portal textarea:focus-visible,
.md1812-portal [tabindex]:focus-visible,
.md1812-portal .md1812-button:focus-visible,
.md1812-portal .md1812-button--ghost:focus-visible {
	outline: 3px solid var(--md-ink);
	outline-offset: 2px;
	outline-style: solid;
	/* Decorative halo only; the ring above carries the contrast. */
	box-shadow: 0 0 0 6px rgba(181, 137, 58, .3);
}

/* On the navy masthead the gold ring is hard to see; use white there. */
.md1812-masthead a:focus-visible,
.md1812-masthead button:focus-visible {
	outline: 3px solid #fff;
	outline-offset: 2px;
}

/* The ring must not be clipped by the frame the results sit in. */
.md1812-pagination {
	overflow: visible;
}

.md1812-pagination__all {
	margin-left: auto;
}

@media (prefers-reduced-motion: reduce) {
	.md1812-portal * {
		transition: none !important;
		animation: none !important;
	}
}


/* Skip link: off screen until it takes focus. */
.md1812-skip {
	position: absolute;
	left: -9999px;
	top: 0;
	z-index: 100;
	padding: 10px 16px;
	background: var(--md-ink);
	color: #fff;
	text-decoration: none;
	border-radius: 0 0 8px 0;
}

.md1812-skip:focus,
.md1812-skip:focus-visible {
	left: 0;
	outline: 3px solid #fff;
	outline-offset: -6px;
}

.md1812-portal main:focus {
	outline: none;
}

/* ---------- Dues ---------- */

/*
 * The amount is the one number on the page a member needs, so it is set in the
 * Society's serif at a size nothing else on the card competes with.
 */
.md1812-dues__amount {
	font-family: var(--md-serif);
	font-size: 26px;
	line-height: 1.15;
	letter-spacing: -.02em;
	color: var(--md-ink);
	margin: 0 0 2px;
}

.md1812-dues__state { margin: 6px 0 10px; }

/*
 * A class of its own, deliberately not a `.md1812-mark` modifier. `.md1812-mark`
 * is the 38x38 avatar tile in the member cards: fixed width and height, flex
 * centring and `overflow: hidden`. Adding a modifier to it inherited that box,
 * so the dues pill came out as a 38px circle with the word clipped inside it.
 * This restates every property of its own box and inherits nothing.
 */
.md1812-duetag {
	display: inline-block;
	width: auto;
	height: auto;
	max-width: none;
	overflow: visible;
	vertical-align: middle;
	font-family: inherit;
	font-size: 11.5px;
	line-height: 1.45;
	font-weight: 600;
	letter-spacing: .04em;
	text-transform: uppercase;
	white-space: nowrap;
	padding: 3px 9px;
	border-radius: 999px;
	border: 1px solid transparent;
	background: none;
}

.md1812-duetag--due {
	background: #fdf3f3;
	color: var(--md-error);
	border-color: #e7c3c4;
}

.md1812-duetag--paid {
	background: #f2faf5;
	color: var(--md-success);
	border-color: #bfdcc9;
}

/* Only a card that is actually asking for money wears the warning border. */
.md1812-portal .md1812-card--dues.is-owing { border-color: #e7c3c4; }

/*
 * Zeffy's embedded form cannot tell us how tall it is: listening on the dues
 * page for a message from its origin catches nothing, so there is no height to
 * react to and the frame has to be given one.
 *
 * Width. Zeffy lays its content out in a column of about 517px and centres it
 * whatever room it is given, so a frame stretched across the card would be that
 * same column with a field of white either side. 620px is the column plus its
 * own padding. The frame is then centred in the card - left-aligned it sat as a
 * narrow strip against 500px of empty paper, which is what made it look wrong.
 *
 * Height. Measured on the live page by loading the form in an oversized frame
 * and finding where its content ended: about 1345px at 620px wide and about
 * 1365px at phone width, the difference being how much the tier descriptions
 * wrap. 1440px clears both with a little to spare, so the whole tier list is
 * visible and the frame never grows its own scrollbar.
 *
 * That last point is the trade being made. A shorter frame would be immune to
 * the campaign changing, but it puts a scroll region inside a scrolling page,
 * and every member meets the tier list. A member only reaches the step after it
 * once they have chosen, and that step is not short either. So: fit the list.
 *
 * ** If tiers are added to the Zeffy campaign, this number has to be measured
 * again. ** There is no way to derive it from here.
 */
.md1812-zeffy {
	max-width: 620px;
	margin: 14px auto 10px;
	border: 1px solid var(--md-line);
	border-radius: var(--md-radius);
	overflow: hidden;
	background: #fff;
}

.md1812-zeffy__frame {
	display: block;
	width: 100%;
	height: 1440px;
	border: 0;
}

.md1812-dues__assurance { margin-top: 0; }

.md1812-dues__ledger { margin-top: 30px; }

.md1812-dues__heading {
	font-family: var(--md-serif);
	font-size: 20px;
	letter-spacing: -.02em;
	line-height: 1.15;
	color: var(--md-ink);
	margin: 0 0 6px;
	padding-bottom: 6px;
	border-bottom: 2px solid var(--md-gold);
}

/*
 * Two column counts, not one. The Treasurer sees a tick column the Internal
 * Audit chairman does not, so `nth-child` means a different column to each of
 * them - the earlier single set of widths was silently one column out of step
 * on the read-only view. `--dues-pick` is on the table only when the tick
 * column is rendered, and each set counts from its own first column.
 */
.md1812-portal .md1812-table--dues { table-layout: fixed; width: 100%; }

/*
 * Nine columns in 1080px, so the widths below are measured rather than guessed,
 * and the padding is tightened from the 16px the other tables use to 10px. That
 * alone gives back 108px across the row.
 *
 * The trap when setting these: a column's usable width is what is left after
 * BOTH paddings. The member number column had 65px, which is 33px of room for a
 * four-digit number needing 35px - so every row wrapped to two lines over two
 * pixels, and the table ran 1,200px longer than it needed to.
 *
 * Measured against the live record, the widest content in each column is:
 * member 126px, number 35, date paid 85, paid through 114 ("Nothing recorded",
 * not a date), covers 95 (the short wording), method 33, amount 47, recorded by
 * 194. Add 20px of padding to each before comparing with the widths here.
 */
.md1812-portal .md1812-table--dues th,
.md1812-portal .md1812-table--dues td { padding: 13px 10px; }

/* Read-only: Member, No., Date paid, Paid through, Covers, Method, Amount, By. */
.md1812-portal .md1812-table--dues tr > *:nth-child(1) { width: 19.5%; }
.md1812-portal .md1812-table--dues tr > *:nth-child(2) { width: 7%; white-space: nowrap; }
.md1812-portal .md1812-table--dues tr > *:nth-child(3) { width: 11%; }
.md1812-portal .md1812-table--dues tr > *:nth-child(4) { width: 13.5%; }
.md1812-portal .md1812-table--dues tr > *:nth-child(5) { width: 12.5%; }
.md1812-portal .md1812-table--dues tr > *:nth-child(6) { width: 7.5%; }
.md1812-portal .md1812-table--dues tr > *:nth-child(7) { width: 7.5%; white-space: nowrap; }
.md1812-portal .md1812-table--dues tr > *:nth-child(8) { width: auto; }

/* With the tick column in front, everything shifts one to the right. */
.md1812-portal .md1812-table--dues-pick tr > *:nth-child(1) { width: 40px; }
.md1812-portal .md1812-table--dues-pick tr > *:nth-child(2) { width: 18.5%; }
.md1812-portal .md1812-table--dues-pick tr > *:nth-child(3) { width: 6.5%; white-space: nowrap; }
.md1812-portal .md1812-table--dues-pick tr > *:nth-child(4) { width: 10.6%; }
.md1812-portal .md1812-table--dues-pick tr > *:nth-child(5) { width: 13%; }
.md1812-portal .md1812-table--dues-pick tr > *:nth-child(6) { width: 12%; }
.md1812-portal .md1812-table--dues-pick tr > *:nth-child(7) { width: 7%; }
.md1812-portal .md1812-table--dues-pick tr > *:nth-child(8) { width: 7.4%; white-space: nowrap; }
.md1812-portal .md1812-table--dues-pick tr > *:nth-child(9) { width: auto; }

/*
 * Below 900px the table becomes stacked records, and a column width means
 * nothing to a block - but `table-layout: fixed` and the percentages above
 * still applied, squeezing every value into a narrow strip against the right
 * edge: "15 Dec 2025" broke across three lines, one word each. The shared
 * reset in the stacking block cannot reach these because it is written earlier
 * in the file at the same specificity, so the undo lives here, next to what it
 * undoes.
 *
 * `:nth-child(n)` matches every cell and is written for its weight, not its
 * filtering: a bare `tr > *` scores a pseudo-class lower than the rules above
 * and loses to them. Do not "simplify" it away.
 */
@media (max-width: 900px) {
	.md1812-portal .md1812-table--dues,
	.md1812-portal .md1812-table--dues-pick {
		table-layout: auto;
	}

	.md1812-portal .md1812-table--dues tr > *:nth-child(n),
	.md1812-portal .md1812-table--dues-pick tr > *:nth-child(n) {
		width: auto;
	}
}

.md1812-dues__remit { margin-top: 16px; }

.md1812-dues__name {
	font-family: var(--md-serif);
	font-size: 15.5px;
	letter-spacing: -.02em;
	color: var(--md-ink);
}

.md1812-dues__by { font-size: 12.5px; color: var(--md-muted); }

.md1812-table--dues tr.is-owing .md1812-dues__name { color: var(--md-crimson); }

/* ---------- What a member has paid, year by year ---------- */

.md1812-dues__history {
	margin-top: 20px;
}

/* The last row of a portal table has no bottom rule, so without this the
   footnote runs straight into the final year. */
.md1812-dues__history .md1812-help {
	margin-top: 16px;
}

.md1812-dues__nohistory {
	margin: 16px 2px 0;
}

.md1812-portal .md1812-table--paidby tr > *:nth-child(1) { width: 22%; }
.md1812-portal .md1812-table--paidby tr > *:nth-child(2) { width: 16%; }
.md1812-portal .md1812-table--paidby tr > *:nth-child(3) { width: 30%; }
.md1812-portal .md1812-table--paidby tr > *:nth-child(4) { width: 12%; }
.md1812-portal .md1812-table--paidby tr > *:nth-child(5) { width: 20%; }

.md1812-portal .md1812-table--paidby .md1812-paid__year {
	text-align: left;
	font-weight: 700;
	font-size: 16px;
	color: var(--md-ink);
	font-variant-numeric: tabular-nums;
}

/*
 * The paid-through date, under the year it is grouped by.
 *
 * Not decoration and not redundant: the year is the calendar year of this
 * date, which tells the whole truth only while the dues year ends on 31
 * December. Zeffy already tells payers it is selling a rolling twelve months,
 * and if the Society ever adopts that, "2027" against a payment made in
 * September stops being self-explanatory while this line stays exact.
 */
.md1812-paid__through {
	display: block;
	font-weight: 400;
	font-size: 12px;
	color: var(--md-muted);
	white-space: nowrap;
	margin-top: 2px;
}

@media (max-width: 900px) {
	/* The widths above weigh (0,3,1); a reset that weighs less loses in
	   silence and leaves every cell in a 22% column. */
	.md1812-portal .md1812-table--paidby {
		table-layout: auto;
	}

	.md1812-portal .md1812-table--paidby tr > *:nth-child(n) {
		width: auto;
	}

	/* The year leads its own card rather than sitting in a label/value row:
	   it is what the card is about, not one of its facts. */
	.md1812-portal .md1812-table--paidby .md1812-paid__year {
		display: block;
		padding-bottom: 4px;
		border-bottom: 1px solid var(--md-line);
		margin-bottom: 4px;
	}

	.md1812-paid__through {
		display: inline;
		margin-left: 8px;
	}
}

/* The bar that turns a stack of checks into one pass. */
.md1812-dues__bar {
	margin-top: 16px;
	background: #f4f7fc;
	border: 1px solid #cfd8e6;
	border-radius: var(--md-radius);
	padding: 14px 16px;
	display: flex;
	gap: 14px;
	align-items: flex-end;
	flex-wrap: wrap;
}

.md1812-dues__count {
	margin: 0 auto 10px 0;
	font-size: 13.5px;
	font-weight: 600;
	color: var(--md-ink);
}

/* Nothing ticked is the resting state, not a warning - so it recedes. */
.md1812-dues__count.is-empty {
	font-weight: 400;
	color: var(--md-muted);
}

.md1812-dues__bar .md1812-field { margin-bottom: 0; }

/*
 * Taking the whole roll on a telephone.
 *
 * The control that does this on a wide screen is a cell in the table header,
 * and below 900px the header is clipped away - the rows become cards carrying
 * their column names in `data-label`, so there is no header left to put a
 * control in. This bar exists only for that width; above it the header box is
 * the one to use and this one would be a second thing saying the same.
 */
.md1812-portal .md1812-dues__picktools {
	display: none;
}

@media (max-width: 900px) {
	.md1812-portal .md1812-dues__picktools {
		display: flex;
		flex-wrap: wrap;
		align-items: center;
		gap: 4px 14px;
		margin: 0 0 14px;
		padding: 12px 14px;
		background: #f4f7fc;
		border: 1px solid #cfd8e6;
		border-radius: var(--md-radius);
	}

	/*
	 * The whole line is the tap target, not the twenty-pixel box: 44px is the
	 * smallest thing a finger hits reliably, and this one ticks fifty-seven
	 * people at once, so it is worth being certain the tap was meant.
	 */
	.md1812-portal .md1812-dues__pickall {
		flex: 1 1 100%;
		min-height: 44px;
		font-size: 15px;
		font-weight: 600;
		color: var(--md-ink);
	}

	.md1812-portal .md1812-dues__picktools .md1812-dues__count {
		flex: 1 1 100%;
		margin: 0;
		font-size: 13px;
	}

	/* Nothing ticked is the resting state and the bar already says what the
	   box will do, so the count only speaks once it has something to report. */
	.md1812-portal .md1812-dues__picktools .md1812-dues__count.is-empty {
		display: none;
	}
}

@media (max-width: 700px) {
	.md1812-dues__bar { align-items: stretch; }
	.md1812-dues__bar .md1812-button { width: 100%; }
}

/* ---------- Reading a printed yearbook ---------- */

.md1812-yearbook__year {
	max-width: 12rem;
}

.md1812-yearbook__paste {
	margin: 4px 0 18px;
	border-top: 1px dotted var(--md-line);
	padding-top: 12px;
}

.md1812-yearbook__paste summary {
	cursor: pointer;
	color: var(--md-ink-soft);
	font-size: 14px;
	/* A summary is a 44px-tall thing to tap, not a line of text. */
	padding: 10px 0;
}

.md1812-yearbook__h3 {
	font-family: var(--md-serif);
	font-size: 17px;
	color: var(--md-ink);
	margin: 24px 0 4px;
}

.md1812-yearbook__names {
	margin: 8px 0 0;
	padding-left: 20px;
	font-size: 14px;
	line-height: 1.6;
	color: var(--md-text);
}

.md1812-yearbook__last,
.md1812-yearbook__bundled {
	margin-top: 20px;
}

/*
 * A summary table stays a table at every width.
 *
 * Two columns of label and number read perfectly well on a telephone and are
 * made worse by the card treatment the portal gives wider tables - each row
 * would become a card and, having no `data-label`, would print its label once
 * and then nothing. The reset is written at the same weight as the rule it
 * cancels; a bare class loses. See the theme-conflicts note for why that
 * sentence keeps being necessary.
 *
 * Shared, and named for its shape rather than its screen: the yearbook import
 * and the search index both count things in exactly this form, and a second
 * copy of these rules would be a second place to get the reset wrong.
 */
.md1812-portal .md1812-table--sum tr > *:nth-child(1) { width: 66%; }
.md1812-portal .md1812-table--sum tr > *:nth-child(2) { width: 34%; }

.md1812-portal .md1812-table--sum th {
	font-weight: 400;
	color: var(--md-text);
	text-align: left;
}

.md1812-portal .md1812-table--sum td {
	font-weight: 600;
	color: var(--md-ink);
	font-variant-numeric: tabular-nums;
}

.md1812-portal .md1812-table--sum .md1812-help {
	display: block;
	font-weight: 400;
	margin-top: 2px;
}

.md1812-portal .md1812-table--ybconf tr > *:nth-child(1) { width: 30%; }
.md1812-portal .md1812-table--ybconf tr > *:nth-child(2) { width: 14%; }
.md1812-portal .md1812-table--ybconf tr > *:nth-child(3) { width: 28%; }
.md1812-portal .md1812-table--ybconf tr > *:nth-child(4) { width: 28%; }

.md1812-portal .md1812-table--ybconf td {
	font-size: 13px;
	overflow-wrap: anywhere;
}

/*
 * What the yearbook would add to each member.
 *
 * These widths are declared BEFORE the stacked block below, not after it. A
 * media query does not change a rule's weight - only where it sits in the file
 * decides between two rules that weigh the same - so the same widths written
 * afterwards override the reset and the stacked cards come out in a column
 * thirty percent wide. Which is exactly what happened.
 */
.md1812-portal .md1812-table--ybchange tr > *:nth-child(1) { width: 5%; }
.md1812-portal .md1812-table--ybchange tr > *:nth-child(2) { width: 30%; }
.md1812-portal .md1812-table--ybchange tr > *:nth-child(3) { width: auto; }

.md1812-portal .md1812-table--ybchange .md1812-import__take {
	text-align: center;
}

.md1812-ybchange__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 4px;
	font-size: 13px;
}

/*
 * The field's name, then what would go in it. The ancestors are spelled out
 * rather than counted: "3 ancestors" is nothing the Registrar can check, and
 * "Capt. Jacob Alexander (1782-1830)" he can read straight off the page.
 */
.md1812-ybchange__label {
	display: inline-block;
	min-width: 6.5rem;
	vertical-align: top;
	color: var(--md-muted);
}

.md1812-ybchange__detail {
	color: var(--md-ink);
	overflow-wrap: anywhere;
}

@media (max-width: 900px) {
	.md1812-portal .md1812-table--sum {
		display: table;
		width: 100%;
		background: transparent;
		border: 0;
		box-shadow: none;
		margin-bottom: 0;
	}

	.md1812-portal .md1812-table--sum tbody {
		display: table-row-group;
	}

	.md1812-portal .md1812-table--sum tr {
		display: table-row;
		background: transparent;
		border: 0;
		border-radius: 0;
		box-shadow: none;
		margin: 0;
		padding: 0;
	}

	.md1812-portal .md1812-table--sum tr > *:nth-child(n) {
		display: table-cell;
		text-align: left;
		padding: 9px 4px;
	}

	.md1812-portal .md1812-table--sum tr > *:nth-child(n)::before {
		content: none;
	}

	/* The conflicts table does carry data-labels, so it takes the card
	   treatment as intended - it only needs its column widths cancelled. */
	.md1812-portal .md1812-table--ybconf,
	.md1812-portal .md1812-table--ybchange {
		table-layout: auto;
	}

	.md1812-portal .md1812-table--ybconf tr > *:nth-child(n),
	.md1812-portal .md1812-table--ybchange tr > *:nth-child(n) {
		width: auto;
	}

	.md1812-portal .md1812-table--ybchange .md1812-import__take {
		text-align: left;
		justify-content: flex-start;
		gap: 10px;
		border-bottom: 1px solid var(--md-line);
	}

	/*
	 * The member and the list of changes are not label-and-value pairs, so
	 * they opt out of the treatment that makes them one: a name pushed to the
	 * right of the word "Member" wraps into a three-line column, and each line
	 * of the change list already carries its own label.
	 */
	.md1812-portal .md1812-table--ybchange tr > *:nth-child(2),
	.md1812-portal .md1812-table--ybchange tr > *:nth-child(3) {
		display: block;
		text-align: left;
	}

	.md1812-portal .md1812-table--ybchange tr > *:nth-child(2)::before,
	.md1812-portal .md1812-table--ybchange tr > *:nth-child(3)::before {
		content: none;
	}

	.md1812-portal .md1812-table--ybchange tr > *:nth-child(2) {
		font-size: 16px;
		padding-bottom: 2px;
		border-bottom: 0;
	}

	.md1812-ybchange__label {
		display: block;
		min-width: 0;
		margin-bottom: 1px;
		font-size: 11px;
		letter-spacing: .07em;
		text-transform: uppercase;
	}

	.md1812-ybchange__list {
		gap: 8px;
	}
}


/* Import, throw away: two forms, one row, and full width on a telephone. */
.md1812-yearbook .md1812-record-edit__bar form {
	margin: 0;
}

@media (max-width: 700px) {
	.md1812-yearbook .md1812-record-edit__bar form {
		flex: 1 1 100%;
	}

	.md1812-yearbook .md1812-record-edit__bar .md1812-button {
		width: 100%;
	}
}

/* ---------- Importing the Zeffy export ---------- */

/*
 * This screen lives in the portal rather than in wp-admin because the Treasurer
 * is a Society Officer, not an administrator. He records check payments, reads
 * the ledger and works out the General Society remittance at /portal/dues/;
 * sending him into WordPress for the one remaining step was a seam.
 */
.md1812-dues__importlink {
	display: flex;
	align-items: center;
	gap: 12px;
	flex-wrap: wrap;
	margin: 0 0 16px;
}

.md1812-dues__importlink .md1812-help { margin: 0; }

.md1812-import__back { margin: -6px 0 18px; font-size: 14px; }

.md1812-import__rules {
	margin: 14px 0 0;
	padding: 14px 16px;
	background: #f4f7fc;
	border: 1px solid #cfd8e6;
	border-radius: var(--md-radius);
}

.md1812-import__rules fieldset { border: 0; margin: 0 0 10px; padding: 0; }
.md1812-import__rules legend { padding: 0; }
.md1812-import__rule { margin: 6px 0; font-size: 14px; }
.md1812-import__rule label { display: flex; gap: 8px; align-items: flex-start; }

.md1812-import__tally {
	margin: 14px 0 0;
	font-size: 13.5px;
	font-weight: 600;
	color: var(--md-ink);
}

.md1812-import__email,
.md1812-import__how {
	display: block;
	font-family: var(--md-sans, inherit);
	font-size: 12px;
	font-weight: 400;
	letter-spacing: 0;
	color: var(--md-muted);
}

/*
 * The verdict is the only thing on this screen the Treasurer must not misread,
 * so it is a labelled mark rather than a colour: "Will be recorded" is the one
 * that writes, and everything else says why it does not.
 */
.md1812-verdict {
	display: inline-block;
	width: auto;
	height: auto;
	overflow: visible;
	font-size: 11.5px;
	line-height: 1.45;
	font-weight: 600;
	letter-spacing: .03em;
	padding: 2px 8px;
	border-radius: 999px;
	border: 1px solid var(--md-line);
	background: #f4f4f2;
	color: var(--md-muted);
}

.md1812-verdict--record {
	background: #f2faf5;
	border-color: #bfdcc9;
	color: var(--md-success);
}

.md1812-verdict--nomember,
.md1812-verdict--ambiguous,
.md1812-verdict--unknown,
.md1812-verdict--baddate {
	background: #fdf7ef;
	border-color: #e6d2b0;
	color: #8a6c2f;
}

.md1812-verdict--life {
	background: #f4f7fc;
	border-color: #cfd8e6;
	color: var(--md-ink);
}

.md1812-table--import tr.is-writing .md1812-dues__name { color: var(--md-ink); }

.md1812-portal .md1812-table--import th,
.md1812-portal .md1812-table--import td { padding: 11px 10px; vertical-align: top; }

.md1812-portal .md1812-table--import { table-layout: fixed; width: 100%; }
/*
 * Nine columns now, not eight: a Take box was added at the front and every
 * width below moved along one. Renumbering is not optional - the last column
 * is the only one set to `auto`, so a set that still totals 100% across the
 * first eight leaves the ninth with nothing and its contents render off the
 * page. That has happened twice in this stylesheet already.
 *
 * The Through column is wider than it reads, because it now holds a date
 * input rather than a date.
 */
.md1812-portal .md1812-table--import tr > *:nth-child(1) { width: 4%; }
.md1812-portal .md1812-table--import tr > *:nth-child(2) { width: 9%; }
.md1812-portal .md1812-table--import tr > *:nth-child(3) { width: 17%; }
.md1812-portal .md1812-table--import tr > *:nth-child(4) { width: 16%; }
.md1812-portal .md1812-table--import tr > *:nth-child(5) { width: 7%; white-space: nowrap; }
.md1812-portal .md1812-table--import tr > *:nth-child(6) { width: 6%; white-space: nowrap; }
.md1812-portal .md1812-table--import tr > *:nth-child(7) { width: 14%; }
.md1812-portal .md1812-table--import tr > *:nth-child(8) { width: 13%; }
.md1812-portal .md1812-table--import tr > *:nth-child(9) { width: auto; }

/* A date the Treasurer can correct. Kept narrow enough that eight other
   columns still fit beside it, and never wider than its cell. */
.md1812-portal .md1812-import__through {
	padding: 6px 8px;
	font-size: 13px;
	width: 100%;
	max-width: 100%;
	min-width: 0;
}

.md1812-portal .md1812-table--import .md1812-import__take {
	text-align: center;
}

@media (max-width: 900px) {
	/* Stacked, the tick leads the card rather than sitting in a
	   label-and-value row: it is the decision the card is there for. */
	.md1812-portal .md1812-table--import .md1812-import__take {
		text-align: left;
		justify-content: flex-start;
		gap: 10px;
		border-bottom: 1px solid var(--md-line);
	}

	.md1812-portal .md1812-import__through {
		max-width: 12rem;
	}
}

@media (max-width: 900px) {
	.md1812-portal .md1812-table--import { table-layout: auto; }
	.md1812-portal .md1812-table--import tr > *:nth-child(n) { width: auto; }
}

.md1812-import__bar { align-items: center; }
.md1812-import__bar form { margin: 0; }
.md1812-import__note { margin-top: 14px; max-width: 46em; }

/* ---------- The registrar's record editor ---------- */

/*
 * At /portal/members/<id>/edit rather than in wp-admin, so that the registrar
 * need not be a WordPress administrator. See Members::can_edit_record() for the
 * guards that replaces.
 */
.md1812-record-edit__grid {
	display: grid;
	grid-template-columns: 1fr;
	gap: 20px;
	align-items: start;
}

@media (min-width: 860px) {
	.md1812-record-edit__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }

	/*
	 * A card that is one wide box rather than a column of fields spans both.
	 * Three cards in a two-column grid leave the second half of the second row
	 * empty, which with `align-items: start` reads as a mistake - and it was
	 * one. Anything added here should be asked the same question: is this a
	 * column of short fields, or one wide thing?
	 */
	.md1812-record-edit__grid > .md1812-record-edit__wide { grid-column: 1 / -1; }
}

.md1812-record-edit__bar { margin-top: 20px; }
.md1812-record-edit__stamp { margin-top: 14px; }

/* ---------- Ancestors on the member record ---------- */

.md1812-ancestry {
	margin-top: 20px;
}

.md1812-ancestry__rows {
	display: flex;
	flex-direction: column;
}

/*
 * Rank, ancestor, born, died, and a way to take the row away. The ancestor's
 * name gets everything left over: a rank is four characters and a year is
 * always four, so only the name has anything to gain from the space.
 */
.md1812-ancestry__row {
	display: grid;
	grid-template-columns: 1fr;
	gap: 0 12px;
	padding: 10px 0;
	border-bottom: 1px dotted var(--md-line);
}

.md1812-ancestry__row:last-child {
	border-bottom: 0;
}

.md1812-ancestry__row .md1812-field {
	margin-bottom: 10px;
}

.md1812-ancestry__act {
	display: flex;
	align-items: flex-end;
	padding-bottom: 10px;
}

.md1812-ancestry__add {
	margin: 12px 0 0;
}

@media (min-width: 720px) {
	.md1812-ancestry__row {
		grid-template-columns: 7rem minmax(0, 1fr) 5rem 5rem auto;
		align-items: end;
	}

	.md1812-ancestry__row .md1812-field {
		margin-bottom: 0;
	}

	.md1812-ancestry__act {
		padding-bottom: 0;
	}

	/*
	 * Four labels repeated down fourteen rows is noise, so past the first row
	 * they are taken out of sight - and only out of sight. They stay in the
	 * page for anyone listening, who has no column headings to go by and would
	 * otherwise meet four unlabelled boxes; `display: none` would have taken
	 * them from both. Below 720px the row stacks and every label is shown,
	 * because then there is no first row to read them from.
	 */
	.md1812-ancestry__row:not(:first-child) .md1812-label {
		position: absolute;
		width: 1px;
		height: 1px;
		overflow: hidden;
		clip: rect(0, 0, 0, 0);
		clip-path: inset(50%);
		white-space: nowrap;
	}
}

/* The directory's edit link, shown only to whoever may use it. */
.md1812-member__edit { margin-top: 14px; }
.md1812-portal .md1812-table--members .md1812-td-edit { text-align: right; white-space: nowrap; }

/* ---------- Filing a document from the portal ---------- */

.md1812-docedit__grid {
	display: grid;
	grid-template-columns: 1fr;
	gap: 20px;
	align-items: start;
}

@media (min-width: 860px) {
	.md1812-docedit__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.md1812-docedit__bar { margin-top: 20px; }
.md1812-docedit__current { margin: 0 0 10px; }
.md1812-docedit__current .md1812-help { display: block; margin: 2px 0 0; }

.md1812-docedit__delete {
	display: flex;
	align-items: center;
	gap: 12px;
	flex-wrap: wrap;
	margin-top: 28px;
	padding-top: 18px;
	border-top: 1px solid var(--md-line);
}

.md1812-docedit__delete .md1812-help { margin: 0; }

/* Destructive, so it says so before it is pressed rather than after. */
.md1812-portal .md1812-button--danger {
	border-color: #e7c3c4;
	color: var(--md-error);
}

.md1812-portal .md1812-button--danger:hover,
.md1812-portal .md1812-button--danger:focus-visible {
	background: #fdf3f3;
	border-color: var(--md-error);
	color: var(--md-error);
}

/* The archive's own "add" button, shown only to officers. */
/* Two buttons since 1.33.3 (Add a document, Search index), so it is a row. */
.md1812-archive__add { margin: 0 0 18px; }

/* Adding one member: a narrow form, because it asks for very little. */
.md1812-member-new { max-width: 34em; }
.md1812-member-new__note { margin: 18px 0; }

/* ---------- The search index ---------- */

/*
 * At /portal/documents/index/ rather than in wp-admin. The screen was the last
 * thing an officer had to leave the portal for; see Text::enqueue_portal().
 */
.md1812-index__bar {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 14px;
	margin: 0 0 6px;
}

/*
 * The running commentary the indexer writes while it works. It must be able to
 * sit on its own line on a telephone rather than squeezing the button, which is
 * what `flex-wrap` above and a basis of nothing here between them arrange.
 */
.md1812-index__status {
	flex: 1 1 12em;
	min-width: 0;
	font-size: 14px;
	color: var(--md-text);
}

.md1812-index__note {
	max-width: 46em;
}

/*
 * The badge the indexer draws into each result cell when a document has been
 * read. The same three tones as the admin stylesheet, restated here because
 * the portal does not load that file and a class that is never defined draws
 * as plain text - which is exactly what "could not be read" must not look like.
 */
.md1812-portal .md1812-badge {
	display: inline-block;
	padding: 3px 10px;
	border-radius: 4px;
	font-size: 13px;
	line-height: 1.6;
}

.md1812-portal .md1812-badge--pass {
	background: #edfaef;
	color: #1a6b38;
	border: 1px solid #b6ddc2;
}

.md1812-portal .md1812-badge--warn {
	background: #fdf8e8;
	color: #7a5c00;
	border: 1px solid #e6d9a8;
}

.md1812-portal .md1812-badge--fail {
	background: #fdf1f1;
	color: #9b2226;
	border: 1px solid #e6bfc0;
}

/* Two columns: the title takes the room, the result is a badge. */
.md1812-portal .md1812-table--index tr > *:nth-child(1) { width: 68%; }
.md1812-portal .md1812-table--index tr > *:nth-child(2) { width: 32%; }

@media (max-width: 900px) {
	/* Both cells carry a data-label, so the card treatment is wanted here and
	   only the column widths and the fixed layout need cancelling - at matching
	   weight, and after the widths above, or neither reset fires. */
	.md1812-portal .md1812-table--index { table-layout: auto; }
	.md1812-portal .md1812-table--index tr > *:nth-child(n) { width: auto; }
}

/* ---------- The member card, and the dialog it opens in ---------- */

/*
 * A member's name is a link now. It was a span carrying the archive's title
 * class, which underlines on hover — so it advertised itself as clickable and
 * was not. Both places the name appears use this.
 */
.md1812-portal .md1812-member__link {
	color: inherit;
	text-decoration: none;
	background-image: none;
}

.md1812-portal .md1812-member__link:hover,
.md1812-portal .md1812-member__link:focus-visible {
	text-decoration: underline;
}

/* What the member wrote about themselves. */
.md1812-member__bio {
	margin: 14px 0 0;
	padding-top: 14px;
	border-top: 1px dotted var(--md-line);
}

.md1812-member__biohead {
	font-family: var(--md-font);
	font-size: 11px;
	letter-spacing: .09em;
	text-transform: uppercase;
	color: var(--md-muted);
	font-weight: 600;
	margin: 0 0 6px;
}

.md1812-member__bio p {
	margin: 0;
	font-size: 14.5px;
	line-height: 1.6;
	color: var(--md-text);
}

/*
 * On a card in the list, two lines and no more: twenty-four cards each running
 * to five sentences is a page nobody scrolls. The dialog and the member's own
 * page show the whole thing.
 */
.md1812-portal .md1812-results[data-md1812-view="cards"] .md1812-member__bio p {
	display: -webkit-box;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.md1812-portal .md1812-modal .md1812-member__bio p,
.md1812-memberpage .md1812-member__bio p {
	display: block;
	overflow: visible;
}

.md1812-memberpage {
	max-width: 44em;
}

/* ---------- The dialog ---------- */

/*
 * The dialog carries no padding of its own, so that a click anywhere outside
 * the panel lands on the dialog element and closes it. The panel is the child.
 */
.md1812-portal .md1812-modal,
dialog.md1812-modal {
	padding: 0;
	border: 0;
	background: transparent;
	max-width: min(34em, calc(100vw - 32px));
	width: 100%;
	max-height: calc(100vh - 32px);
	overflow: visible;
	color: var(--md-text);
}

dialog.md1812-modal::backdrop {
	background: rgba(18, 35, 63, .55);
}

.md1812-modal__inner {
	position: relative;
	background: var(--md-surface);
	border: 1px solid var(--md-line);
	border-radius: var(--md-radius);
	box-shadow: 0 18px 50px rgba(18, 35, 63, .28);
	padding: 22px;
	max-height: calc(100vh - 32px);
	overflow-y: auto;
	-webkit-overflow-scrolling: touch;
}

.md1812-modal__close {
	position: absolute;
	top: 10px;
	right: 10px;
	width: 34px;
	height: 34px;
	border: 1px solid transparent;
	border-radius: 50%;
	background: transparent;
	color: var(--md-muted);
	font-size: 22px;
	line-height: 1;
	cursor: pointer;
}

.md1812-portal .md1812-modal__close:hover,
.md1812-portal .md1812-modal__close:focus-visible {
	background: var(--md-paper);
	color: var(--md-ink);
	border-color: var(--md-line);
}

/* The card inside a dialog is the whole dialog: no second frame around it. */
.md1812-portal .md1812-modal .md1812-member {
	background: transparent;
	border: 0;
	box-shadow: none;
	margin: 0;
	padding: 0;
}

.md1812-modal__foot {
	margin: 16px 0 0;
	padding-top: 14px;
	border-top: 1px dotted var(--md-line);
	font-size: 14px;
}

/*
 * Full height on a telephone. A small floating panel on a small screen is the
 * worst of both — too little room to read and too little page to return to.
 */
@media (max-width: 620px) {
	.md1812-portal .md1812-modal,
	dialog.md1812-modal {
		max-width: 100vw;
		width: 100vw;
		max-height: 100vh;
		height: 100vh;
		margin: 0;
	}

	.md1812-modal__inner {
		max-height: 100vh;
		height: 100vh;
		border: 0;
		border-radius: 0;
		padding: 20px 16px calc(20px + env(safe-area-inset-bottom, 0px));
	}
}

/* ---------- A textarea, and how much room is left in it ---------- */

.md1812-portal .md1812-textarea {
	min-height: 7em;
	line-height: 1.55;
	resize: vertical;
	font-family: inherit;
}

.md1812-counter {
	margin-top: 4px;
	font-variant-numeric: tabular-nums;
}

.md1812-counter.is-low {
	color: var(--md-crimson);
}

/* ---------- Tags on the filing screen ---------- */

/*
 * wp-admin suggests tags as you type and lists the most used ones. The portal's
 * field was a bare comma-separated box, so moving officers out of wp-admin took
 * that away — and a tag nobody can see is a tag nobody reuses, which is how one
 * subject ends up filed under three spellings.
 */
.md1812-tagbank {
	margin: 14px 0 0;
	padding-top: 14px;
	border-top: 1px dotted var(--md-line);
}

.md1812-tagbank__head {
	margin: 0 0 2px;
	font-family: var(--md-font);
	font-size: 11px;
	letter-spacing: .09em;
	text-transform: uppercase;
	color: var(--md-muted);
	font-weight: 600;
}

.md1812-tagbank__row {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin: 10px 0 10px;
}

/*
 * A chip is a button, and the theme styles bare buttons with 22px of padding —
 * which is how a 28px round control once became a 72×45 oval. State the whole
 * box.
 */
.md1812-portal .md1812-tagchip {
	display: inline-flex;
	align-items: baseline;
	gap: 6px;
	margin: 0;
	padding: 6px 12px;
	width: auto;
	min-width: 0;
	height: auto;
	font-family: inherit;
	font-size: 13.5px;
	line-height: 1.35;
	font-weight: 400;
	text-transform: none;
	letter-spacing: 0;
	color: var(--md-text);
	background: var(--md-paper);
	background-image: none;
	border: 1px solid var(--md-line);
	border-radius: 999px;
	box-shadow: none;
	cursor: pointer;
}

.md1812-portal .md1812-tagchip:hover {
	border-color: var(--md-ink);
	color: var(--md-ink);
}

/* Chosen: filled, so a glance says which are on without reading the field. */
.md1812-portal .md1812-tagchip.is-on,
.md1812-portal .md1812-tagchip[aria-pressed="true"] {
	background: var(--md-ink);
	background-color: var(--md-ink);
	border-color: var(--md-ink);
	color: #fff;
}

.md1812-portal .md1812-tagchip:focus-visible {
	outline: 2px solid var(--md-gold);
	outline-offset: 2px;
}

.md1812-tagchip__count {
	font-size: 11.5px;
	opacity: .7;
	font-variant-numeric: tabular-nums;
}

/* A button that reads as a link: same box discipline as the chip. */
.md1812-portal .md1812-linkbutton {
	display: inline;
	margin: 0;
	padding: 0;
	width: auto;
	height: auto;
	font-family: inherit;
	font-size: 13px;
	font-weight: 400;
	text-transform: none;
	letter-spacing: 0;
	color: var(--md-crimson);
	background: transparent;
	background-image: none;
	border: 0;
	box-shadow: none;
	text-decoration: underline;
	cursor: pointer;
}

.md1812-portal .md1812-linkbutton:focus-visible {
	outline: 2px solid var(--md-gold);
	outline-offset: 2px;
}

/* What is being typed, matched against the tags already in use. */
.md1812-tagsuggest {
	margin: 8px 0 0;
	padding: 10px 12px;
	background: var(--md-paper);
	border: 1px solid var(--md-line);
	border-radius: var(--md-radius);
}

.md1812-tagsuggest__head {
	margin: 0 0 6px;
	font-size: 11px;
	letter-spacing: .09em;
	text-transform: uppercase;
	color: var(--md-muted);
	font-weight: 600;
}

.md1812-portal .md1812-tagsuggest__item {
	display: block;
	width: 100%;
	margin: 0;
	padding: 7px 8px;
	height: auto;
	font-family: inherit;
	font-size: 14px;
	font-weight: 400;
	text-transform: none;
	letter-spacing: 0;
	text-align: left;
	color: var(--md-ink);
	background: transparent;
	background-image: none;
	border: 0;
	border-radius: 6px;
	box-shadow: none;
	cursor: pointer;
}

.md1812-portal .md1812-tagsuggest__item:hover {
	background: var(--md-surface);
}

.md1812-portal .md1812-tagsuggest__item:focus-visible {
	outline: 2px solid var(--md-gold);
	outline-offset: -2px;
}
