/* ===================================================================
   fresh.css — presentation layer for the hero-expansion pages
   (index.php carousel, site.php hero page, recent.php updates grid)

   Loaded AFTER style.css so it overrides the inherited 2000s rules at
   equal specificity. No frameworks, no webfonts, no external requests
   of any kind — the estate forbids CDN references, so every typeface
   here is one the visitor already has.

   DESIGN NOTES, so the next person knows these were choices:

   1. THE GRID UNIT IS 468px. The site banners are 468x60 — a legacy ad
      format. They cannot be upscaled without visible softening, and
      cropping destroys the artwork. So rather than fight the format,
      every card is exactly one banner wide and the layout is strict
      multiples of 468. That constraint IS the visual identity.

   2. WARM DARK GROUND, not neutral black. The real content is
      skin-tone photography. A brown-black (#16110f) flatters it; a
      cool grey-black makes it look morgue-lit. This is why the palette
      is warm rather than a default dark theme.

   3. THE BANNERS ARE NOT NORMALIZED. No grayscale, no filter, no
      overlay, no hover desaturation. They are chromatically wild
      because they were made by different people over 25 years, and
      that is the directory's actual identity. Everything AROUND them
      is disciplined instead. Do not "tidy" them.

   4. The table markup in recent.php is preserved and restyled into a
      CSS grid via display:contents on the rows. No PHP change needed.
   =================================================================== */

:root {
	/* Ground and surfaces — warm brown-black, see design note 2 */
	--ink:        #16110f;   /* page ground                       */
	--ink-2:      #1f1815;   /* card surface                      */
	--ink-3:      #2b211c;   /* raised / hover surface            */
	--rule:       #3a2c24;   /* hairlines and borders             */

	/* Ink on that ground — warm off-white, never pure #fff */
	--bone:       #eee6dc;   /* primary text                      */
	--bone-dim:   #a2948a;   /* secondary text, captions          */

	/* Accents. Brass carries forward the love001 banner's gold.    */
	--brass:      #c9922e;
	--brass-lift: #e8b84b;   /* hover / emphasis                  */
	--rose:       #b4485a;   /* RESERVED for join actions only     */

	/* The one measurement everything derives from */
	--unit:       468px;     /* native site-banner width           */
	--gap:        28px;

	/* Type roles — three, all locally available */
	--prose: Georgia, "Palatino Linotype", "Book Antiqua", serif;
	--ui:    system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
	--stamp: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
}

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

body {
	margin: 0;
	padding: 0 20px 72px;
	background: var(--ink);
	color: var(--bone);
	font-family: var(--ui);
	font-size: 15px;
	line-height: 1.55;
	-webkit-text-size-adjust: 100%;
}

a         { color: var(--brass); text-decoration: none; }
a:hover   { color: var(--brass-lift); }
a:focus-visible,
img:focus-visible {
	/* Keyboard focus must stay visible — this is a link-dense page */
	outline: 2px solid var(--brass-lift);
	outline-offset: 2px;
}
img { border: 0; display: block; }

/* ---------- masthead ------------------------------------------------ */

.logo_div,
.head_div {
	max-width: calc(var(--unit) * 3 + var(--gap) * 2);
	margin: 0 auto;
	text-align: center;
}
.logo_div { padding-top: 34px; }
.logo_div img,
.head_div img { max-width: 100%; height: auto; margin: 0 auto; }

/* ---- knocking the white out of the two legacy logo rasters ----------
   Both ship with a hard white background and no alpha channel
   (BHE_Head.gif is a 440x35 grayscale wordmark; bighornlogo_blue.jpg is
   123x108 — and JPEG cannot carry transparency at all). On a dark ground
   they read as harsh white blocks.

   Fixed here in CSS rather than by editing the images, deliberately:
   the image files are shared source with sites.bhebill.com, and a
   stylesheet rule cannot leak into another site the way an edited
   raster could. Revert = delete these two rules.

   HOW IT WORKS: invert() turns the white field black and the dark
   artwork light. mix-blend-mode:screen then renders black as fully
   transparent while keeping the light artwork — and because screen
   works on continuous values, the images' own antialiased edges become
   a smooth alpha ramp instead of the jagged 1-bit cutout a GIF
   transparency index would give. No halo, no matte line. */

