/* Single post template (post.html). Everything else comes from design-system.css. Mobile-first.
   Phones: header, the at-a-glance card, the article, the share links, the author, the comments, and a floating Contents button.
   From 64em: three columns. A slim column of icons (Contents, then the share links) sticks on the left, the article is in the
   middle, the at-a-glance card with the price button sticks on the right. */

.article { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-5); padding-block: clamp(1.5rem, 4vw, 2.5rem) clamp(2.5rem, 6vw, 4.5rem); }
.article__body { min-width: 0; }
.article__crumbs { margin-bottom: var(--space-5); }
/* Affiliate notice between the breadcrumbs and the title: 11.8px, line height 1, a pale grey (owner's values), so it stays a footnote and does not compete with either. */
.article__crumbs--tight { margin-bottom: var(--space-3); }
.article__disclosure { max-width: none; margin: 0 0 5px; color: var(--text-quiet); font-size: var(--fs-200); line-height: 1; }   /* 5px is the owner's value */
.disclosure__link { color: inherit; }   /* the Learn more link takes the notice's color (owner request); it stays underlined */
/* The title is the page's one large type moment: bigger than the section headings (h2 is 38 px at most, the title 56 px at most),
   and still within three lines at every width. Phones start at the h3 size. */
.article__title { margin-bottom: var(--space-4); font-size: var(--fs-700); line-height: var(--lh-snug); }
.article__rail { display: grid; gap: var(--space-4); align-content: start; }
.article__toc { display: contents; }   /* phones: the floating Contents button is out of the flow and the share icons are hidden here */
@media (min-width: 40em) {
  .article__title { font-size: var(--fs-900); line-height: var(--lh-tight); }
}
@media (min-width: 64em) {
  .article {
    grid-template-columns: 3.5rem minmax(0, 1fr) clamp(15rem, 24vw, 19rem);
    column-gap: clamp(1.5rem, 3vw, 3rem);
  }
  .article__head { grid-column: 2; }
  .article__body { grid-column: 2; grid-row: 2; }
  /* Both side columns stay in view while the article scrolls. The right column scrolls inside itself when it is taller than the window;
     its padding and the matching negative margin leave room for the focus ring. The left column holds only icons, so it never scrolls. */
  .article__toc,
  .article__rail { grid-row: 1 / span 2; align-self: start; position: sticky; top: var(--space-5); }
  .article__rail { max-height: calc(100vh - var(--space-6)); margin: calc(var(--space-2) * -1); padding: var(--space-2); overflow-y: auto; }
  .article__toc { display: grid; grid-column: 1; gap: var(--space-2); justify-items: start; margin-top: calc(var(--space-3) * -1); }   /* the 48px Contents icon is centered on the breadcrumb line, not below it */
  .article__rail { grid-column: 3; }
}

/* Page template (page.html): the same layout as the post without the right-hand card: the icon column and one text column, centered.
   The lead is a statement in the heading font under the large title (after the Patreon and Discord story pages). */
.article__title--page { font-size: var(--fs-900); line-height: var(--lh-tight); }   /* page titles are short, so they take the full h1 size at every width */
.article__lead { max-width: 34ch; margin-bottom: var(--space-2); color: var(--text); font: var(--fw-regular) var(--fs-600) / var(--lh-snug) var(--font-heading); }
@media (min-width: 40em) {
  .article__lead { font-size: var(--fs-700); }
}
@media (min-width: 64em) {
  .article--page { grid-template-columns: 3.5rem minmax(0, 46rem); justify-content: center; }
}

/* Featured image under the byline: the site's own photo (450 px wide) cropped to a wide strip. It has a white background, which is blended into the page color so the image sits on the page without a box. */
.article__image { display: block; width: 100%; height: auto; aspect-ratio: 21 / 9; object-fit: cover; margin-top: var(--space-5); mix-blend-mode: multiply; }   /* multiply lets the photo's white background take the page color, so there is no box */

/* The article text fills the column, at the same width as the cards above it, in the larger body size so the lines stay a readable length. */
.prose--wide { max-width: none; font-size: var(--fs-500); }

/* Byline: who wrote it and when. Kept on the post page only (the cards carry no post meta). */
.byline { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-5); margin: 0 0 var(--space-3); color: var(--text-muted); font-size: 1rem; }

/* At a glance: the facts of the product as a term and a value, then the price button */
.glance { padding: var(--space-5); border-radius: var(--radius-l); }   /* the quiet tint comes from has-cream-deep-background-color in the markup */
.glance__title { margin-bottom: var(--space-4); font-size: var(--fs-600); }
.glance__list { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: var(--space-3) var(--space-4); margin: 0 0 var(--space-5); }
.glance__term { color: var(--text-muted); font-size: 1rem; font-weight: var(--fw-bold); }
.glance__value { margin: 0; font-size: 1rem; line-height: 1.4; }

