/* One stylesheet, both sites. Nothing site-specific belongs here: it is served
   to the 1969 and 1970 sites alike, from marian-shared/ by way of a symlink in
   each doc root.

   The palette is the 2004 palette, deliberately. The typography is not: these
   two classes are 74 to 77 years old and the browser default was 16px Times
   across a 200-character line. */

:root {
	--page-bg:      #99c5ec;
	--box-bg:       #98e1ee;
	--box-border:   #88c1ce;
	--ink:          #10222c;
	--ink-quiet:    #26404c;   /* secondary text: a colour step, never a size step */
	--link:         #114a80;
	--link-visited: #5a3a80;

	--measure:   38em;   /* readable line length for running text */
	--box-max:   46em;   /* an item or form, including its padding */
	--nav-width: 19rem;
	--gap:       1rem;
}

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

/* ---------------------------------------------------------------- page grid */

/* #header, the toggle, #sidebar and #content are all direct children of body,
   so body is the grid. The nav row sits between the header and the content, so
   opening the menu pushes the page down rather than covering it -- the sidebar
   is long (1969's runs to about thirty links) and it is meant to be scrolled. */
body {
	/* Only so the skip link has something to anchor to. Without it body is
	   static, the link's top/left resolve against the initial containing
	   block, and on a wide monitor the one visible accessibility affordance
	   on the page lands hundreds of pixels to the left of the page itself. */
	position: relative;

	display: grid;
	grid-template-columns: minmax(0, 1fr);
	grid-template-areas:
		"header"
		"navbutton"
		"nav"
		"content";

	max-width: 78rem;
	margin: 0 auto;
	padding: 0 var(--gap);

	background-color: var(--page-bg);
	color: var(--ink);
	font-family: system-ui, -apple-system, "Segoe UI", Roboto,
	             "Helvetica Neue", Arial, sans-serif;
	font-size: 1.125rem;
	line-height: 1.6;
	-webkit-text-size-adjust: 100%;

	/* Inherited by everything, and it has to be, because the long unbreakable
	   token in this data is not a filename or a URL -- it is a subject line.
	   1969's news set contains a post titled
	   "Hoban/Maher/Walker/Leto/Leonard/O'Neil/K King": no spaces, and a slash
	   is not a break opportunity, so it laid out 541px wide inside a 294px
	   heading and gave a 360px phone a horizontal scrollbar. minmax(0, 1fr)
	   stops the grid TRACK growing; this is what stops the text spilling out
	   of it. break-word rather than anywhere, so a word that fits is still
	   never broken and the intrinsic sizing of everything else is unchanged. */
	overflow-wrap: break-word;
}

#header     { grid-area: header; }
.nav-button { grid-area: navbutton; }
#sidebar    { grid-area: nav; }
#content    { grid-area: content; min-width: 0; padding-bottom: 2rem; }

@media (min-width: 60em) {
	body {
		grid-template-columns: var(--nav-width) minmax(0, 1fr);
		grid-template-areas:
			"header header"
			"nav    content";
		column-gap: calc(var(--gap) * 2);
	}
}

/* minmax(0, 1fr) rather than 1fr above: a 1fr track takes its minimum from its
   contents, so one wide gallery row or one long filename would push the column
   past the viewport and give the whole page a horizontal scrollbar. */

/* ------------------------------------------------------------------ elements */

img { max-width: 100%; height: auto; }

