/* =============================================================================
 * Heron product page.
 *
 * Built 2026-08-27 from the v6 merge of a five-way redesign; the working
 * versions and the reasoning live in artifacts/heron-page-redesign/.
 * The page is set to the same specification as
 * Heron's own document canvas, with the measure, leading, type scale,
 * hairlines and single ochre accent lifted from src/themes/shallows.css and
 * src/styles/markdown.css rather than invented for the web. Where the page
 * shows a Markdown construct (frontmatter, a table, a task list, an alert,
 * a code block, footnotes) it is styled the way the app styles it.
 *
 * The frame to hold in mind is that the page is a Heron *window*, not a
 * Heron *file*: topbar, then what the app shows with nothing open (the
 * Welcome lockup), then the document. That is why the masthead sits above
 * the frontmatter rather than inside the prose.
 *
 * Three system rules, stated once here so they stay rules:
 *   1. ONE GROUND. Every screenshot sits on the same mist plate with the
 *      same hairline. The hero gets its weight from scale, never from a
 *      different colour. No dark bands.
 *   2. THREE RADII. 4px, 6px, 10px. Nothing else.
 *   3. OCHRE MEANS BUY. The accent fills the purchase control wherever it
 *      appears and nothing else, so its meaning is learnable rather than
 *      decorative. The trial is the same control unfilled. Never ochre text.
 *      It is also the focus ring, which is what the design system reserves
 *      the accent for.
 * ========================================================================== */

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 650;
  font-display: swap;
  src: url('fonts/inter.woff2') format('woff2');
}

@font-face {
  font-family: 'Source Serif 4';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('fonts/source-serif.woff2') format('woff2');
}

/* ---------- Tokens: the Shallows theme, verbatim ---------- */

:root {
  /* Surfaces */
  --bg-app: #f4f3ef;          /* Paper */
  --bg-sidebar: #eceeef;
  --bg-code: #eaedee;

  /* Lines */
  --border: #dbe0e2;

  /* Text */
  --text: #2e3a42;            /* Slate */
  /* Deliberately NOT shallows.css's #808a91. There it dresses chrome at
     small sizes; here it sets caption and footnote prose, where 3.17:1 on
     Paper fails AA. This is 4.96:1 on Paper and 4.73:1 on the footer. */
  --text-muted: #626a70;
  --heading: #232c33;
  --body-color: rgba(46, 58, 66, 0.88);
  --code-text: #2e3a42;
  --brand-ink: #31404e;       /* the fill baked into the standing mark */

  /* Accent. Ochre, deepened to clear contrast, exactly as the theme does:
     the logo sheet's #b56d2a carries only 4.10:1 under a white label, under
     the AA floor. #a3641f clears it at 4.78:1. Same family, real contrast. */
  --accent: #a3641f;
  --accent-hover: #8a5318;
  --accent-contrast: #ffffff;
  --link: #4a6b85;
  --selection: #f0dfc6;

  /* Frontmatter plate */
  --frontmatter-bg: #edeef0;
  --frontmatter-border: #dde2e5;

  /* Alerts */
  --alert-note: #3b6fe0;

  /* Code tokens */
  --tok-keyword: #0550ae;
  --tok-string: #0a7d33;
  --tok-class: #953800;
  --tok-punctuation: #57606a;

  /* Screenshot ground. Heron's canvas is Paper and so is this page, so a
     screenshot dropped straight on the background dissolves into it. It gets
     the treatment the app gives an embedded block: a faint tint and a
     hairline, never a shadow. ONE ground, at every size. */
  --plate: #e6e8ea;           /* Mist */
  --plate-border: #d7dcdf;
  --plate-inner: rgba(46, 58, 66, 0.16);

  --font-body: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --font-heading: 'Source Serif 4', Charter, Georgia, serif;
  --font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;

  --measure: 680px;   /* the app's 760px canvas less its 48px side padding */
  --bleed: 240px;     /* how far a figure may step outside the measure */
}

* { box-sizing: border-box; }

