/* The blog's own layer over the Bloom brand tokens
   (COLOR_ANALYSIS_BLOG_SPEC.md Slice B).

   Hallmark - genre: editorial - macrostructure: Reading - theme: Bloom.

   Loaded by templates/blog/base.html after static/tokens.css. Only what the
   token file does not already define lives here; the brand scale is never
   copied, which is the rule the landing page's inline block follows for the
   same reason (two copies of a scale is how the plan table drifted).

   The masthead and colophon rules are the landing page's, reproduced here
   because that page keeps its CSS inline and there is no shared public
   stylesheet to import from. If a third public page appears, this file is
   where the shared chrome should be lifted to.

   One column, one measure, no grid: a reading page's job is the paragraph. */

:root {
  --measure: 66ch;
  --measure-narrow: 42rem;
  /* the tilted wire hanger for the masthead mark, -10deg baked into the path */
  --hanger-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cg transform='translate(-1.04 0) rotate(-10 12 12)' fill='none' stroke='black' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 10.2V7.4a1.9 1.9 0 0 1 3.8 0v.5'/%3E%3Cpath d='M12 10.2 3.6 18h16.8Z'/%3E%3C/g%3E%3C/svg%3E") center / contain no-repeat;
}

/* Not optional, and not decoration. Without it `.wrap`'s width:100% and its
   padding-inline ADD, so the page lays out 32px wider than the viewport on a
   phone. `overflow-x: clip` below then hides the overflow instead of scrolling,
   which turns the missing gutter into clipped words at the right edge - a
   defect that is invisible on a desktop and cuts every line short at 390px. */
*, *::before, *::after { box-sizing: border-box; }

html, body { overflow-x: clip; }
html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--color-paper);
  color: var(--color-ink);
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1.62;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

.wrap {
  width: 100%;
  max-width: var(--page-max);
  margin-inline: auto;
  padding-inline: var(--page-gutter);
}

/* ---------- masthead ---------- */
.mast {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-4); padding-block: var(--sp-5);
}
.masthead {
  display: inline-flex; align-items: center; gap: 0;
  color: var(--color-ink); text-decoration: none; min-height: 44px;
}
.masthead .petal {
  width: 1.1rem; height: 1.1rem; flex: none;
  background: var(--color-accent);
  margin-right: .5em;
  -webkit-mask: var(--hanger-mask);
  mask: var(--hanger-mask);
}
.masthead .script,
.masthead .caps {
  font-family: var(--font-wordmark); font-style: italic; font-weight: 600;
  font-size: var(--text-md); line-height: 1;
}
.masthead .script { margin-right: .26em; }

.mast__link {
  font-family: var(--font-display); font-size: var(--text-xs); font-weight: 500;
  letter-spacing: 0.1em; text-transform: uppercase; text-decoration: none;
  white-space: nowrap; color: var(--color-muted);
  display: inline-flex; align-items: center; gap: .45em; min-height: 44px;
  transition: color var(--dur-1) var(--ease-out);
}
.mast__link .arrow { transition: transform var(--dur-2) var(--ease-out); }
.mast__link:hover { color: var(--color-accent); }
.mast__link:hover .arrow { transform: translateX(3px); }

/* ---------- index ---------- */
.index-head { padding-block: var(--sp-7) var(--sp-6); max-width: var(--measure); }
.index-head h1 {
  font-family: var(--font-display); font-weight: 600; line-height: 1.08;
  font-size: clamp(2.05rem, 2.6vw + 1.05rem, 3.05rem);
  letter-spacing: -0.02em; margin: 0 0 var(--sp-4);
}
.lede { color: var(--color-muted); font-size: var(--text-md); margin: 0; }