.logo_div img[src*="BHE_Head"] {
	/* Grayscale wordmark -> clean bone-white lettering. */
	filter: invert(1);
	mix-blend-mode: screen;
}

.head_div img[src*="bighornlogo"] {
	/* The blue mark inverts to amber, which sits with the brass accent
	   rather than fighting it. hue-rotate nudges it onto the brass hue
	   instead of the raw complement of blue. */
	filter: invert(1) hue-rotate(-14deg) saturate(.85) brightness(1.05);
	mix-blend-mode: screen;
}

/* Blend modes need something to blend against; without an explicit
   background these can composite against the canvas instead. */
.logo_div, .head_div { background: var(--ink); }

.head_div {
	padding-bottom: 26px;
	margin-bottom: 34px;
	border-bottom: 1px solid var(--rule);
}

/* ---------- the 468 grid (see design note 1 and 4) ------------------ */

/* recent.php ships a <table>; we keep the markup and make it a grid.
   display:contents on tbody/tr promotes the cells to grid items, so
   the two-per-row markup reflows to 1/2/3 columns by viewport. */
table         { display: grid;
                grid-template-columns: repeat(auto-fit, var(--unit));
                justify-content: center;
                gap: var(--gap);
                max-width: calc(var(--unit) * 3 + var(--gap) * 2);
                margin: 0 auto;
                border-collapse: separate; }
tbody, tr.row { display: contents; }

/* ---------- the card ------------------------------------------------ */

/* TWO CARD SHAPES, because the two pages put different things in the
   same .site_div class:
     - index.php's legacy list holds a 468-wide BANNER + description.
       That must be VERTICAL (banner on top). Making it a flex ROW turns
       the banner into a shrinkable flex item sharing 468px with the
       text, which squeezes a 468x60 banner down to a fraction of its
       size. That was the "banners are tiny" bug.
     - recent.php holds a 160x120 THUMB + description, which reads
       better side by side.
   Default is COLUMN (safe for banners); the thumb variant opts into
   row via :has(). If a browser lacks :has() support everything stays
   vertical, which is the harmless direction to fail. */
td.site_div,
div.site_div {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	width: var(--unit);
	max-width: 100%;
	padding: 0;                        /* banner is full-bleed        */
	background: var(--ink-2);
	border: 1px solid var(--rule);
	border-radius: 3px;                /* just enough to not be a box */
	overflow: hidden;
	transition: border-color .18s ease, background .18s ease, transform .18s ease;
}
td.site_div:hover,
div.site_div:hover {
	background: var(--ink-3);
	border-color: var(--brass);
	transform: translateY(-2px);
}

/* Banners are NOT uniformly 468x60 — measured across the 87 files:
   65 are 468x60, plus 480x80, 468x120, 460x60, 385x60, 318x59, 200x50,
   180x45, 134x29, 99x30, 93x25, and a large number of 1x1 placeholder
   files for sites that never had artwork.

   So: cap at 468 and CENTRE at natural size. Never width:100% — that
   upscales a 93x25 banner five times over into mush, and smears a 1x1
   placeholder across the whole card. Same rule as the thumbs and the
   hero: respect the artifact, don't stretch it to the container. */
.site_div img.banner,
.hero_banner_div img {
	max-width: var(--unit);
	width: auto;
	height: auto;
	margin: 0 auto;
	image-rendering: auto;
}

/* A 1x1 placeholder cannot be detected in CSS (there is no intrinsic-
   size selector). Left visible-but-tiny deliberately rather than
   stretched — a 1px dot is honest, a 468px smear is not. Suppressing
   them properly needs a getimagesize() check server-side; see the
   note in the deploy report. */

