/*
Theme Name: Living the Lineage
Theme URI: https://livingthelineage.com
Author: Eric Grey
Author URI: https://livingthelineage.com
Description: Block theme for Living the Lineage — reading notes from a living lineage of classical Chinese medicine. A pared-down sibling of the Watershed Wellness block theme: same construction, one third the surface area.
Version: 0.1.0
Requires at least: 6.7
Tested up to: 7.1
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: ltl-block-theme
Tags: blog, one-column, custom-colors, custom-menu, block-templates, full-site-editing
*/

/*
Nearly all styling belongs in theme.json rather than here. This file carries the theme
header above, plus the rules theme.json cannot express.

PROVENANCE. Most of what follows is ported from ~/Sites/ww-block-theme/theme/style.css,
where each rule was arrived at by measuring a real failure on the Watershed site. The
comments explaining WHY are kept, because the reasoning is the thing that stops a future
session "tidying" a rule back into the bug it fixes. Rules that were specific to Watershed
(SeedProd compatibility, wave dividers, accordions, service cards, hours tables) are gone.
*/

/*--------------------------------------------------------------
Links and rhythm in content
--------------------------------------------------------------*/

.wp-block-post-content a:where(:not(.wp-element-button)),
.entry-content a:where(:not(.wp-element-button)) {
	text-decoration: underline;
}

/* Reading rhythm. This is a notes site, so paragraphs get a full line between them and a
   heading groups with the text it introduces rather than floating between two sections.

   WW learned this the hard way: its first no-white-stripe fix was
   `.wp-block-post-content > * + * { margin-block-start: 0 }`, which killed the gap between
   EVERY pair of blocks and made ordinary prose unreadable. The stripe problem is a
   full-bleed problem only, so it is fixed below with a narrower selector and prose keeps
   its rhythm. */
.wp-block-post-content > * + * {
	margin-block-start: 24px;
}

.wp-block-post-content > p + p {
	margin-block-start: 1.6em;
}

.wp-block-post-content > * + :where(h2, h3, h4) {
	margin-block-start: 2.2em;
}

.wp-block-post-content > :where(h2, h3, h4) + * {
	margin-block-start: 0.6em;
}

/* Never a gap above a full-bleed band, or between one and whatever follows it — that gap
   is not space, it is a window onto the page background, and it reads as an unexplained
   white stripe. Higher specificity than the rhythm rules above, deliberately.

   GENERAL RULE FOR THIS THEME: between full-bleed sections, use PADDING. A margin there
   will always show through. */
.wp-block-post-content > .alignfull,
.wp-block-post-content > .alignfull + * {
	margin-block-start: 0;
}

/* A full-bleed block escapes the root gutter, so it has to put one back. Without this the
   inner row runs to 100% on a narrow screen and text sits flush against the glass. */
.wp-block-post-content > .alignfull {
	padding-left: clamp(16px, 4vw, 28px);
	padding-right: clamp(16px, 4vw, 28px);
}

/* Same block gap, one level up: the root layout puts 24px between header, main and footer.
   Where those carry different backgrounds — and the nav strip and the footer are both navy
   against a paper page — that gap shows the page through as a stripe. */
.wp-site-blocks > header,
.wp-site-blocks > main,
.wp-site-blocks > footer {
	margin-block-start: 0;
}

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

/* The header owns a stacking context above the page, so an open dropdown is never painted
   over by anything that comes later in document order. */
.ltl-header {
	position: relative;
	z-index: 100;
}

/* The photograph of Dr. Zeng reading Eric's pulse.

   The masthead has no band colour: it is the page's own paper, so the cut-out's removed
   background shows the paper through it and the two of them sit directly on the page with
   no box around them. That is the whole reason to use a cut-out rather than a rectangle.
   (It was navy first. Jisho, 2026-09-05: "eliminate the blue band and just let the
   background of the header be white... I think that would make the image look better." He
   was right — on navy it read as a photograph pasted into a header, on paper it reads as
   part of the page.)

   The width is capped rather than left to the image's own 1897x1246. Uncapped it filled
   most of a laptop screen ("WAY too big", 2026-09-04). object-fit is not used: the cut-out
   has meaningful transparent margins and cropping them changes the composition. */