.post-list { list-style: none; margin: 0; padding: 0; max-width: var(--measure); }
.post-card {
  padding-block: var(--sp-6);
  border-top: 1px solid var(--color-rule-soft);
}
.post-card__date {
  margin: 0 0 var(--sp-2);
  font-family: var(--font-display); font-size: var(--text-xs);
  letter-spacing: 0.09em; text-transform: uppercase; color: var(--color-neutral);
}
.post-card__title {
  font-family: var(--font-display); font-weight: 600; line-height: 1.18;
  font-size: var(--text-xl); letter-spacing: -0.015em; margin: 0 0 var(--sp-3);
}
.post-card__title a { color: var(--color-ink); text-decoration: none; }
.post-card__title a:hover { color: var(--color-accent); }
.post-card__desc { margin: 0 0 var(--sp-3); color: var(--color-muted); }
.post-card__more { margin: 0; }
.post-card__more a {
  font-family: var(--font-display); font-size: var(--text-xs); font-weight: 500;
  letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--color-accent); text-decoration: none;
  display: inline-flex; align-items: center; min-height: 44px;
}
.post-card__more a:hover { text-decoration: underline; }

/* ---------- a post ---------- */
.post { max-width: var(--measure-narrow); padding-block: var(--sp-6) var(--sp-7); }
.post__back { margin: 0 0 var(--sp-5); }
.post__back a {
  font-family: var(--font-display); font-size: var(--text-xs); font-weight: 500;
  letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--color-muted); text-decoration: none;
}
.post__back a:hover { color: var(--color-accent); }
.post__title {
  font-family: var(--font-display); font-weight: 600; line-height: 1.08;
  font-size: clamp(2.05rem, 2.6vw + 1.05rem, 3.05rem);
  letter-spacing: -0.02em; margin: 0 0 var(--sp-3);
}
.post__meta {
  margin: 0 0 var(--sp-6);
  font-family: var(--font-display); font-size: var(--text-xs);
  letter-spacing: 0.06em; color: var(--color-neutral);
  display: flex; flex-wrap: wrap; gap: .5em; align-items: baseline;
}
.post__byline { color: var(--color-muted); }

/* The rhythm of the page, and the ORDER of these three rules is the whole of
   it. The reset has to be a `> *` selector rather than `.post__body p`,
   because a `margin: 0` shorthand at higher specificity beats the margin-top
   below it no matter where it sits: with `.post__body p { margin: 0 }` the
   flow rule silently did nothing and every paragraph ran into the next one.
   Element selectors below only ever RAISE the gap, and they win on
   specificity, which is why no !important is needed here. */
.post__body > * { margin: 0; }
.post__body > * + * { margin-top: var(--sp-5); }
.post__body p { color: var(--color-ink); }
.post__body h2 {
  font-family: var(--font-display); font-weight: 600; line-height: 1.2;
  font-size: var(--text-xl); letter-spacing: -0.015em;
  margin-top: var(--sp-7);
}
.post__body h3 {
  font-family: var(--font-display); font-weight: 600; font-size: var(--text-md);
  margin-top: var(--sp-6);
}
.post__body ul, .post__body ol { padding-left: 1.3em; color: var(--color-ink); }
.post__body li + li { margin-top: var(--sp-2); }
.post__body a { color: var(--color-accent); text-underline-offset: 3px; }
.post__body strong { font-weight: 600; }

/* A quiet aside for the "this is a generic guide" label. It has to read as a
   caveat, not as decoration, so it sits on the paper tint with a rule. */
.note {
  background: var(--color-paper-3);
  border-left: 3px solid var(--color-accent);
  border-radius: 0 var(--r-tile) var(--r-tile) 0;
  padding: var(--sp-4) var(--sp-5);
  color: var(--color-muted);
  font-size: var(--text-xs);
  line-height: 1.75;
}
.note p { margin: 0; color: inherit; }
.note p + p { margin-top: var(--sp-3); }

/* ---------- the palette strip ---------- */
/* Twelve named colors. Every hex is printed beside its swatch on purpose: a
   reader who wants to match a garment needs the number, and a swatch with no
   number is a color claim nobody can check. */