/* The old per-site stylesheets carried this under a comment reading "for admin
   pages", and it left with them. admin.php and admin_set.php group their links
   in <fieldset><legend>, and with no reset every one of those groups came back
   wearing the browser's default 2px groove -- a beveled 1995 box nobody chose,
   on the pages the sole admin uses. #sidebar fieldset below zeroes the margin
   and padding too, which is right there and wrong here: the admin lists want
   the UA's padding so the legend has something to sit on.

   min-width: 0 is the other half, and it is not cosmetic. A fieldset's
   automatic minimum size is min-content, not zero, and `overflow-wrap:
   break-word` does not reduce min-content -- so a fieldset refuses to shrink
   below its longest line and pushes the page sideways. #sidebar fieldset
   below has carried this for the same reason since the sidebar became a grid
   track. It was missing on #content's, and admin_set.php for 1969's news set
   overflowed a 320px viewport by 148px: the "Edit/Delete Contents:" list
   holds post subjects, and "February 2009 Class News" wanted 379px. Measured
   before this line and after: 148px of horizontal scroll, then none. That bug
   predates the border reset above -- removing the 2px border took it from
   148px to 144px -- but this is the rule that should have owned it. */
fieldset { border: 0; min-width: 0; }

a         { color: var(--link); }
a:visited { color: var(--link-visited); }

/* Three rules, not one, and the order matters.
   :focus-visible only reached Safari in 15.4. An unknown pseudo-class
   invalidates the whole selector it appears in, so a :focus-visible-only rule
   is thrown away entirely on the iOS 14 iPads this audience still uses, and
   they get no focus indicator from us at all. So: state the ring with plain
   :focus, which every browser knows, then take it back for pointer focus with
   :focus:not(:focus-visible). That middle rule is itself invalid on those old
   browsers -- :not() is not forgiving -- so they keep the plain :focus ring,
   which is exactly the outcome we want there. Modern browsers apply all
   three and behave as :focus-visible alone would have. */
:focus {
	outline: 3px solid var(--link);
	outline-offset: 2px;
}
:focus:not(:focus-visible) { outline: none; }
:focus-visible {
	outline: 3px solid var(--link);
	outline-offset: 2px;
}

/* #content is only focusable because it carries tabindex="-1" so the skip link
   has somewhere to land -- see header.php. It is not a control, and the ring
   above drew a 3px box around the entire article: measured 736x2238 at a 768px
   viewport when the skip link is used from the keyboard, which is the one way
   it is ever used. Worse on an iOS 14 iPad, where the two :focus-visible rules
   above are thrown away as unparseable and only the plain :focus ring is left,
   so there is nothing to take it back. An id plus a pseudo-class outranks all
   three regardless of order. Focus still moves -- that is the whole point of
   the tabindex -- it just stops being drawn around the page. */
#content:focus { outline: none; }