html {
  background: var(--bg-app);
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--bg-app);
  color: var(--body-color);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.75;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

::selection { background: var(--selection); color: var(--text); }

img { display: block; max-width: 100%; height: auto; }

a { color: var(--link); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

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

/* =============================================================================
 * Chrome
 * ========================================================================== */

.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--bg-app);
  border-bottom: 1px solid var(--border);
}

.topbar__inner {
  width: min(100% - 40px, 1160px);   /* = 240 + 680 + 240, the wide track */
  min-height: 58px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 28px;
}

.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  margin-right: auto;
  color: var(--heading);
  text-decoration: none;
}

.wordmark__icon {
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  border-radius: 6px;
  background: #5c6f7d;
}

.wordmark__icon img {
  width: 17px;
  height: 21px;
  object-fit: contain;
  filter: brightness(0) invert(1);
}

.wordmark__text {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 19px;
  line-height: 1;
}

.topbar__nav {
  display: flex;
  align-items: center;
  gap: 22px;
}

.topbar__nav a {
  color: var(--text-muted);
  text-decoration: none;
  font-size: 13px;
  font-weight: 500;
}

.topbar__nav a:hover { color: var(--text); }

/* The two chrome actions travel together and stay together at every width. */
.topbar__cta {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* ---------- Buttons ----------
   The filled ochre button appears exactly once on the page, at the price.
   The topbar's persistent buy affordance is the same control unfilled, so
   the page never carries two ochre fills at once. */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 46px;
  padding: 0 22px;
  border: 1px solid var(--accent);
  border-radius: 6px;
  background: var(--accent);
  color: var(--accent-contrast);
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 600;
  line-height: 1;
  text-decoration: none;
  transition: background 0.12s ease, border-color 0.12s ease;
}

.btn:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.btn:focus-visible { outline-color: var(--text); outline-offset: 3px; }

.btn--ghost {
  border-color: var(--border);
  background: transparent;
  color: var(--text);
  transition: border-color 0.12s ease, background 0.12s ease;
}

.btn--sm {
  min-height: 34px;
  padding: 0 14px;
  font-size: 13px;
  white-space: nowrap;
}

.btn--ghost:hover {
  background: var(--bg-sidebar);
  border-color: var(--text-muted);
}

.btn--ghost span { color: var(--text-muted); }

/* =============================================================================
 * The document column
 *
 * A five-track grid: gutter, bleed, measure, bleed, gutter. Prose sits in the
 * measure. A figure that needs the room steps out into the bleed tracks and
 * stays centred on the same spine.
 * ========================================================================== */

.doc {
  display: grid;
  grid-template-columns:
    [full-start] minmax(20px, 1fr)
    [wide-start] minmax(0, var(--bleed))
    [col-start] min(100% - 40px, var(--measure)) [col-end]
    minmax(0, var(--bleed)) [wide-end]
    minmax(20px, 1fr) [full-end];
  padding: 44px 0 96px;
}

.doc > * { grid-column: col-start / col-end; }
.doc > .wide { grid-column: wide-start / wide-end; }

/* ---------- The masthead: the Welcome lockup, as live text ----------
   Mark, serif wordmark, letterspaced descriptor. The app's empty state and the
   logo sheet stack these vertically; this is the horizontal arrangement of the
   same three parts, with the mark spanning both text lines. Left-ranged, like
   everything else here. If the app's Welcome screen is ever restyled, these
   two should be reconciled so the brand has one lockup, not two. */

/* A horizontal lockup: the mark stands to the left and spans both text lines.
   The mark tracks the wordmark's clamp at ~1.37x, which is what keeps it the
   height of the two lines together at every width. */
.masthead {
  display: flex;
  align-items: center;
  gap: clamp(16px, 1.8vw, 24px);
  margin: 0 0 34px;
}

.masthead__mark {
  flex: none;
  width: auto;
  height: clamp(71px, 8.2vw, 104px);   /* artwork is 675 x 969 */
}

