/* strangefolk — pages */

/* ---- hero ----
   Ported from homepage-mockup.html:34-57 (.hero -> .sf-hero). The mockup's
   placeholder gradients on .art are replaced with a rule that covers the
   real featured-specimen photo and keeps the vignette (brief step 6); the
   dashed "Scene art" dev-only annotation (.hero .slot) is not ported — the
   theme renders a real image, not a mockup placeholder. */
.sf-hero { position: relative; min-height: min(78vh, 660px); display: flex; align-items: flex-end; overflow: hidden; border-bottom: 1px solid var(--rule) }
.sf-hero__art { position: absolute; inset: 0 }
.sf-hero__art img { width: 100%; height: 100%; object-fit: cover; }
/* The scrim. homepage-mockup.html:36-40 stacked three background layers on
   .hero .art: two placeholder gradients standing in for the photo, and — at
   50% 100%, rising from the bottom edge where the headline and lede sit —
   rgba(10,13,10,.97). That third one is not a placeholder, it is the
   readability treatment that lets Bone text sit over arbitrary scene art.
   Porting the real photo in replaced all three, so the scrim was lost and
   the headline was left riding directly on the image with only the soft
   edge-vignette below. Reinstated here as an overlay above the photo instead
   of as a background beneath it, with the mockup's ::before scanline texture
   (line 41-42), which went the same way. Paint order: img -> ::before
   (scrim + scanlines) -> ::after (vignette) -> .sf-hero .u (text). */
.sf-hero__art::before {
	content: "";
	position: absolute;
	inset: 0;
	background:
		radial-gradient(ellipse 120% 80% at 50% 100%, rgba(10,13,10,.97), transparent 62%),
		/* Reaches higher than the radial and along the axis the narrow
		   layout actually stacks in. On a phone the hero crops to portrait,
		   so object-fit: cover centres the frame and puts the brightest band
		   of a dusk photograph — the horizon — directly behind the Fog-
		   coloured lede, which is the lowest-contrast text in the hero. The
		   radial alone left its first line washed out. Kept deliberately
		   gentler than the wide-viewport wash below: it has to clear the
		   lede without flattening the photograph back into a black band,
		   which is the whole reason that wash stops at 700px. */
		linear-gradient(to top, rgba(10,13,10,.93) 0%, rgba(10,13,10,.76) 40%, rgba(10,13,10,.32) 64%, transparent 86%),
		repeating-linear-gradient(180deg, rgba(0,0,0,.16) 0 1px, transparent 1px 4px);
}
/* Wide enough that the headline is a column rather than the whole page.
   Here the vertical wash above is replaced by a horizontal one, because the
   text no longer runs the full width and darkening the bottom of the frame
   would be treating the wrong axis: at this size the headline block sits
   around 40% of the way UP the hero, past the point where the radial has
   already faded to nothing, and a dusk sky or a bank of lit fog lands exactly
   there. On the fog-field image that left the Bone headline, the Fog lede and
   the amber intake label washed out together.

   Anchored left to follow the text column (capped at 15ch) and gone by 78%,
   so the right-hand two-fifths of the photograph stay exactly as exposed as
   they were. This is the same job the radial was always doing — the comment
   on the base rule calls it the treatment that lets Bone text sit over
   arbitrary scene art — turned onto the axis the text actually runs along.
   It matters more now than it did: the hero used to be one dark fixture and
   now rotates through real landscape photography (inc/hero.php). */
@media (min-width: 700px) {
	.sf-hero__art::before {
		background:
			radial-gradient(ellipse 120% 80% at 50% 100%, rgba(10,13,10,.97), transparent 62%),
			linear-gradient(96deg, rgba(10,13,10,.9) 0%, rgba(10,13,10,.74) 34%, rgba(10,13,10,.3) 60%, transparent 78%),
			repeating-linear-gradient(180deg, rgba(0,0,0,.16) 0 1px, transparent 1px 4px);
	}
}
.sf-hero__art::after { content: ""; position: absolute; inset: 0; box-shadow: inset 0 0 190px 60px rgba(8,10,8,.95); }
.sf-hero .u { position: relative; padding-top: 92px; padding-bottom: 60px; width: 100% }
.sf-hero__intake { color: var(--amber) }