/* Post thumbnails are 160x120 on disk. NEVER stretch them to the card
   width — a 2.9x upscale turns them to mush. Same principle as the
   banners: respect the artifact's native size and build the grid from
   it. So the thumbs become a crisp contact sheet at 1:1 pixels. */
img.post_thumb {
	width: 160px;
	height: 120px;
	flex: 0 0 auto;
	background: var(--ink-3);
	border-radius: 2px;
}

/* ---------- card text ----------------------------------------------- */

.description {
	flex: 1 1 auto;
	min-width: 0;
	padding: 12px 16px;
	font-family: var(--prose);
	font-size: 14px;
	line-height: 1.45;
	color: var(--bone-dim);
	border-top: 1px solid var(--rule);   /* vertical card default */
	display: flex;
	flex-direction: column;
	justify-content: center;
}

/* ---- the horizontal (thumbnail) variant ---------------------------- */
td.site_div:has(img.post_thumb),
div.site_div:has(img.post_thumb) { flex-direction: row; }

/* Beside the thumb, the divider becomes vertical instead of horizontal. */
td.site_div:has(img.post_thumb) > .description,
div.site_div:has(img.post_thumb) > .description {
	border-top: 0;
	border-left: 1px solid var(--rule);
}

/* Banners must never be squeezed by their flex parent. */
.site_div img.banner { flex: 0 0 auto; align-self: center; }
/* Long site names must not blow out the fixed 468 card. */
.description a { overflow-wrap: break-word; }
.description a {
	display: block;
	font-family: var(--ui);
	font-size: 15px;
	font-weight: 600;
	letter-spacing: .01em;
	color: var(--bone);
	margin-bottom: 6px;
}
.description a:hover { color: var(--brass-lift); }

/* Freshness stamp. This is a recency directory — the date is data,
   so it gets the monospace treatment rather than being buried. */
.post_date {
	display: inline-block;
	margin-top: 10px;
	font-family: var(--stamp);
	font-size: 11px;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--brass);
	margin-top: 6px;
}

/* ---------- site.php hero ------------------------------------------- */

.hero_banner_div,
.hero_image_div,
.join_div {
	max-width: calc(var(--unit) * 2 + var(--gap));
	margin: 0 auto;
}
.hero_banner_div { width: var(--unit); max-width: 100%; }

/* The hero is the posting's FULL-SIZE image — and its orientation is
   unpredictable (angelfoot's is 1600x2400 portrait; others are
   landscape). So constrain by HEIGHT and let width follow. Forcing
   width:100% on a portrait source renders it ~1400px tall and the page
   becomes a single enormous photograph. No cropping either: these are
   composed photographs, not textures. */
.hero_image_div  { margin: 26px auto; text-align: center; }
.hero_image_div img {
	max-height: 62vh;
	width: auto;
	max-width: 100%;
	height: auto;
	margin: 0 auto;
	border: 1px solid var(--rule);
	border-radius: 3px;
	background: var(--ink-2);
}
.hero_image_div .post_date { margin-top: 14px; }

.sitetitle {
	display: block;
	max-width: calc(var(--unit) * 2 + var(--gap));
	margin: 30px auto 4px;
	font-family: var(--prose);
	font-size: 30px;
	line-height: 1.2;
	font-weight: normal;
	letter-spacing: -.01em;
	color: var(--bone);
}

/* ---------- join action — the only rose on the page ----------------- */

.join_div { text-align: center; margin: 32px auto 44px; }