/* Share links: brand icons with no background. Plain links to each network's share page (no scripts, no tracking);
   the Copy link button is hidden until js/article.js shows it. Each target is 44px. Hover turns the icon paprika and lifts it a little.
   Two copies: in the left column from 64em, after the article before it. */
.share__title { margin: 0 0 var(--space-1); color: var(--heading); font-weight: var(--fw-bold); }
.share__list { display: flex; flex-wrap: wrap; gap: 0; margin: 0 0 0 calc(var(--space-3) * -1); padding: 0; list-style: none; }
.share__link {
  display: grid;
  place-items: center;
  width: var(--target);
  height: var(--target);
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--heading);
  cursor: pointer;
  transition: color 0.2s ease, transform 0.2s var(--ease-out);
}
.share__list--stack { flex-direction: column; margin: 0; }
.share__icon { width: 1.375rem; height: 1.375rem; fill: currentColor; }
@media (hover: hover) {
  .share__link:hover { color: var(--link); transform: translateY(-2px) scale(1.08); }
}
.share__link:active { transform: none; }
.article__share--rail { display: none; }
.article__share--end { margin-top: var(--space-7); }
@media (min-width: 64em) {
  .article__share--rail { display: block; margin-top: var(--space-2); }
  .article__share--end { display: none; }
}

/* Contents: an icon that opens the list as a panel. Without JavaScript it is a plain list in a card (the .toc card from the design
   system). js/article.js adds .contents--float to the root and .contents__panel--popover to the panel, and shows the button.
   Phones: a round olive button floats at the bottom left once the article is in view, and the panel opens above it.
   From 64em: the button sits in the left column like the share icons, and the panel opens beside it.
   The panel fades and rises in; a tap outside, Escape, or a click on a link closes it (the script). */
.contents__button {
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--olive);
  color: var(--cream);
  box-shadow: var(--shadow-m);
  cursor: pointer;
  transition: background-color 0.2s ease, color 0.2s ease, transform 0.2s var(--ease-out);
}
.contents__button[aria-expanded="true"] { background: var(--paprika); }
.contents__icon { width: 1.375rem; height: 1.375rem; }
.contents--float {
  position: fixed;
  left: var(--gutter);
  bottom: var(--space-4);
  z-index: 40;
  opacity: 0;
  visibility: hidden;
  transform: translateY(0.75rem);
  transition: opacity 0.25s ease, transform 0.3s var(--ease-out), visibility 0s linear 0.3s;
}
.contents--shown { opacity: 1; visibility: visible; transform: none; transition: opacity 0.25s ease, transform 0.3s var(--ease-out), visibility 0s; }
.contents__panel--popover {
  position: absolute;
  left: 0;
  bottom: calc(100% + var(--space-2));
  z-index: 40;
  width: min(20rem, calc(100vw - var(--gutter) * 2));
  max-height: min(60vh, 24rem);
  overflow-y: auto;
  box-shadow: var(--shadow-m);
  opacity: 0;
  visibility: hidden;
  transform: translateY(0.5rem) scale(0.98);
  transform-origin: bottom left;
  transition: opacity 0.2s ease, transform 0.25s var(--ease-out), visibility 0s linear 0.25s;
}
@media (min-width: 64em) {
  .contents { position: relative; }
  .contents--float { position: relative; left: auto; bottom: auto; opacity: 1; visibility: visible; transform: none; transition: none; }
  .contents__button { background: transparent; color: var(--heading); box-shadow: none; }
  .contents__button[aria-expanded="true"] { background: transparent; color: var(--link); }
  .contents__panel--popover { left: calc(100% + var(--space-2)); bottom: auto; top: 0; transform: translateX(-0.5rem) scale(0.98); transform-origin: top left; }
}
@media (hover: hover) {
  .contents__button:hover { background: var(--paprika); }
}
@media (min-width: 64em) and (hover: hover) {
  .contents__button:hover { background: transparent; color: var(--link); transform: translateY(-2px) scale(1.08); }
}
.contents__panel--open { opacity: 1; visibility: visible; transform: none; transition: opacity 0.2s ease, transform 0.25s var(--ease-out), visibility 0s; }

/* Pros and cons in the post: plain lists with no box, fill or border, one above the other at every width, each under a Bitter title.
   The titles ("Pros", "Cons", "What we liked", "What we did not") carry the meaning, so the lists use a small muted dot instead of the
   + and minus icons, which the owner found too strong (one place where the "+ and minus marks" rule in CLAUDE.md is not followed). */
.proscons--stack { grid-template-columns: minmax(0, 1fr); gap: var(--space-6); }
.proscons__title--display { margin-bottom: var(--space-3); color: var(--heading); font: var(--fw-semibold) var(--fs-700) / var(--lh-snug) var(--font-heading); }
.proscons__list--plain { font-size: 1.0625rem; line-height: 1.5; }
.proscons__list--plain > li { padding-left: 1.5rem; }
.proscons__list--plain > li::before { content: ""; top: 0.6em; left: 0.4rem; width: 0.375rem; height: 0.375rem; border: 0; background: var(--text-muted); }