.sf-hero__title { font-family: var(--mono); font-weight: 700; text-transform: uppercase; font-size: clamp(30px, 6.6vw, 74px); line-height: .98; letter-spacing: -.018em; margin: 14px 0 0; max-width: 15ch; text-wrap: balance }
.sf-hero__sub { font-size: clamp(17px, 2.1vw, 22px); color: var(--fog); margin: 20px 0 0; max-width: 44ch }
.sf-hero__acts { display: flex; gap: 13px; flex-wrap: wrap; margin-top: 34px }

/* Kept per brief step 6 ("the .rise animation kept"); not yet wired to any
   element in front-page.php's markup. */
.rise { animation: rise .9s cubic-bezier(.2, .7, .3, 1) both }
.rise:nth-child(2) { animation-delay: .09s }
.rise:nth-child(3) { animation-delay: .17s }
.rise:nth-child(4) { animation-delay: .25s }
@keyframes rise { from { opacity: 0; transform: translateY(13px) } to { opacity: 1; transform: none } }

/* ---- featured specimen ----
   Ported from homepage-mockup.html:95-111 (.spec -> .sf-spec). The stamp and
   the <dl> are already covered by the .sf-stamp/.sf-data components (Task 3)
   so they are not re-defined here. .sf-spec__art gets the same containment
   treatment already applied to .sf-card__img (overflow:hidden + a sized img)
   because it renders a real photo the same way — without it, the same
   640x640-into-a-small-box overflow bug Task 3 fixed for the card grid would
   reappear here. */
.sf-spec { border: 1px solid var(--rule); background: var(--surface); display: grid; grid-template-columns: 1.15fr 1fr }
@media (max-width: 840px) { .sf-spec { grid-template-columns: 1fr } }
.sf-spec__art { position: relative; min-height: 400px; background: linear-gradient(170deg, var(--art-fallback-1), var(--art-fallback-2)); overflow: hidden }
.sf-spec__art img { width: 100%; height: 100%; object-fit: cover; display: block }
.sf-spec__art::after { content: ""; position: absolute; inset: 0; box-shadow: inset 0 0 110px 34px rgba(8, 10, 8, .9) }
.sf-spec__data { padding: 34px 34px 38px; border-left: 1px solid var(--rule) }
@media (max-width: 840px) { .sf-spec__data { border-left: none; border-top: 1px solid var(--rule) } }
.sf-spec__data h3 { font-family: var(--mono); font-size: clamp(21px, 3vw, 30px); letter-spacing: -.005em; text-transform: uppercase; margin: 19px 0 3px; font-weight: 700 }
.sf-spec__place { font-family: var(--mono); font-size: 10.5px; letter-spacing: .17em; text-transform: uppercase; color: var(--lichen) }
.sf-spec__notes { font-size: 15.5px; line-height: 1.68; color: var(--fog); margin: 0 0 26px }

/* ---- specimen file ----
   Ported from page-layouts.html:36-71 (.sp-top/.sp-art/.sp-data ->
   .sf-file__top/__art/__data, .prose -> .sf-prose, .redact -> .sf-redact,
   .log -> .sf-log, .log .row -> .sf-log__row). .sf-stamp and the <dl>
   (.sf-data) are already covered by the Task 3 components, so they are not
   re-declared here. .sf-file__art gets the same containment treatment as
   .sf-card__img and .sf-spec__art (overflow:hidden plus a sized img)
   because it renders a real photo, not the mockup's placeholder gradient —
   without it the same 640x640-into-a-small-box overflow bug those fixed
   would reappear here too; the mockup's dev-only ".sp-art .slot" label is
   dropped for the same reason the hero's was. h1 and the "place" line are
   scoped to .sf-file__data rather than the mockup's bare h1/.place
   selectors, matching how the homepage's equivalent
   (.sf-spec__data h3 / .sf-spec__place) avoids a bare element selector
   leaking into other templates. .sf-file__foot ports the mockup's bare
   footer{...} rule (line 134), scoped the same way. */