.doc .masthead__name {
  margin: 0;
  color: var(--heading);
  font-family: var(--font-heading);
  font-weight: 400;
  font-size: clamp(52px, 6vw, 76px);
  line-height: 0.92;
  letter-spacing: -0.045em;
}

.doc .masthead__desc {
  margin: 9px 0 0;
  color: var(--text-muted);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

/* ---------- Typography, straight off the theme ----------
   Two scales, which is how the app splits it. The document runs on em against
   a 17px root: 0.76 / 0.82 / 0.86 / 0.88 / 0.94 / 1 / 1.24 / 1.5 / 1.75 / 2.5,
   with two responsive overrides reusing values from it. Chrome runs on px
   (11 / 13 / 15 / 17 / 19) because it is UI, not prose. The masthead's clamp
   is the single exception: it is brand artwork, not a text size. */

h1, h2 {
  color: var(--heading);
  font-family: var(--font-heading);
  font-weight: 600;
  scroll-margin-top: 90px;
}

h1 {
  font-size: 2.5em;
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin: 0.4em 0 0.45em;
}

h2 {
  font-size: 1.75em;
  line-height: 1.25;
  letter-spacing: -0.015em;
  margin: 1.75em 0 0.45em;
}

.doc p { margin: 1.15em 0; }

.lede {
  font-size: 1.24em;
  line-height: 1.6;
}

.doc a { text-decoration: none; }
.doc a:hover { text-decoration: underline; text-underline-offset: 3px; }

strong { font-weight: 650; color: var(--text); }

hr {
  border: none;
  border-top: 1px solid var(--border);
  margin: 3em 0;
}

code {
  font-family: var(--font-mono);
  font-size: 0.88em;
  background: var(--bg-code);
  color: var(--code-text);
  padding: 0.15em 0.4em;
  border-radius: 4px;
}

kbd {
  font-family: var(--font-body);
  font-size: 0.88em;
  padding: 0.1em 0.45em;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--bg-code);
}

/* ---------- Frontmatter plate ---------- */

.frontmatter {
  background: var(--frontmatter-bg);
  border: 1px solid var(--frontmatter-border);
  border-left: 3px solid var(--frontmatter-border);
  border-radius: 10px;
  padding: 14px 18px;
  margin: 0;
  overflow-x: auto;
}

.frontmatter pre,
.frontmatter code {
  font-family: var(--font-mono);
  font-size: 0.86em;
  line-height: 1.7;
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  color: var(--code-text);
  white-space: pre;
}

/* ---------- Code block ---------- */

.code-block {
  background: var(--bg-code);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 16px 18px;
  margin: 1.4em 0;
  overflow-x: auto;
  line-height: 1.55;
}

.code-block code {
  background: none;
  border: none;
  padding: 0;
  font-size: 0.86em;
  color: var(--code-text);
}

.t-title  { color: var(--tok-keyword); font-weight: 600; }
.t-class  { color: var(--tok-class); }
.t-string { color: var(--tok-string); }
.t-punct  { color: var(--tok-punctuation); }

/* ---------- Table ---------- */

.table-wrap {
  overflow-x: auto;
  margin: 1.5em 0;
}

table {
  border-collapse: collapse;
  width: 100%;
  min-width: 480px;
  font-size: 0.94em;
}

th, td {
  border: 1px solid var(--border);
  padding: 9px 13px;
  text-align: left;
  vertical-align: top;
}

th {
  background: var(--bg-code);
  color: var(--text);
  font-weight: 600;
}

td:first-child {
  width: 34%;
  white-space: nowrap;
}

td code { white-space: nowrap; }

/* ---------- Lists ----------
   Bullets are muted, not ochre. A bullet is punctuation, and the accent is
   reserved for things that mean something. */

.doc ul, .doc ol { padding-left: 1.6em; margin: 1.05em 0; }
.doc li { margin: 0.5em 0; }
.doc li::marker { color: var(--text-muted); }
.doc li > p { margin: 0; }

/* ---------- Alert ---------- */