.palette {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: var(--sp-3);
  grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
}
.palette li {
  border: 1px solid var(--color-rule-soft);
  border-radius: var(--r-tile);
  overflow: hidden;
  background: var(--color-paper-2);
}
.palette .chip { display: block; height: 4.5rem; }
.palette .label {
  display: block; padding: var(--sp-3);
  font-family: var(--font-display); font-size: var(--text-xs); line-height: 1.5;
}
.palette .label b { display: block; font-weight: 600; color: var(--color-ink); }
.palette .label span { color: var(--color-neutral); letter-spacing: 0.04em; }

/* ---------- closing call to action ---------- */
.post__cta {
  margin-top: var(--sp-8);
  padding: var(--sp-6);
  background: var(--color-paper-2);
  border: 1px solid var(--color-rule-soft);
  border-radius: var(--r-panel);
  max-width: var(--measure-narrow);
}
.post__cta h2 {
  font-family: var(--font-display); font-weight: 600; font-size: var(--text-md);
  margin: 0 0 var(--sp-3);
}
.post__cta p { margin: 0 0 var(--sp-4); color: var(--color-muted); }
.post__cta p:last-child { margin-bottom: 0; }

.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 48px; padding: 0 var(--sp-6);
  background: var(--color-accent); color: var(--color-on-accent);
  border-radius: var(--r-pill); text-decoration: none;
  font-family: var(--font-display); font-size: var(--text-xs); font-weight: 500;
  letter-spacing: 0.09em; text-transform: uppercase;
  transition: background var(--dur-1) var(--ease-out);
}
.btn:hover { background: var(--color-accent-2); }

/* ---------- colophon ---------- */
.colophon { padding-block: var(--sp-8) var(--sp-7); border-top: 1px solid var(--color-rule-soft); }
.colophon__mark { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4); flex-wrap: wrap; margin-bottom: var(--sp-6); }
.colophon__body { font-size: var(--text-xs); line-height: 1.85; color: var(--color-neutral); max-width: 68ch; }
.colophon__body b { color: var(--color-muted); font-weight: 500; }
.colophon__links { margin-top: var(--sp-5); display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4); }
.colophon__links a {
  font-size: var(--text-xs); text-decoration: none; color: var(--color-muted);
  white-space: nowrap; min-height: 44px; display: inline-flex; align-items: center;
  transition: color var(--dur-1) var(--ease-out);
}
.colophon__links a:hover { color: var(--color-accent); }
.colophon__contact { margin-top: var(--sp-4); font-size: var(--text-xs); color: var(--color-neutral); }
.colophon__contact a { color: var(--color-accent); }
.colophon__copy { margin-top: var(--sp-2); font-size: var(--text-xs); color: var(--color-neutral); }

:where(a):focus-visible, :where(button):focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
  border-radius: 4px;
}

/* --- Slice D: hubs, breadcrumbs, hero figure, FAQ, more-in-hub ------------
   Every one of these is a block that renders only when its data exists, so
   none of them can leave an empty heading or a dangling rule on a post that
   does not carry the key. */

.hub-strip {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  max-width: var(--measure);
  margin: 0 0 var(--sp-6);
}
.hub-strip__link {
  font-size: var(--text-sm);
  text-decoration: none;
  color: var(--color-ink);
  border: 1px solid var(--color-line);
  border-radius: 999px;
  padding: 0.35rem 0.85rem;
  background: var(--color-paper);
}
.hub-strip__link:hover { border-color: var(--color-accent); color: var(--color-accent); }

.post__crumbs {
  font-size: var(--text-sm);
  color: var(--color-muted);
  margin: 0 0 var(--sp-3);
}
.post__crumbs a { color: var(--color-muted); text-decoration: none; }
.post__crumbs a:hover { color: var(--color-accent); }

/* The hero is the article's own illustration. It is NOT the social card: the
   palette card carries a wordmark footer and belongs in a share preview. */
.post__hero { margin: 0 0 var(--sp-6); max-width: var(--measure); }
.post__hero img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius-md, 10px);
}