.visually-hidden {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* Absolutely positioned, so the hidden checkbox occupies no grid cell -- but
   still rendered and still focusable, so Space toggles the menu. */

/* The first focusable thing in the document, and the way past the thirty
   navigation links that now precede the content. Hidden the same way as the
   checkbox above, and for the same reason -- out of flow, so it claims no grid
   cell -- but it reveals itself the moment it takes focus.

   The reveal below is keyed on plain :focus and nothing else. It used to read
   ".skip-link:focus, .skip-link:focus-visible", which looks like the safe
   belt-and-braces version and is in fact the broken one: a selector list is
   not forgiving, so one unparseable selector invalidates the whole group and
   an iOS 14 Safari threw the entire rule away -- leaving a keyboard user with
   focus on a 1px clipped link they cannot see. :focus is a superset of
   :focus-visible anyway, and this link is 1px and unclickable, so pointer
   focus is not a case that exists. One selector, every browser. */
.skip-link {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

.skip-link:focus {
	top: .5rem;
	left: .5rem;
	z-index: 10;
	width: auto;
	height: auto;
	margin: 0;
	padding: .7em 1em;
	overflow: visible;
	clip-path: none;
	background: var(--box-bg);
	border: 2px solid var(--box-border);
	border-radius: 8px;
	font-weight: 600;
	text-decoration: none;
}

#header h1 {
	margin: .7em 0 .5em;
	font-size: 1.75rem;
	line-height: 1.2;
}

/* The two delete-confirmation pages (admin_item.php, admin_set.php) print an
   <h1> inside #content, so those documents carry two of them. Unstyled it took
   the browser default 2em -- 36px against the site title's 28px, the inner
   heading larger than the outer one. It gets the section-heading size instead,
   which is the largest thing #content is allowed to contain. */
#content h1 { margin-top: 0; font-size: 1.5rem;    line-height: 1.25; }

/* h2 unscoped, deliberately, where h1 and h3 above and below it are not.
   ".item h2" wants a size of its own -- a post title inside a box, one step
   under the set heading that lists it -- and "#content h2" is an id selector,
   so the component rule lost the cascade and every post title rendered at
   24px, exactly the size of the heading above it. Adding "#content" to the
   component selector would win the fight; taking the id out of this one ends
   it. Nothing outside #content is an h2 (the header is an h1, the sidebar uses
   <legend>), so the scoping was never doing any work. */
h2 { margin-top: 0; font-size: 1.5rem; line-height: 1.25; }

#content h3 {               font-size: 1.25rem;    line-height: 1.3;  }
#content > p { max-width: var(--measure); }

/* --------------------------------------------------------------- menu toggle */

.nav-button {
	display: block;
	margin: 0 0 var(--gap);
	padding: .7em 1em;
	background: var(--box-bg);
	border: 2px solid var(--box-border);
	border-radius: 8px;
	font-weight: 600;
	cursor: pointer;
	user-select: none;
}

.nav-button [data-when="open"] { display: none; }
#nav-toggle:checked + .nav-button [data-when="closed"] { display: none; }
#nav-toggle:checked + .nav-button [data-when="open"]   { display: inline; }

/* The same three-rule shape as the global focus ring above, and this is the
   one place it is load-bearing rather than tidy: the element that takes focus
   here is the checkbox, which is 1px and clipped, so there is no UA ring to
   fall back on. A :focus-visible-only rule left an iOS 14 iPad with no
   indication whatever of where focus was on the menu button. */
#nav-toggle:focus + .nav-button {
	outline: 3px solid var(--link);
	outline-offset: 2px;
}
#nav-toggle:focus:not(:focus-visible) + .nav-button { outline: none; }
#nav-toggle:focus-visible + .nav-button {
	outline: 3px solid var(--link);
	outline-offset: 2px;
}

/* The toggle is emitted only for a logged-in member, and its absence is the
   logged-out case: with no #nav-toggle in the document neither rule below can
   match, so the login page's two photographs are simply visible. No body class
   and no :has() -- an iPad on iOS 14 has neither. */
#nav-toggle ~ #sidebar         { display: none;  }
#nav-toggle:checked ~ #sidebar { display: block; }

@media (min-width: 60em) {
	.nav-button            { display: none;  }
	#nav-toggle ~ #sidebar { display: block; }
}

/* -------------------------------------------------------------------- sidebar */

/* min-width for the same reason the fieldset below needs one: at >=60em the
   sidebar is a grid item in a fixed 19rem track, and a grid item's automatic
   minimum size is its content, which can exceed the track it sits in. One long
   set name would then push the content column off the right of the page. */
#sidebar { margin-bottom: 1.5rem; min-width: 0; }

#sidebar fieldset {
	margin: 0 0 1.25rem;
	padding: 0;
	border: 0;
	min-width: 0;    /* a fieldset's intrinsic minimum width overflows a grid track */
}

#sidebar legend {
	padding: 0;
	font-weight: 600;
	font-size: 1rem;
	line-height: 1.3;
}

#sidebar ul {
	margin: .35rem 0 0;
	padding: 0;
	list-style: none;
}

/* Roughly 48px tall: a thumb, not a mouse pointer. */
#sidebar a {
	display: block;
	padding: .55rem .5rem;
	text-decoration: none;
	border-radius: 6px;
}

/* :focus, not :focus-visible: this one is only a highlight on top of the ring
   the rules above already draw, but an old Safari would have dropped the
   selector and lost the highlight too. :focus is a superset of
   :focus-visible, so one selector covers every browser and nothing needs a
   companion rule. */