.alert {
  border-left: 4px solid var(--border);
  border-radius: 0 6px 6px 0;
  padding: 0.6em 1em;
  margin: 1.5em 0;
  color: var(--text);
}

.alert p { margin: 0.35em 0; }
.alert p:first-child { margin-top: 0; }
.alert p:last-child { margin-bottom: 0; }

.alert__title {
  display: flex;
  align-items: center;
  gap: 7px;
  font-weight: 700;
  margin-bottom: 0.3em !important;
}

.alert__icon { width: 1em; height: 1em; flex: none; }

.alert--note { border-left-color: var(--alert-note); }
.alert--note .alert__title { color: var(--alert-note); }

/* ---------- Figures and their ground ----------
   One plate colour, one hairline, one radius, at every size. The hero is
   bigger, not different. */

.doc figure { margin: 2em 0; }

.plate {
  padding: 12px;
  border: 1px solid var(--plate-border);
  border-radius: 10px;
  background: var(--plate);
}

.plate--hero { padding: clamp(20px, 3vw, 40px); }
.plate--sm { padding: 9px; }

.plate img {
  width: 100%;
  border: 1px solid var(--plate-inner);
  border-radius: 6px;
  object-fit: cover;
  object-position: top center;
}

/* Two kinds of figure, and they need different edges.

   A DETAIL CROP is cut flush through document content, so it needs the hairline
   to separate it from the plate. Those are the capability tiles, the theme
   tiles and quick open.

   A FULL-WINDOW CAPTURE already carries a window edge and macOS' rounded
   corners. A hairline there traces a 6px curve across the window's much larger
   one and reads as a notch, and no fixed radius can match it because the image
   scales with the viewport. Those are framed by the plate's hairline instead;
   the corner fill is the plate colour, so the wedge outside the window's curve
   is invisible. Marked with .plate--window. */
.plate--window img { border: none; }

/* Ratios match the capture spec, so the page holds its shape before the
   images decode and nothing reflows under the reader. */
.plate--hero img  { aspect-ratio: 2200 / 1500; }
.plate--split img { aspect-ratio: 2480 / 1516; }
.grid--3 .plate img { aspect-ratio: 4 / 3; }
.grid--3.grid--tight .plate img { aspect-ratio: 800 / 783; }
.grid--2 .plate img { aspect-ratio: 4 / 3; }

figcaption {
  margin-top: 0.85em;
  color: var(--text-muted);
  font-size: 0.88em;
  line-height: 1.65;
}

figcaption strong { color: var(--text); font-weight: 650; }
figcaption code, figcaption kbd { font-size: 0.94em; }

/* Cap the caption's measure, not the figure's width. */
figure.wide > figcaption { max-width: var(--measure); margin-inline: auto; }

/* ---------- Figure grids ---------- */

.grid {
  display: grid;
  margin: 2em 0;
  gap: 34px 30px;
}

.grid figure { margin: 0; }
.grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 34px; }
.grid--tight { gap: 26px 22px; }

.label {
  margin-top: 0.7em;
  color: var(--text-muted);
  font-size: 0.76em;
  font-weight: 550;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}

/* ---------- Price ---------- */

.price-line {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 12px;
  margin: 1.2em 0 0.6em !important;
}

.price-line__amount {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 1.75em;
  letter-spacing: -0.015em;
  color: var(--heading);
}

.price-line__note {
  color: var(--text-muted);
  font-size: 0.94em;
}

.buy-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin: 1.8em 0 !important;
}

/* ---------- Details ----------
   Reference material, below the decision it supports. Label and value on one
   rhythm, separated by the same hairline as everything else. */

.details {
  margin: 1.4em 0 0;
  border-top: 1px solid var(--border);
}

.details > div {
  display: grid;
  grid-template-columns: 190px minmax(0, 1fr);
  gap: 4px 24px;
  padding: 14px 0;
  border-bottom: 1px solid var(--border);
}

.details > div:last-child { border-bottom: none; }