.post__faq { max-width: var(--measure); margin: var(--sp-7) 0 0; }
.post__faq h2 { font-size: var(--text-lg); margin: 0 0 var(--sp-4); }
.post__faq dt { font-weight: 600; margin-top: var(--sp-4); }
.post__faq dd { margin: var(--sp-2) 0 0; color: var(--color-muted); }

.post__more { max-width: var(--measure); margin: var(--sp-7) 0 0; }
.post__more h2 { font-size: var(--text-lg); margin: 0 0 var(--sp-3); }
.post__more ul { list-style: none; margin: 0; padding: 0; }
.post__more li { margin: var(--sp-2) 0; }
.post__more a { color: var(--color-ink); }
.post__more a:hover { color: var(--color-accent); }

.post__byline a { color: inherit; }
.post__byline a:hover { color: var(--color-accent); }

/* /about: the illustrated avatar D2 rules, beside the page title. Inline SVG,
   never a photograph. */
.about__head { display: flex; align-items: center; gap: var(--sp-4); margin: 0 0 var(--sp-5); }
.about__head .post__title { margin: 0; }
.about__avatar {
  flex: 0 0 auto;
  display: block;
  width: 72px;
  height: 72px;
  border-radius: 50%;
  border: 1px solid var(--color-line);
  overflow: hidden;
}
.about__avatar svg { display: block; width: 100%; height: 100%; }
@media (max-width: 480px) {
  .about__head { gap: var(--sp-3); }
  .about__avatar { width: 56px; height: 56px; }
}

/* --- The featured image on an index or hub card (owner ruling 2026-08-25) ---
   Every post carries one, so the card becomes a two-part block: picture, then
   text. A post with no hero keeps the old text-only card, which is what the
   fallback below is for rather than a hole where a picture should be. */
.post-card--has-image { display: grid; grid-template-columns: 240px 1fr; gap: var(--sp-5); align-items: start; }
.post-card__media { display: block; border-radius: var(--radius-md, 10px); overflow: hidden; }
.post-card__media img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; }
.post-card__text { min-width: 0; }
@media (max-width: 620px) {
  /* The picture goes full width above the text on a phone: a 240px thumbnail
     beside two lines of title is smaller than either deserves at that width. */
  .post-card--has-image { grid-template-columns: 1fr; gap: var(--sp-3); }
}

/* The second in-body image. Same frame as the hero, so a post reads as one
   piece rather than as a header plus an attachment. */
.post__figure { margin: var(--sp-7) 0 0; max-width: var(--measure); }
.post__figure img { display: block; width: 100%; height: auto; border-radius: var(--radius-md, 10px); }

/* ---------- the season hubs (SEO_TOOLS_AND_AUTHORITY_SPEC.md T1) ---------- */
/* The hub reuses .palette, .post-list and .post__cta unchanged. What is new
   is the three colour stories and the two link lists, which the blog posts
   have no equivalent of. */
.season-hub { max-width: var(--measure); }

.vh {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.season-stories {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: var(--sp-5);
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
}
.season-story {
  border: 1px solid var(--color-rule-soft);
  border-radius: var(--r-tile);
  overflow: hidden;
  background: var(--color-paper-2);
  padding-bottom: var(--sp-4);
}
.season-story h3 {
  font-family: var(--font-display); font-size: var(--text-sm); font-weight: 600;
  margin: var(--sp-4) var(--sp-4) var(--sp-2);
}
.season-story p { margin: 0 var(--sp-4); color: var(--color-muted); }
/* Four flat bands, edge to edge, so a story reads as a colour combination
   before it reads as a card. The hex rides along in a visually hidden span:
   the strip is decorative beside a note that names the same colours in
   words. */
.season-story__chips {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
}
.season-story__chips .chip { display: block; height: 3.5rem; }

.season-links { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-2); }
.season-links a { color: var(--color-ink); }
.season-links--dense {
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  font-size: var(--text-xs);
}

.season-hub__note {
  margin-top: var(--sp-6);
  color: var(--color-muted);
  font-size: var(--text-xs);
}