.ltl-masthead__photo img {
	display: block;
	width: 100%;
	max-width: 416px;
	height: auto;
	margin-left: auto;
	margin-right: 0;
	margin-bottom: 0;

	/* The cut-out ends in a hard horizontal line across the table, and against a colour band
	   that line could be hidden by putting it on the band's edge. There is no edge any more,
	   so it would simply sit on the paper looking torn. Fading the last sixth of the image
	   into transparency dissolves the table into the page instead. */
	-webkit-mask-image: linear-gradient(to bottom, #000 82%, transparent 100%);
	mask-image: linear-gradient(to bottom, #000 82%, transparent 100%);
}

.ltl-masthead__photo figure {
	margin-bottom: 0;
}

/* The three-panel variant: Tian, Zeng, and Eric with Arnaud, knitted into one image.

   Built by bin/build-lineage-strip.py from three Eagle originals spanning about eighty
   years. The knitting is a single warm duotone keyed to this site's own paper and navy,
   panels that overlap with gradient seams so each face emerges from the one before it,
   and the same bottom fade the single-photograph masthead gets.

   ⚠️ The fade is BAKED INTO the file's alpha channel, so this variant must NOT also take
   the CSS mask above — two fades stacked start the dissolve halfway up Zeng's face. That
   is the whole reason this is a modifier class rather than a change to the base rule:
   swapping the single photograph back in is then one edit to header.html, and its mask
   is still there waiting for it. */
.ltl-masthead__photo--strip img {
	max-width: 700px;
	-webkit-mask-image: none;
	mask-image: none;
}

/* Title in the navy, tagline in ink beneath it. The navy is the site's one accent and it
   earns its keep by appearing in few places: the title, the nav strip, the footer, and the
   headings inside a note. */
.ltl-masthead__text .wp-block-site-title a,
.ltl-masthead__text .wp-block-site-title a:hover {
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
}

.ltl-masthead__text .wp-block-site-title {
	font-family: var(--wp--preset--font-family--brand);
	font-size: 44px;
	font-weight: 700;
	line-height: 1.1;
	letter-spacing: -0.01em;
	margin: 0;
}

.ltl-masthead__text .wp-block-site-tagline {
	color: var(--wp--preset--color--ink);
	font-size: 18px;
	line-height: 1.45;
	margin: 10px 0 0;
	max-width: 30em;
}

/*--------------------------------------------------------------
Navigation
--------------------------------------------------------------*/

/* The nav is a navy strip with white text. It gives the masthead a floor to sit on, and it
   is where the photograph's faded lower edge comes to rest — the mask is fully transparent
   by then, so the last band of the image is paper and the navy starts cleanly underneath it
   with no visible cut.

   Hairlines are gone: the navy is its own definition and a rule on top of it would be a
   second one saying the same thing. */
.ltl-nav {
	background-color: var(--wp--preset--color--contrast);
}

.ltl-nav .wp-block-navigation {
	--wp--style--block-gap: 0;
}

/* Colour set on the STRIP, not only on the links.

   Core ships `.wp-block-navigation .wp-block-navigation-item__content { color: inherit }`,
   which is three classes. A plain `.ltl-nav .wp-block-navigation a` is two classes and an
   element, so core wins and the links inherit whatever the strip inherits — which was the
   page's ink, rendering near-black on navy. Measured: rgb(32, 31, 28).

   Setting the colour on `.ltl-nav` makes core's `inherit` resolve to white on its own, which
   is the fix rather than a fight. The explicit rules below still carry it, at three classes
   plus an element so they beat core outright, because hover has to win too. */
.ltl-nav {
	color: #ffffff;
}

.ltl-nav .wp-block-navigation a,
.ltl-nav .wp-block-navigation a.wp-block-navigation-item__content {
	color: #ffffff;
	text-decoration: none;
}

.ltl-nav .wp-block-navigation a:hover,
.ltl-nav .wp-block-navigation a:focus,
.ltl-nav .wp-block-navigation a.wp-block-navigation-item__content:hover,
.ltl-nav .wp-block-navigation a.wp-block-navigation-item__content:focus {
	/* Sand, Watershed's own hover tone. A literal rather than a token because nothing else
	   on this site uses it and the palette is deliberately short. */
	color: #d9ba71;
	text-decoration: underline;
}

.ltl-nav .wp-block-navigation .wp-block-navigation-item {
	padding: 0 2px;
}

.ltl-nav .wp-block-navigation__responsive-container-open,
.ltl-nav .wp-block-navigation__responsive-container-close {
	color: #ffffff;
}

/* Never let a nav label break mid-word, at any width. Four uppercase items is not many,
   but "GET UPDATES" is the one that would split. */
.wp-block-navigation-item__label {
	word-break: keep-all;
	overflow-wrap: normal;
}

/*--------------------------------------------------------------
The note list
--------------------------------------------------------------*/

/* Cards, with production Watershed's exact shadow and padding. Jisho on the WW blog index:
   "each blog post is in a kind of box with some shadowing on it, and I like that look". */
.ltl-notes .wp-block-post-template > li {
	background-color: var(--wp--preset--color--white);
	padding: 22px;
	box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.14);
}

.ltl-notes .wp-block-post-title {
	margin-top: 0;
}

.ltl-notes .wp-block-post-title a {
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
}

.ltl-notes .wp-block-post-title a:hover {
	color: var(--wp--preset--color--linkblue);
	text-decoration: underline;
}

/* A post with no featured image should not leave a hole where one would have been. */
.ltl-notes .wp-block-post-featured-image:empty {
	display: none;
}

/* Featured image on a single note. Capped, because the image illustrates a piece of writing
   and is not the point of the page — an uncapped tall scroll at the wide 1100px measure
   pushed the first line of text a full screen down. Carried as its own class rather than a
   :not() against the card grid, so the two cases never have to be told apart by selector. */
.ltl-hero-image img {
	max-height: 460px;
	width: 100%;
	object-fit: cover;
	object-position: center;
}

/* Titles run one to three lines, which shifts every excerpt below them and leaves the row
   ragged. Reserving two lines lands them on the same baseline and costs nothing on the
   posts that already use two. The em figure tracks the title's own line-height rather than
   hard-coding pixels. */
.ltl-notes .wp-block-post-title {
	min-height: calc(2 * 1.2em);
}

/*--------------------------------------------------------------
Classical text with its translation beneath — the one custom component
--------------------------------------------------------------*/

/* The pattern this theme exists to set well: a line of the Shanghan Lun or Jingui Yaolue,
   then its rendering, then a note. Characters at a size that can actually be read rather
   than at body size, the translation subordinate but not apologetic.

   Registered as a block pattern (patterns/classical-passage.php) so it inserts as ordinary
   core blocks — a group, a paragraph, a paragraph. Nothing here needs remembering how to
   drive a page builder. */
.ltl-passage {
	border-left: 3px solid var(--wp--preset--color--gold);
	padding: 4px 0 4px 22px;
	margin-block: 2em;
}

.ltl-passage__han {
	font-family: var(--wp--preset--font-family--han);
	font-size: 25px;
	line-height: 1.9;
	color: var(--wp--preset--color--contrast);
	margin: 0;
}

.ltl-passage__trans {
	font-size: 18px;
	line-height: 1.65;
	margin: 0.7em 0 0;
}

.ltl-passage__cite {
	font-family: var(--wp--preset--font-family--heading);
	font-size: 15px;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	color: var(--wp--preset--color--muted);
	margin: 0.9em 0 0;
}

/* Inline characters in running prose — 桂枝湯 (Guìzhī Tāng) will appear constantly, and at
   body size against Latin text they set too small to read. A shade larger, with the serif
   face, and no extra weight. */
.ltl-han,
.wp-block-post-content :lang(zh) {
	font-family: var(--wp--preset--font-family--han);
	font-size: 1.12em;
	line-height: 1.5;
}

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

.ltl-footer a {
	color: #ffffff;
	text-decoration: none;
}

.ltl-footer a:hover {
	text-decoration: underline;
}

/*--------------------------------------------------------------
The colophon — 脈 at the foot of the page

A seal belongs at the END of a piece of work, not at the head of it. That is where it goes
on a painting or a piece of calligraphy, and it is why this ended up in the footer rather
than in the masthead: it reads as the page being SIGNED, where a mark up beside the title
would have read as branding. Jisho's suggestion, 2026-09-05, and it was the better answer.

It is live text in the `han` family, not the favicon PNG. Text stays sharp at any pixel
density, costs no request, and follows the font stack the theme already loads — the seal
square would have been invisible here anyway, because its field is the same navy as this
band.

⚠️ The gold is #D9BE7C, NOT the theme's `gold` token #A38643. Same reason as the site icon:
the token is built to be read on paper so it is dark, and on this navy it measures 3.31:1,
which is under the 4.5:1 floor and looks muddy. #D9BE7C is 6.35:1. Do not swap it for
var(--wp--preset--color--gold) to tidy the palette; that would fail contrast on the one
element whose whole job is to be a small quiet mark.

The character is hidden from screen readers and paired with a glossed label, so a reader
hears "Mai - pulse, and lineage" instead of an unannounced CJK glyph.
--------------------------------------------------------------*/
.ltl-colophon {
	margin: 30px 0 0;
	text-align: center;
	font-family: var(--wp--preset--font-family--han);
	font-size: 34px;
	line-height: 1;
	color: #D9BE7C;
}

.ltl-footer__divider {
	padding: 0 10px;
}

.ltl-footer__search .wp-block-search__input {
	height: 45px;
	border: 0;
	border-radius: 0;
	background: #ffffff;
	color: var(--wp--preset--color--contrast);
	padding-left: 1rem;
}

.ltl-footer__search .wp-block-search__button {
	height: 45px;
	margin: 0;
	border: 0;
	border-radius: 0;
	background: var(--wp--preset--color--gold);
	color: #ffffff;
	padding: 0 0.75rem;
}

.ltl-footer__search .wp-block-search__button svg {
	fill: currentColor;
}

/*--------------------------------------------------------------
Contrast — the cover block's white-text default

WordPress core ships:
    :where(.wp-block-cover:not(.has-text-color)) { color: #fff }

That assumes a cover sits over a dark, dimmed photograph. Any cover here that uses dimRatio 0
over a light image would inherit WHITE and become unreadable — the root cause of a whole class
of contrast bug on the Watershed site. Default cover text to the deep blue instead; a band
that genuinely wants white sets it explicitly and still wins, because has-text-color beats this.
--------------------------------------------------------------*/

.wp-block-cover:not(.has-text-color),
.wp-block-cover:not(.has-text-color)
	:where(h1, h2, h3, h4, h5, h6, p, li, .wp-block-heading):not(.has-text-color) {
	color: var(--wp--preset--color--contrast);
}

/* SeedProd's background rule is `center top`; WordPress's cover block defaults its image to
   object-position 50% 50%. On a tall photograph those show entirely different slices, which
   is how text that sits legibly over sky ends up over dark water. Anchor to the top. */
.wp-block-cover .wp-block-cover__image-background,
.wp-block-cover video.wp-block-cover__video-background {
	object-position: center top;
}

/*--------------------------------------------------------------
Utility
--------------------------------------------------------------*/

/* A page whose visible top element is not its title still needs an h1 for screen readers
   and search engines. */
.ltl-sr-only {
	position: absolute !important;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

.ltl-rule {
	margin-inline: auto;
	border: 0;
	border-top: 1px solid var(--wp--preset--color--line);
	width: 100%;
}

.wp-element-button,
.wp-block-button__link {
	font-size: 17px;
	font-weight: 700;
}

/*--------------------------------------------------------------
Responsive
--------------------------------------------------------------*/

@media (max-width: 899px) {
	/* The masthead stacks: text above the photograph, both centred. Side by side, the
	   photograph is squeezed to a width where neither face is legible. */
	.ltl-masthead .wp-block-columns {
		flex-wrap: wrap !important;
	}

	.ltl-masthead .wp-block-column {
		flex-basis: 100% !important;
		width: 100% !important;
	}

	.ltl-masthead__photo img {
		margin-left: auto;
		margin-right: auto;
		max-width: 360px;
	}

	.ltl-masthead__text {
		text-align: center;
	}

	.ltl-masthead__text .wp-block-site-tagline {
		margin-inline: auto;
	}

	/* Core only swaps the navigation for its hamburger below 600px, which is far too late
	   for uppercase multi-word items — they wrap and break mid-word between roughly 600 and
	   900. Force the overlay by re-asserting core's own two rules in the other direction. */
	.ltl-nav .wp-block-navigation__responsive-container-open:not(.always-shown) {
		display: flex !important;
	}

	/* ...but hide it once the menu IS open, or the hamburger sits alongside the close X and
	   both do the same thing. WordPress puts has-modal-open on <html> while the panel is
	   open, which is a plain ancestor class, so no :has() is needed. */
	html.has-modal-open .ltl-nav .wp-block-navigation__responsive-container-open {
		display: none !important;
	}

	.ltl-nav .wp-block-navigation__responsive-container:not(.hidden-by-default):not(.is-menu-open) {
		display: none !important;
	}

	.ltl-nav .wp-block-navigation {
		justify-content: center !important;
	}

	.ltl-nav .wp-block-navigation__responsive-container-open,
	.ltl-nav .wp-block-navigation__responsive-container-close {
		font-size: 28px !important;
	}

	/* The panel itself: inline and full width, page still visible below it. */
	.ltl-nav .wp-block-navigation__responsive-container.is-menu-open {
		position: static;
		height: auto;
		max-height: none;
		width: 100%;
		padding: 0 0 20px;
		background-color: var(--wp--preset--color--contrast);
		overflow: visible;
		z-index: auto;
	}

	/* Core paints the open overlay's links from its own theme colours, which on a navy panel
	   would be navy on navy. */
	.ltl-nav .wp-block-navigation__responsive-container.is-menu-open a {
		color: #ffffff !important;
	}

	.ltl-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-dialog {
		position: static;
	}

	.ltl-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-close {
		position: static;
		display: block;
		margin: 4px auto 10px;
	}

	.ltl-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container {
		align-items: center !important;
		width: 100%;
	}

	/* Full-bleed bands carry large desktop padding so their heights read right on a wide
	   screen. That padding is dead space once the content stacks. */
	.ltl-band {
		padding-top: 48px !important;
		padding-bottom: 48px !important;
	}

	/* The masthead is the exception: its bottom edge is where the photograph rests, and it
	   was never padding in the first place. */
	.ltl-masthead {
		padding-bottom: 0 !important;
	}
}

/* The note grid is two across on a desktop and one on a phone. Core's grid layout emits a
   fixed `repeat(2, minmax(0, 1fr))` from the block's columnCount, which does not respond to
   width on its own -- at 430px that left two cards of about 190px each with the titles
   breaking every second word. */
@media (max-width: 781px) {
	.ltl-notes .wp-block-post-template.is-layout-grid {
		grid-template-columns: 1fr !important;
	}
}

@media (max-width: 599px) {
	.ltl-masthead__text .wp-block-site-title {
		font-size: 34px;
	}

	.ltl-masthead__text .wp-block-site-tagline {
		font-size: 17px;
	}

	.ltl-passage__han {
		font-size: 22px;
	}
}

@media (max-width: 480px) {
	body {
		font-size: 17px;
	}
}

/*--------------------------------------------------------------
The interest form
--------------------------------------------------------------*/

.ltl-form__row {
	margin-block: 1.1em;
}

.ltl-form label {
	display: block;
	font-family: var(--wp--preset--font-family--heading);
	font-size: 15px;
	letter-spacing: 0.03em;
	color: var(--wp--preset--color--muted);
	margin-bottom: 5px;
}

.ltl-form input[type="text"],
.ltl-form input[type="email"],
.ltl-form textarea {
	width: 100%;
	max-width: 30rem;
	padding: 11px 13px;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: 3px;
	background: var(--wp--preset--color--white);
	font-family: var(--wp--preset--font-family--body);
	font-size: 17px;
	color: var(--wp--preset--color--ink);
}

.ltl-form input:focus,
.ltl-form textarea:focus {
	outline: 2px solid var(--wp--preset--color--contrast);
	outline-offset: 1px;
}

/* The honeypot. Hidden from people without `display:none`, which some bots check for, and
   kept out of the tab order and off screen readers by the markup rather than by CSS alone. */
.ltl-form__hp {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

.ltl-form__ok,
.ltl-form__err {
	border-left: 3px solid var(--wp--preset--color--gold);
	padding: 2px 0 2px 18px;
}

.ltl-form__err {
	border-left-color: #c95426;
}