/* Short answer first: the verdict, then what we liked and did not. Plain text on the page, with no box or panel, so nothing competes with the review. */
.summary { margin-bottom: var(--space-7); }
.summary__title { margin-bottom: var(--space-3); font-size: var(--fs-800); }
.summary__text { margin-bottom: var(--space-5); font-size: var(--fs-500); }

/* Author box: a quiet-tint panel (has-cream-deep-background-color). No photo until the owner supplies a real one. */
.author { margin-top: var(--space-7); padding: var(--space-5); border-radius: var(--radius-l); }
.author__title { margin-bottom: var(--space-2); font-size: var(--fs-600); }
.author__bio { max-width: var(--measure); margin-bottom: var(--space-3); color: var(--text-muted); }

/* Previous and next post: two rows with an arrow */
.post-nav { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-3); margin-top: var(--space-5); }
.post-nav__link {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 4rem;
  padding: var(--space-4) var(--space-5);
  background: var(--cream-deep);
  border-radius: var(--radius);
  color: var(--heading);
  font: var(--fw-semibold) var(--fs-400) / var(--lh-snug) var(--font-heading);
  text-decoration: none;
}
.post-nav__link--prev::before { content: "\2190"; font-family: var(--font-body); color: var(--link); }
.post-nav__link--next { justify-content: space-between; text-align: right; }
.post-nav__link--next::after { content: "\2192"; font-family: var(--font-body); color: var(--link); }
@media (hover: hover) {
  .post-nav__link:hover { background: var(--highlight); }
}
@media (min-width: 40em) {
  .post-nav { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Comments. References (Mobbin): the New York Times and Meetup for the layout (name and time on one line, the text under it, a quiet
   Reply link; a reply indented with a vertical bar), Skillshare and Base44 for a small role badge on the author's reply. No avatars (no Gravatar
   requests), no votes, no boxes: comments are text on the page, 32 px apart. A reply is indented behind a 3 px bar (the same bar as the contents
   list); the author's reply has an olive bar and an Author badge, a reader's reply a steel bar. */
.comments { margin-top: var(--space-8); }
.comments__title { margin-bottom: var(--space-5); font-size: var(--fs-800); }
.comments__list { display: grid; gap: var(--space-6); margin: 0; padding: 0; list-style: none; }
.comment__head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-1) var(--space-2); margin-bottom: var(--space-1); }
.comment__author { color: var(--heading); font-weight: var(--fw-bold); }
.comment__time { color: var(--text-muted); font-size: var(--fs-300); }
.comment__time::before { content: "\00B7" / ""; margin-right: var(--space-2); }   /* a middle dot between the name and the time, decorative */
.comment__body > :last-child { margin-bottom: 0; }
.comment__reply {
  display: inline-flex;
  align-items: center;
  min-height: var(--target);
  color: var(--text-muted);
  font-size: 1rem;
  font-weight: var(--fw-semibold);
  text-decoration: none;
}
@media (hover: hover) {
  .comment__reply:hover { color: var(--link-hover); text-decoration: underline; }
}
.comment__replies { display: grid; gap: var(--space-4); margin: var(--space-2) 0 0 var(--space-2); padding: 0; list-style: none; }
.comment--reply { padding-left: var(--space-5); border-left: 3px solid var(--steel); }
.comment--author { border-left-color: var(--olive); }
@media (min-width: 40em) {
  .comment__replies { margin-left: var(--space-5); }
  .comment--reply { padding-left: var(--space-6); }
}

.comment-form { display: grid; gap: var(--space-4); margin-top: var(--space-5); padding: var(--space-5); border-radius: var(--radius-l); }
.comment-form__title { margin: 0; font-size: var(--fs-700); }
.comment-form__row { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-4); }
.comment-form__label { display: block; margin-bottom: var(--space-1); }
.comment-form__message { min-height: 9rem; resize: vertical; }
.comment-form__consent { display: flex; align-items: center; gap: var(--space-3); min-height: var(--target); font-weight: var(--fw-regular); }
.comment-form__check { flex: none; width: 1.5rem; height: 1.5rem; accent-color: var(--olive); }
.comment-form__note { margin: 0; color: var(--text-muted); font-size: var(--fs-300); }
.comment-form__submit { justify-self: start; }
@media (min-width: 40em) {
  .comment-form { padding: var(--space-6); }
  .comment-form__row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Build-script additions (2026-10-29), for the posts generated from the export. */
/* Featured image on a photo with no white background: the page's blend trick would darken it, so it keeps its colors and gets rounded corners; a wide 16:9 crop. */
.article__image--photo { aspect-ratio: 16 / 9; border-radius: var(--radius-l); mix-blend-mode: normal; }
/* At a glance with the owner's own highlight lines (the post's meta fields have text but no labels): a plain list of lines, no term and value pairs. */
.glance__list--lines { grid-template-columns: minmax(0, 1fr); padding: 0; list-style: none; }
.glance__line { margin: 0; font-size: 1rem; line-height: 1.4; }