#sidebar a:hover,
#sidebar a:focus {
	background: var(--box-bg);
	text-decoration: underline;
}

#sidebar img { margin-bottom: var(--gap); border-radius: 6px; }

/* ---------------------------------------------------------------------- items */

.item {
	max-width: var(--box-max);
	margin: 0 0 1rem;
	padding: .75rem 1rem;
	background: var(--box-bg);
	border: 3px solid var(--box-border);
	border-radius: 15px;
}

.item h2 { margin: 0 0 .25rem; font-size: 1.375rem; }
.item h2 a { color: inherit; text-decoration: none; }
.item h2 a:hover { text-decoration: underline; }

.row { padding-top: .5rem; }

/* Nothing on these pages is allowed below 1rem. "Everybody needs bigger font
   sizes now" is the requirement, and a 14px label at 75% opacity was both
   smaller and fainter than the text it labels. The hierarchy is a colour step
   and a weight step instead: --ink-quiet is 7.5:1 on the box background and
   6:1 on the page background, so it reads as secondary without reading as
   faint. */
.row .label {
	display: block;
	font-size: 1rem;
	font-weight: 600;
	color: var(--ink-quiet);
}

.row .value { display: block; min-width: 0; overflow-wrap: break-word; }

/* Every real block of prose on these sites is here: a post, a comment, a
   recipe, a caption paragraph. --box-max bounds the BOX, which is a different
   job -- it left the text itself running to 790px, about 92 characters a line,
   at a 1280px window. Long lines are hardest on exactly the readers this
   stylesheet is for: the eye has to find the start of the next line unaided.
   38em against this element's own 18px is 684px, about 79 characters. Scoped
   to .item because the one other .value.body on either site is the two-line
   welcome blurb inside the login form, which is already shorter than this. */
.item .value.body { max-width: var(--measure); }

.row-body { padding-top: .75rem; }
.row-photo { padding-top: .75rem; }
.row-photo img { border-radius: 6px; }

@media (min-width: 40em) {
	.item .row {
		display: grid;
		grid-template-columns: 7em minmax(0, 1fr);
		column-gap: .75rem;
		align-items: baseline;
	}
	.item .row .label { text-align: right; }

	/* Rows with no label span the whole box rather than starting in column two. */
	.item .row-body,
	.item .row-photo,
	.item .row-title { display: block; }

	/* .edit only. Every unlabelled row an item emits now carries row-body,
	   row-photo or row-title, which the rule above already takes out of the
	   grid, so the .item half of this selector became dead the moment
	   class_item.php was repaired. The .edit half is still load-bearing and
	   has no class to hang off: user_check()'s paragraph of welcome sits in a
	   bare <div class="row"> in globals.php, and without this it renders in
	   the 8em label column -- 144px on the one page every member sees before
	   anything else. Measured at 792px with the rule. */
	.edit .row > :only-child { grid-column: 1 / -1; }
}

/* ---------------------------------------------------------------------- forms */

.edit {
	max-width: var(--box-max);
	margin: 0 0 1rem;
	padding: 1rem;
	background: var(--box-bg);
	border: 2px solid var(--box-border);
	border-radius: 15px;
}

.edit .row { padding-top: .85rem; }

/* .label as well as <label>: the "Current:" row in the two file edit forms
   labels a link, not a control, so it is a span (see class_item.php -- its id
   used to collide with the file input's). It still has to look like the real
   labels it sits among. font-size and color are restated because ".row .label"
   in the items section above sets both, and a form label is not a secondary
   colour step the way an item's label is. */
.edit label,
.edit .label {
	display: block;
	margin-bottom: .25rem;
	font-size: inherit;
	font-weight: 600;
	color: inherit;
}

.edit input,
.edit textarea {
	font: inherit;
	width: 100%;
	padding: .5em;
	background: #fff;
	color: inherit;
	border: 1px solid var(--box-border);
	border-radius: 6px;
}