.details dt {
  color: var(--text);
  font-size: 0.94em;
  font-weight: 650;
}

.details dd {
  margin: 0;
  font-size: 0.94em;
}

/* ---------- Footnotes ---------- */

.fn-ref {
  color: var(--link);
  font-size: 0.76em;
  font-weight: 550;
  vertical-align: super;
  line-height: 0;
  padding: 0 0.15em;
  text-decoration: none;
}

.footnotes { margin-top: 3.5em; }

.footnotes dl { margin: 0; }

.footnote {
  display: flex;
  gap: 0.5em;
  align-items: baseline;
  margin: 0.5em 0;
  color: var(--text-muted);
  font-size: 0.88em;
}

.footnote::before {
  content: attr(data-fn) ".";
  flex: none;
  min-width: 1.4em;
  color: var(--text-muted);
}

.footnote dt { display: none; }

.footnote dd { flex: 1 1 auto; min-width: 0; margin: 0; }
.footnote dd > p { margin: 0; }

.footnote:first-of-type {
  border-top: 1px solid var(--border);
  margin-top: 1.5em;
  padding-top: 1em;
}

.fn-back {
  margin-left: 0.4em;
  color: var(--link);
  text-decoration: none;
}

/* =============================================================================
 * Footer chrome
 * ========================================================================== */

.site-footer {
  border-top: 1px solid var(--border);
  background: var(--bg-sidebar);
}

.site-footer__inner {
  width: min(100% - 40px, 1160px);   /* aligns with the wide figure track */
  margin: 0 auto;
  padding: 40px 0 46px;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 22px 40px;
  color: var(--text-muted);
  font-size: 0.82em;
}

.site-footer__brand {
  display: flex;
  align-items: center;
  gap: 14px;
}

.site-footer__mark {
  width: auto;
  height: 44px;
}

.site-footer__name {
  margin: 0;
  color: var(--heading);
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 1.5em;
  line-height: 1.2;
}

.site-footer__sub { margin: 0; line-height: 1.5; }

.site-footer__links {
  display: flex;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: 20px;
}

.site-footer a { color: var(--text-muted); text-decoration: none; }
.site-footer a:hover { color: var(--text); text-decoration: underline; text-underline-offset: 3px; }

.site-footer__copy {
  grid-column: 1 / -1;
  margin: 0;
  padding-top: 8px;
  border-top: 1px solid var(--border);
}

/* =============================================================================
 * Responsive
 * ========================================================================== */

@media (max-width: 900px) {
  .grid--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 720px) {
  body { font-size: 16px; }
  /* Let the table reflow to the column instead of scrolling sideways. */
  table { min-width: 0; font-size: 0.88em; }
  th, td { padding: 8px 10px; }
  td:first-child { width: 42%; white-space: normal; }
  .doc { padding: 40px 0 72px; }
  .topbar__nav { display: none; }
  .topbar__inner { min-height: 54px; gap: 16px; }
  .grid--2 { grid-template-columns: minmax(0, 1fr); gap: 30px; }
  .plate { padding: 10px; }
  .masthead { margin-bottom: 28px; }
  .details > div { grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .site-footer__inner {
    grid-template-columns: minmax(0, 1fr);
    padding: 34px 0 40px;
  }
  .site-footer__links { justify-content: flex-start; }
}

/* Below this the tiles stop being readable two across, and a screenshot you
   cannot read proves nothing. One across, full column width. */
@media (max-width: 620px) {
  .grid--3 { grid-template-columns: minmax(0, 1fr); gap: 28px; }
  .grid--3.grid--tight { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 22px 18px; }
}

@media (max-width: 480px) {
  .wordmark__text { font-size: 17px; }
  .btn--sm { padding: 0 11px; font-size: 12px; }
  h1 { font-size: 2.1em; }
  .frontmatter pre, .frontmatter code { font-size: 0.78em; }
  .code-block code { font-size: 0.78em; }
  .plate--sm { padding: 6px; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .btn, .btn--ghost { transition: none; }
}