.button, .buttonsmall,
.join_div a {
	display: inline-block;
	padding: 13px 30px;
	background: var(--rose);
	color: #fff;
	font-family: var(--ui);
	font-size: 13px;
	font-weight: 700;
	letter-spacing: .1em;
	text-transform: uppercase;
	border: 0;
	border-radius: 2px;
	cursor: pointer;
	transition: filter .16s ease;
}
.button:hover, .buttonsmall:hover,
.join_div a:hover { filter: brightness(1.14); color: #fff; }

/* ---------- carousel (index.php) ------------------------------------ */


/* ---------- legacy classes still present on these pages ------------- */

.bold, .largebold { font-weight: 600; color: var(--bone); }
.small            { font-size: 12.5px; color: var(--bone-dim); }

/* ---------- responsive: the grid already reflows; tune type --------- */

@media (max-width: 560px) {
	body        { padding: 0 12px 48px; }
	.sitetitle  { font-size: 24px; }
	:root       { --unit: 100%; --gap: 18px; }
	table       { grid-template-columns: 1fr; }
	/* Keep the thumb at native pixels; just let text wrap under it. */
	td.site_div, div.site_div { flex-direction: row; }
	.description { padding: 10px 12px; font-size: 13.5px; }
}

/* Respect a reduced-motion preference — the carousel auto-advances. */
@media (prefers-reduced-motion: reduce) {
	*, *::before, *::after {
		animation-duration: .001ms !important;
		transition-duration: .001ms !important;
	}
	td.site_div:hover, div.site_div:hover { transform: none; }
}

/* ===================================================================
   VISUAL REVIEW PASS — corrections made from actual screenshots
   (headless chromium, 1440px). Everything above this line was written
   blind from the CSS; these are the things that only showed up once
   the pages could be seen.
   =================================================================== */

/* 1. LINKS. Underlines survived `a { text-decoration:none }`, so state
      it across the link pseudo-classes rather than relying on the bare
      element selector to win. */
a, a:link, a:visited, a:active {
	color: var(--brass);
	text-decoration: none;
}
a:hover { color: var(--brass-lift); text-decoration: none; }

/* 2. HERO IMAGE was rendering 930px tall — 62vh is still enormous on a
      tall window, and it pushed the posts grid entirely below the fold.
      A hero should lead the page, not be the page. */
.hero_image_div img { max-height: min(520px, 52vh); }

/* 3. "View the full set" is a LINK that inherited .post_date's
      monospace stamp styling, so it read as a broken timestamp.
      Give it back its own voice. */
.hero_image_div a.post_date {
	font-family: var(--ui);
	font-size: 13px;
	letter-spacing: .04em;
	text-transform: none;
	color: var(--brass);
	border: 1px solid var(--rule);
	border-radius: 2px;
	padding: 8px 18px;
}
.hero_image_div a.post_date:hover {
	border-color: var(--brass);
	background: var(--ink-2);
}

/* 4. RECENT CARDS. The description panel was centred, which left the
      site name floating in the middle of a wide empty band. Left-align
      the text column; give the thumb column a fixed 160 and let the
      model-name caption (a text node inside the thumb's own anchor)
      read as a caption rather than a link. */
td.site_div:has(img.post_thumb) > a,
div.site_div:has(img.post_thumb) > a {
	flex: 0 0 160px;
	display: flex;
	flex-direction: column;
	gap: 5px;
	padding: 10px 0 10px 10px;
	font-family: var(--ui);
	font-size: 11.5px;
	line-height: 1.3;
	color: var(--bone-dim);
	text-align: center;
}
td.site_div:has(img.post_thumb) > a:hover { color: var(--brass-lift); }

td.site_div:has(img.post_thumb) > .description,
div.site_div:has(img.post_thumb) > .description {
	text-align: left;
	align-items: flex-start;
	padding: 14px 18px;
}

/* 5. CARDS WITH NO WRITEUP left a dead band under the banner. Collapse
      the panel when it holds nothing but whitespace. */
.description:empty { display: none; }
.site_div > .description:only-child:empty { display: none; }

/* 6. CAROUSEL. The slide image ran to ~300px tall against a 940px
      container so it sat left of a large void; the caption was a dark
      underlined link on a dark ground; and Prev/Next were unstyled
      browser buttons. */
/* COSMETICS ONLY below. Do NOT set display/flex/width on
   .hero-carousel-track, .hero-carousel-slide, or the dot elements:
   S3 built that geometry and C3 verified it with a real headless-browser
   test (8 of 8 slides reachable, zero alignment drift). Overriding the
   track's display broke slide clipping and collapsed the dots — my
   error, reverted. Style colour and type here; leave layout alone. */

.hero-carousel-title  { display: block; margin: 16px auto 6px;
                        font-family: var(--prose); font-size: 21px;
                        color: var(--bone); }
.hero-carousel-title a, .hero-carousel-title a:link { color: var(--bone); }
.hero-carousel-title a:hover { color: var(--brass-lift); }

.hero-carousel-desc   { display: block; max-width: 62ch; margin: 0 auto;
                        font-family: var(--prose); font-size: 14px;
                        line-height: 1.5; color: var(--bone-dim); }
.hero-carousel-desc a, .hero-carousel-desc a:link { color: var(--bone-dim); }

/* Prev/Next and the dot indicators, whatever element the JS emits. */
.hero-carousel button {
	background: transparent;
	color: var(--brass);
	border: 1px solid var(--rule);
	border-radius: 2px;
	padding: 7px 16px;
	margin: 16px 5px 0;
	font-family: var(--ui);
	font-size: 12px;
	letter-spacing: .08em;
	text-transform: uppercase;
	cursor: pointer;
	transition: border-color .16s ease, color .16s ease;
}
.hero-carousel button:hover {
	border-color: var(--brass);
	color: var(--brass-lift);
	background: var(--ink-3);
}

/* Centre the slide's inline content. text-align cannot affect the
   track's widths, transforms or clipping, so this is safe to set where
   display/flex/width are not — the image was sitting left of centre. */
.hero-carousel-slide { text-align: center; }

/* ===================================================================
   TWO-COLUMN HERO (site.php) — photo left, text right.

   Centring a portrait hero left two dead margins either side of it, so
   the photo goes left and the title / writeup / join action stack in the
   right column beside it.

   Done with a grid on the page wrapper rather than new markup. The
   wrapper has no class of its own, so it is selected via
   `body:has(.hero_image_div) > div` — which matches site.php and
   nothing else, because it is the only page with a hero image.
   sitetitle, hero_image_div, description and join_div are already
   siblings there, so they can be placed directly.
   =================================================================== */

@media (min-width: 900px) {
	body:has(.hero_image_div) > div {
		display: grid;
		grid-template-columns: auto minmax(0, 1fr);
		column-gap: 34px;
		align-items: start;
		max-width: calc(var(--unit) * 3 + var(--gap) * 2);
		margin: 0 auto;
	}

	/* Full-width bands: masthead, the site's own banner, the posts grid. */
	body:has(.hero_image_div) > div > .logo_div,
	body:has(.hero_image_div) > div > .head_div,
	body:has(.hero_image_div) > div > .hero_banner_div,
	body:has(.hero_image_div) > div > table,
	body:has(.hero_image_div) > div > a { grid-column: 1 / -1; }

	/* Photo occupies the left column and spans the three text blocks. */
	body:has(.hero_image_div) > div > .hero_image_div {
		grid-column: 1;
		grid-row: span 3;
		margin: 0;
		text-align: left;
	}
	.hero_image_div img { max-height: min(560px, 60vh); }

	/* Right column: title, writeup, join — left-aligned, not centred. */
	body:has(.hero_image_div) > div > .sitetitle,
	body:has(.hero_image_div) > div > .description,
	body:has(.hero_image_div) > div > .join_div {
		grid-column: 2;
		max-width: none;
		margin: 0;
		text-align: left;
	}
	body:has(.hero_image_div) > div > .sitetitle  { margin-bottom: 12px; align-self: end; }
	body:has(.hero_image_div) > div > .description {
		border: 0;
		padding: 0;
		font-size: 15.5px;
		line-height: 1.62;
		align-self: start;
	}
	body:has(.hero_image_div) > div > .join_div { margin-top: 22px; align-self: start; }

	/* The "view the full set" link sits under the photo, left-aligned. */
	.hero_image_div a.post_date { display: inline-block; margin-top: 14px; }
}

/* ---- corrections from the two-column hero screenshot ---------------- */

/* 1. JOIN NOW rendered red-on-pink and unreadable: style.css styles the
      link pseudo-classes, and `a:link` (0,1,1) outranks `.button`
      (0,1,0). Raise specificity past it rather than reaching for
      !important. */
a.button, a.button:link, a.button:visited, a.button:active,
.join_div a, .join_div a:link, .join_div a:visited {
	background: var(--rose);
	color: #fff;
}
a.button:hover, .join_div a:hover { color: #fff; filter: brightness(1.14); }

/* 2. The 3-column grid (3*468 + 2*28 = 1460) overflowed a 1440 viewport
      and clipped the right-hand card. Cap on the viewport as well. */
table,
body:has(.hero_image_div) > div,
.logo_div, .head_div {
	max-width: min(100%, calc(var(--unit) * 3 + var(--gap) * 2));
}

/* 3. The masthead rule shrank to the logo's width once .head_div became
      a grid item sized to its content. Make the bands span. */
body:has(.hero_image_div) > div > .logo_div,
body:has(.hero_image_div) > div > .head_div { justify-self: stretch; width: 100%; }

/* 4. A 560px portrait left a tall void beside ~150px of text. Shorter
      photo, and the writeup column reads better at a measure that is
      not full width. */
@media (min-width: 900px) {
	.hero_image_div img { max-height: min(430px, 52vh); }
	body:has(.hero_image_div) > div > .description { max-width: 62ch; }
}

/* ---- explicit hero grid rows ----------------------------------------
   Auto-placement let the photo's spanned rows be sized by the short text
   blocks, so the photo (and its "view the full set" link) overflowed
   into the posts grid below. site.php's sibling order is fixed and
   known, so pin the rows rather than relying on placement. */
@media (min-width: 900px) {
	body:has(.hero_image_div) > div > .logo_div        { grid-row: 1; }
	body:has(.hero_image_div) > div > .head_div        { grid-row: 2; }
	body:has(.hero_image_div) > div > a                { grid-row: 3; }
	body:has(.hero_image_div) > div > .hero_banner_div { grid-row: 4; }
	body:has(.hero_image_div) > div > .hero_image_div  { grid-row: 5 / span 3; grid-column: 1; }
	body:has(.hero_image_div) > div > .sitetitle       { grid-row: 5; grid-column: 2; }
	body:has(.hero_image_div) > div > .description     { grid-row: 6; grid-column: 2; }
	body:has(.hero_image_div) > div > .join_div        { grid-row: 7; grid-column: 2; }
	body:has(.hero_image_div) > div > table            { grid-row: 8; grid-column: 1 / -1;
	                                                     margin-top: 30px; }
}

/* The join link's inline style (width:400px, color:red, its own border)
   has been removed from site.php, so the button styling above now
   applies. Give it a sensible intrinsic width instead of 400px. */
.join_div a.button { min-width: 240px; text-align: center; }

/* Slack row: the photo spans 5-8 while the text occupies 5-7, so the
   leftover height lands in the empty row 8 instead of being distributed
   across the text rows (which pushed JOIN NOW away from the writeup).
   Plus breathing room under the site's banner. */
@media (min-width: 900px) {
	body:has(.hero_image_div) > div                     { row-gap: 0; }
	body:has(.hero_image_div) > div > .hero_banner_div  { margin-bottom: 22px; }
	body:has(.hero_image_div) > div > .hero_image_div   { grid-row: 5 / span 4; }
	body:has(.hero_image_div) > div > table             { grid-row: 9; }
}