.edit textarea { min-height: 12em; resize: vertical; }

/* Replaces style="width: 10em" on every file input in class_item.php. */
.edit input[type="file"] {
	padding: .4em 0;
	background: transparent;
	border: 0;
}

/* justify-self, not just width: auto. At >=40em .edit .row is a grid and the
   button is a grid item, whose default justify-self is stretch -- so "width:
   auto" resolved to the whole of column two and the two declarations below
   meant nothing. Measured on the live login form before this line: 162px at
   360px wide and 636px at 1280px, which is exactly backwards. */
.edit input[type="submit"] {
	justify-self: start;
	width: auto;
	min-width: 9em;
	padding: .6em 1.5em;
	background: #fff;
	font-weight: 600;
	cursor: pointer;
}

@media (min-width: 40em) {
	.edit .row {
		display: grid;
		grid-template-columns: 8em minmax(0, 1fr);
		column-gap: .75rem;
		align-items: start;
	}
	.edit label,
	.edit .label {
		margin-bottom: 0;
		padding-top: .55em;
		text-align: right;
	}
}

/* -------------------------------------------------------------------- gallery */

/* Was a <table> broken into rows of exactly three, at every screen width.
   auto-fill gives two columns on a 360px phone and five or six on a desktop. */
.gallery {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
	gap: var(--gap);
	margin: 0 0 1rem;
	padding: 0;
	list-style: none;
}

.gallery-item {
	padding: .5rem;
	background: var(--box-bg);
	border: 2px solid var(--box-border);
	border-radius: 10px;
	text-align: center;
}

/* No font-size here, deliberately. It used to say .9375rem -- 15px, under the
   16px floor -- but that declaration never once applied: "#content h3" above
   is an id selector and outranks a class selector, so every caption has always
   rendered at that rule's 1.25rem. Measured: 20px. Rather than add "#content"
   to this selector just to win a fight with it, the caption keeps the section
   heading size, which is comfortably over the floor and is the largest of the
   three plausible answers. The caption under a photograph is the most-read
   text on a gallery page, and it is a name. */
.gallery-item h3 {
	margin: 0 0 .4rem;
	line-height: 1.3;
	overflow-wrap: break-word;
}

.gallery-item a { text-decoration: none; }
.gallery-item a:hover { text-decoration: underline; }

/* A box this stylesheet decides, not one srcset arithmetic decides.

   With "width: auto" an image's layout size is its DENSITY-CORRECTED natural
   size, and that correction is the srcset descriptor divided by the `sizes`
   value. medium/ is 219px wide with a 300w descriptor against sizes: 120px, so
   its density is 2.5 and its used width was 219/2.5 = 87.6px -- and thumb/ at
   120w over the same 120px normalises to the same box. Every candidate lands on
   the same number, so `sizes` was silently driving LAYOUT when its only job is
   to choose a file. Measured at 360px: 88x120 at DPR 1 and 87.6x120 at DPR 2
   and 3, where the tile used to be 105x144. A 17% linear shrink on every
   device, on a site whose whole brief was "everybody needs bigger font sizes
   now".

   So the CSS states the box: 10rem = 160px, deliberately larger than the 144px
   these tiles were before any of this. object-fit: contain is what makes a
   fixed height safe -- it preserves the aspect ratio and letterboxes inside the
   box rather than cropping or squashing, which matters because these are faces
   and because the set mixes portrait scans with landscape reunion photographs.
   `sizes` stays at 120px and now only picks the file: a 1x device takes the
   thumb and upscales it modestly, and the 2x and 3x devices this audience
   actually holds take medium/ and stay sharp. Raising `sizes` to match the box
   would hand back a 78-90% reduction in bytes per gallery page. */
.gallery-item img {
	display: block;
	width: 100%;
	height: 10rem;
	object-fit: contain;
	margin: 0 auto;
}

/* ------------------------------------------------------------- login page art */

.watercolor { margin-top: var(--gap); border-radius: 6px; }