.sf-file__top { display: grid; grid-template-columns: 1.25fr 1fr; gap: 0; border: 1px solid var(--rule); margin-top: 20px }
@media (max-width: 880px) { .sf-file__top { grid-template-columns: 1fr } }
.sf-file__art { position: relative; min-height: 470px; background: linear-gradient(168deg, var(--art-fallback-1), var(--art-fallback-2)); overflow: hidden }
.sf-file__art img { width: 100%; height: 100%; object-fit: cover; display: block }
.sf-file__art::after { content: ""; position: absolute; inset: 0; box-shadow: inset 0 0 130px 40px rgba(8,10,8,.92) }
.sf-file__data { padding: 36px 34px 40px; background: var(--surface); border-left: 1px solid var(--rule) }
@media (max-width: 880px) { .sf-file__data { border-left: none; border-top: 1px solid var(--rule) } }
.sf-file__data h1 { font-family: var(--mono); font-weight: 700; text-transform: uppercase; font-size: clamp(28px, 4.6vw, 46px); line-height: 1; letter-spacing: -.015em; margin: 20px 0 5px }
.sf-file__place { font-family: var(--mono); font-size: 11px; letter-spacing: .17em; text-transform: uppercase; color: var(--lichen) }

.sf-prose { max-width: 68ch }
.sf-prose p { margin: 0 0 17px; color: var(--fog); font-size: 16.5px; line-height: 1.72 }
.sf-prose p:first-child::first-letter { font-family: var(--mono); font-size: 2.6em; line-height: .85; float: left; margin: 5px 11px 0 0; color: var(--amber); font-weight: 700 }
.sf-redact { background: #000; color: transparent; user-select: none; padding: 0 3px }

.sf-log { border: 1px solid var(--rule); background: var(--surface) }
.sf-log__row { display: grid; grid-template-columns: 130px 1fr auto; gap: 20px; padding: 14px 18px; border-bottom: 1px solid var(--rule); font-size: 15px; color: var(--fog); align-items: baseline }
.sf-log__row:last-child { border-bottom: none }
.sf-log__d { font-family: var(--mono); font-size: 10.5px; letter-spacing: .13em; color: var(--lichen); white-space: nowrap }
.sf-log__v { font-family: var(--mono); font-size: 9.5px; letter-spacing: .16em; text-transform: uppercase; color: var(--dim); white-space: nowrap }
@media (max-width: 640px) { .sf-log__row { grid-template-columns: 1fr; gap: 5px } }

.sf-file__foot { margin-top: 72px; border-top: 1px solid var(--rule); padding: 26px 0 60px }

/* ---- archive index header ----
   Neither mockup contains an archive/index header to port (grepped both —
   nothing). Task 7 (the specimen index) is the first template to need one,
   so it owns this definition; Tasks 8 and 10 reuse it rather than
   redefining it, same "first use owns it" rule already applied to
   .sf-grid4. Every value below is drawn from elsewhere in this system
   rather than invented: the top padding matches .sf-crumb's (both are "the
   first thing under the nav"), the bottom margin matches .sf-shead's
   header-to-content gap, the h1 reuses .sf-file__data h1's exact clamp()
   so it sits in the same page-title family as .sf-hero__title, and the
   lede is given the .sf-hero__sub treatment (fog, capped measure). The h1
   is scoped to .sf-archive__head rather than restyling .sf-shead__title,
   which stays correctly sized for sf_section_head()'s in-page sub-section
   labels and is used elsewhere for exactly that. */
.sf-archive__head { padding-top: 26px; margin-bottom: 28px }
.sf-archive__head h1 { font-family: var(--mono); font-weight: 700; text-transform: uppercase; font-size: clamp(28px, 4.6vw, 46px); line-height: 1; letter-spacing: -.015em; margin: 0 0 14px }
/* .sf-404__lede shares this rule (Task 11 dedupe) rather than repeating it —
   404.php's lede was defined verbatim identical to this one down in the
   "page-level titles" section below; same fog/clamp/measure treatment, same
   reason (both are the .sf-hero__sub-style intro line under a page head). */
.sf-archive__lede,
.sf-404__lede { font-size: clamp(17px, 2.1vw, 22px); color: var(--fog); margin: 0; max-width: 44ch }
.sf-empty { font-family: var(--mono); font-size: 10px; letter-spacing: .24em; text-transform: uppercase; color: var(--dim); padding: 28px 0 }

/* ---- page-level titles: field note, static page, 404 ----
   Controller ruling on Task 10: .sf-shead__title is 13px, sized for
   sf_section_head()'s in-page <h2> sub-labels (the "§ NN" ones), not a
   page-level <h1>. .sf-archive__head h1 above already fixes the archive
   case (Task 7); these three sit outside that wrapper so they still need
   covering. Reuses .sf-file__data h1 / .sf-archive__head h1's exact
   clamp() so every page title in the theme agrees.

   Scoped by each template's own wrapper class rather than by restyling
   .sf-shead__title itself — same approach as .sf-archive__head h1, which
   already proves the pattern: a wrapper h1 selector (0,1,1) out-specifies
   the bare .sf-shead__title class (0,1,0), so page.php's and 404.php's
   <h1> can keep that class without it winning. Leaving the class on is a
   deliberate no-op, not an oversight — matches archive.php's h1, which
   was reviewed and kept it for the same reason.

   single.php's <h1> (in .sf-article__head) carries no class at all in the
   brief — the ruling's prose describes it as "will render at 13px" but
   the code block never puts .sf-shead__title on it, so that specific
   diagnosis doesn't apply verbatim; left unstyled it would instead fall
   back to the serif browser-default h1, which is just as wrong for this
   design system. Folded into this same rule so it gets the identical
   page-title treatment as the other two. */
.sf-article__head h1,
.sf-page h1,
.sf-404 h1 {
	font-family: var(--mono);
	font-weight: 700;
	text-transform: uppercase;
	font-size: clamp(28px, 4.6vw, 46px);
	line-height: 1;
	letter-spacing: -.015em;
	margin: 20px 0 14px;
}

/* ---- article, page, and 404 wrappers ----
   Not in the brief's step 3, but every other top-level template gets a
   26px gap under the nav from its first child (.sf-crumb or
   .sf-archive__head both use padding-top: 26px — see the archive-header
   comment above). single.php, page.php and 404.php have no .sf-crumb, so
   without this they would be the only templates sitting flush against the
   nav. Reuses the same 26px rather than inventing a new value.
   .sf-article__head additionally reuses .sf-archive__head's 28px
   header-to-content gap, for the same reason. */
.sf-article__head,
.sf-page,
.sf-404 { padding-top: 26px }
.sf-article__head { margin-bottom: 28px }

/* the_post_thumbnail('sf-scene') is a real 1400x900 photo. Every other
   template that renders one contains it the same way
   (.sf-hero__art/.sf-spec__art/.sf-file__art img — all width:100%;
   height:100%; object-fit:cover); without it here the image would
   overflow .u exactly like the bug those fixed for the card grid. */
.sf-article__art { margin: 0 0 34px }
.sf-article__art img { width: 100%; height: auto; display: block }

/* ---- pagination & post navigation ----
   the_posts_pagination() (archive.php, archive-sf_specimen.php, index.php)
   and the_post_navigation() (single.php:30, inside .sf-article__foot) both
   emit WordPress core's own unclassed markup — <nav class="navigation
   pagination">/<nav class="navigation post-navigation"> wrapping
   <a class="page-numbers">/<span class="page-numbers current">/
   <div class="nav-links"><div class="nav-previous">…</div>… — and nothing in
   this theme styled either before now. Invisible with the seeded dev DB's
   one specimen and one post; both plans call for far more content, so this
   fires the moment either archive crosses ten items. Values are drawn from
   the existing mono/label scale and tokens (.sf-crumb, .sf-btn) rather than
   invented, so unclassed links don't fall back to theme.json's global
   Signal-Flare-serif link style. */
.pagination { margin-top: 40px; padding-top: 24px; border-top: 1px solid var(--rule); display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.pagination .page-numbers { font-family: var(--mono); font-size: 11px; letter-spacing: .08em; color: var(--fog); text-decoration: none; border: 1px solid var(--rule-hi); padding: 8px 13px; white-space: nowrap; }
.pagination a.page-numbers:hover { color: var(--bone); border-color: var(--amber-dim); }
.pagination .page-numbers.current { color: var(--ground); background: var(--amber); border-color: var(--amber); font-weight: 700; }
.pagination .page-numbers.dots { border-color: transparent; color: var(--dim); padding-left: 4px; padding-right: 4px; }

.post-navigation .nav-links { display: flex; justify-content: space-between; gap: 24px; flex-wrap: wrap; }
.post-navigation .nav-previous,
.post-navigation .nav-next { max-width: 47%; }
.post-navigation .nav-next { margin-left: auto; text-align: right; }
.post-navigation a { font-family: var(--mono); font-size: 12px; letter-spacing: .04em; color: var(--fog); text-decoration: none; line-height: 1.45; }
.post-navigation a:hover { color: var(--amber); }

.sf-article__foot { margin-top: 48px; padding-top: 24px; border-top: 1px solid var(--rule); }
