/* peony.social — the brand site.
 *
 * Same rules as every site in this estate: no cookies, no JavaScript, nothing
 * loaded from a third party, no webfonts. So it needs no consent banner and has
 * nothing that can fail on someone else's outage.
 *
 * ⚠ THE PALETTE IS COPIED FROM docs/mockups/peony.html :root, NOT retyped from
 * brand.md's table. That table is the readable index; the mockup is the spec —
 * retyping a hex is how an app once shipped cards a shade too dark.
 * docs/ops/brand-sites.md §4.1.
 *
 * ⚠ AND PEONY'S :root IS A PARTIAL OVERRIDE: it sets eight tokens and inherits
 * the rest from `app.css`, which it loads first
 * (`<link rel="stylesheet" href="app.css">`).
 * So `--surface`, `--line`, `--blk2` and `--muted` below are app.css's values,
 * copied from there, and each is marked. Reading only peony.html would have
 * left this file with no surface colour at all.
 *
 * `--frame`, `--blk`, `--ghost-bg` and the `--danger-*` set are deliberately
 * NOT copied: they are app-only tokens with no counterpart on a web page.
 *
 * ⛔ TWO DEVIATIONS THE LIGHT GROUND FORCES, and they are the mirror image of
 * the problem brand.md's "Dark-theme fixes" block solves on a dark ground:
 *
 *   1. `--accent` (#d9a0a0 blush) CANNOT CARRY TEXT OR A FOCUS RING here. On
 *      `--bg` it is 1.4:1, so links and focus rings take `--brand`, the wine, at
 *      7.1:1. The accent stays what it is in the app — a decorative tint, not a
 *      text colour.
 *   2. `--muted` (#8a8d94, app.css's grey) FAILS AT BODY SIZE on both of this
 *      site's grounds — 2.95:1 on `--bg`, 2.53:1 on `--tile`, against the 4.5:1
 *      that normal-size text needs. Secondary text therefore uses `--hero-ink`
 *      (#6b3646), which is in-palette and measures 8.3:1 and 7.1:1. `--muted`
 *      is kept for hairlines and for the unearned segments of the Active ring,
 *      where it is a line rather than a word.
 */

:root {
  /* From docs/mockups/peony.html :root — variant C, "Slow Burn". */
  --bg: #f9efef;
  --tile: #f1dcdc;
  --ink: #3d2530;
  --brand: #7e3b4a;
  --brand-ink: #ffffff;
  --accent: #d9a0a0;
  --hero: linear-gradient(160deg, #efd8da, #f9f0ee);
  --hero-ink: #6b3646;

  /* From docs/mockups/app.css :root — the defaults peony.html leaves alone. */
  --surface: #ffffff;
  --line: #e4e5ea;
  --blk2: #cfd1d7;
  --muted: #8a8d94;

  --sans: -apple-system, system-ui, "Segoe UI", Roboto, sans-serif;
  --serif: ui-serif, Georgia, "Times New Roman", serif;

  --measure: 62ch;
  --page: 44rem;
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.65;
}

.wrap {
  max-width: var(--page);
  margin: 0 auto;
  padding: 0 1.5rem;
}

/* ---------- header ---------- */
.masthead {
  border-bottom: 1px solid var(--line);
  background: var(--bg);
}
.masthead .wrap {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  flex-wrap: wrap;
  padding-top: 1.5rem;
  padding-bottom: 1.5rem;
}
.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--serif);
  font-size: 1.5rem;
  letter-spacing: -0.01em;
  color: var(--ink);
  text-decoration: none;
}
/* The masthead icon, built rather than photographed: the tile is CSS — the
   brand gradient and the app icon's 22.7% corner radius — and the mark inside
   is inline SVG, crisp at any zoom where a scaled raster is not.

   ⚠ THE MARK IS COPIED FROM docs/brand/export/peony.svg, INCLUDING ITS
   TRANSFORM. That is the rule this estate learned the hard way — copy the
   shipped asset, never redraw from memory or from an older preview.
   That file places the mark with translate(59.39,18.38) scale(9.1034) in a
   1024 box; the same placement in a 100 box is translate(5.8,1.795)
   scale(0.889), which is what the markup carries. Re-derive it from that file
   after any change to the icon, and check it against peony-1024.png.

   The rasters are NOT drawn here: favicon.ico, apple-touch-icon.png and
   og-image.png are downscaled from docs/brand/export/peony-1024.png, because a
   raster can be derived and therefore should be. */
.wordmark .appicon {
  /* 4.8rem, the same as the sibling site — that size was arrived at by eye
     against the wordmark and should not drift between the two. */
  width: 4.8rem;
  height: 4.8rem;
  flex: none;
  display: block;
  border-radius: 22.7%;
  background: var(--hero);
  overflow: hidden;

  /* The hairline and soft shadow iOS draws around and under an app icon, which
     are not in the asset — icon-1024.png is flat gradient to its corners — and
     which nothing adds to a web page. ⚠ On a light tile the lining that reads as
     an edge is a shadow, not a highlight — the opposite of what a dark tile
     wants. */
  box-shadow:
    inset 0 0 0 1px rgba(61, 37, 48, 0.10),
    inset 0 1px 0 rgba(255, 255, 255, 0.55),
    0 1px 2px rgba(61, 37, 48, 0.12),
    0 6px 16px rgba(61, 37, 48, 0.10);
}
.wordmark .appicon svg { display: block; width: 100%; height: 100%; }
.masthead nav {
  margin-left: auto;
  display: flex;
  gap: 1.25rem;
  flex-wrap: wrap;
}
.masthead nav a {
  color: var(--hero-ink);
  text-decoration: none;
  font-size: 0.95rem;
}
.masthead nav a:hover { color: var(--brand); text-decoration: underline; }
.masthead nav a[aria-current="page"] { color: var(--ink); }

/* ---------- hero ---------- */
/* The one place the brand's own gradient appears, as it does in the app. */
.hero {
  background: var(--hero);
  border-bottom: 1px solid var(--line);
  color: var(--hero-ink);
}
.hero .wrap { padding-top: 4rem; padding-bottom: 3.5rem; }
.hero h1 { margin-bottom: 1rem; color: var(--brand); }
/* ⚠ An opacity, not a hex: picking a tint by hand would mean inventing a colour
   that is in no palette file, so the lead simply sits back from the hero ink. */
.hero .lead { color: var(--hero-ink); opacity: 0.85; }

/* ---------- content ---------- */
main { padding: 3rem 0 4rem; }
.hero + main { padding-top: 2.5rem; }

h1 {
  font-family: var(--serif);
  font-weight: 400;
  font-size: 2.25rem;
  line-height: 1.2;
  letter-spacing: -0.015em;
  margin: 0 0 1.25rem;
}
h2 {
  font-family: var(--serif);
  font-weight: 400;
  font-size: 1.4rem;
  line-height: 1.3;
  margin: 2.75rem 0 0.75rem;
}
h3 {
  font-size: 1rem;
  font-weight: 600;
  margin: 2rem 0 0.5rem;
  color: var(--brand);
}
p, li { max-width: var(--measure); }
p { margin: 0 0 1.1rem; }
ul { padding-left: 1.25rem; margin: 0 0 1.1rem; }
li { margin-bottom: 0.4rem; }

.lead { font-size: 1.2rem; color: var(--hero-ink); }

/* The wine, not the blush — see the header comment's deviation 1. */
a { color: var(--brand); }
a:hover { text-decoration-thickness: 2px; }

a:focus-visible,
:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-radius: 2px;
}

/* ---------- panels ---------- */
.note {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 1.25rem 1.5rem;
  margin: 0 0 1.5rem;
  max-width: var(--measure);
}
.note p:last-child { margin-bottom: 0; }

.details {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.5rem 2rem;
  margin: 0 0 1.5rem;
  padding: 1.5rem;
  background: var(--tile);
  border: 1px solid var(--line);
  border-radius: 6px;
  max-width: var(--measure);
}
.details dt { color: var(--hero-ink); }
.details dd { margin: 0; }

@media (max-width: 34rem) {
  .details { grid-template-columns: 1fr; gap: 0.15rem; }
  .details dd { margin-bottom: 0.75rem; }
}

/* ---------- footer ---------- */
/* Companies Act ss.82-84. Owed on EVERY page, not just this one. ⚠ And it is
   the one block on the site that must not be styled quietly into
   illegibility — it is a statutory disclosure, so it takes --hero-ink rather
   than --muted (2.5:1 on this tile). */
.legal {
  border-top: 1px solid var(--line);
  background: var(--tile);
  color: var(--hero-ink);
  font-size: 0.9rem;
  line-height: 1.6;
}
.legal .wrap { padding-top: 2rem; padding-bottom: 2.5rem; }
.legal p { max-width: var(--measure); margin: 0 0 0.5rem; }
.legal a { color: var(--brand); }
.legal nav { margin-top: 1rem; display: flex; gap: 1.25rem; flex-wrap: wrap; }

/* ---------- buttons ---------- */
/* Filled wine with white text, which is the app's own primary button
   (`--brand` on `--brand-ink`). Not the accent: it is a tint and cannot carry a
   label. */
.btn {
  display: inline-block;
  padding: 0.7rem 1.4rem;
  border: 1px solid var(--brand);
  border-radius: 8px;
  background: var(--brand);
  color: var(--brand-ink);
  font-weight: 600;
  text-decoration: none;
}
.btn:hover { background: var(--hero-ink); border-color: var(--hero-ink); }
.btn.quiet {
  background: transparent;
  color: var(--brand);
}
.btn.quiet:hover { background: var(--tile); }

.cta-block { margin-top: 2.75rem; }
.cta-block p:last-child { margin-bottom: 0; }
.cta-block .btn { margin-top: 0.5rem; }

/* ============================================================================
 * HOME PAGE — the scrolling story
 *
 * ⚠ NO JAVASCRIPT IS POSSIBLE HERE, and that is enforced rather than agreed:
 * the distribution serves `default-src 'none'` with no script-src, so the
 * browser refuses to run a script even if one were added. `style-src 'self'`
 * also blocks inline style attributes, which is why every rule lives in this
 * file.
 *
 * So the scroll behaviour is CSS scroll-driven animation. Everything below is
 * PROGRESSIVE: without `animation-timeline` support the page is an ordinary
 * document with all content visible, because the reveal only animates from a
 * hidden state INSIDE @supports. Nothing is hidden by default.
 * ========================================================================= */

/* ---------- bands ---------- */
.story { padding: 0; }
.story > .band:first-child { border-top: 0; }

.band { padding: 4.5rem 0; border-top: 1px solid var(--line); }
.band-alt { background: var(--surface); }
.band h2 { margin-top: 0; }
.band .section-lead { font-size: 1.1rem; color: var(--hero-ink); max-width: var(--measure); }
.band .aside {
  margin-top: 2rem;
  padding-left: 1rem;
  border-left: 2px solid var(--accent);
  color: var(--hero-ink);
  max-width: var(--measure);
}

/* ---------- hero actions ---------- */
.hero-actions {
  display: flex;
  align-items: center;
  gap: 1rem 1.25rem;
  flex-wrap: wrap;
  margin-top: 1.75rem;
}
.btn-note { color: var(--hero-ink); font-size: 0.95rem; }

/* ---------- 1 · the loop everyone recognises ---------- */
.loop {
  list-style: none;
  counter-reset: loop;
  padding: 0;
  margin: 0 0 1.75rem;
  max-width: var(--measure);
}
.loop li {
  counter-increment: loop;
  position: relative;
  padding: 0.55rem 0 0.55rem 2.6rem;
  border-bottom: 1px solid var(--line);
  font-size: 1.05rem;
}
.loop li::before {
  content: counter(loop);
  position: absolute;
  left: 0;
  color: var(--hero-ink);
  font-variant-numeric: tabular-nums;
}
.loop .loop-back { color: var(--brand); border-bottom: 0; }
.loop .loop-back::before { content: "\21bb"; }
.loop-note { max-width: var(--measure); }

/* ---------- 2 · the comparison ---------- */
/* The heading stays put while the rows pass it, so the contrast is always
 * labelled. It is the cheapest honest version of "the content updates as you
 * scroll", and it costs nothing where sticky is unsupported. */
.sticky-h2 {
  position: sticky;
  top: 0;
  z-index: 1;
  margin: 0 0 1.5rem;
  padding: 1rem 0;
  background: var(--surface);
}
.versus { list-style: none; padding: 0; margin: 0; }
.versus li {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.5rem;
  padding: 0.9rem 0;
  border-top: 1px solid var(--line);
  max-width: none;
}
.versus .v-old { color: var(--hero-ink); opacity: 0.75; }
.versus .v-new { color: var(--ink); font-weight: 500; }
.versus .v-new::before { content: "\2192\00a0"; color: var(--brand); }

@media (max-width: 40rem) {
  .versus li { grid-template-columns: 1fr; gap: 0.2rem; padding: 1rem 0; }
  .sticky-h2 { font-size: 1.25rem; padding: 0.75rem 0; }
}

/* ---------- 3 · steps ---------- */
.steps {
  list-style: none;
  counter-reset: step;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 2rem;
}
.steps li { counter-increment: step; max-width: var(--measure); }
.steps h3 { margin: 0 0 0.4rem; font-size: 1.15rem; color: var(--brand); }
.steps h3::before {
  content: counter(step);
  display: inline-grid;
  place-items: center;
  width: 1.7rem;
  height: 1.7rem;
  margin-right: 0.7rem;
  border-radius: 50%;
  background: var(--brand);
  color: var(--brand-ink);
  font-size: 0.9rem;
  vertical-align: 0.05rem;
}
.steps p { margin: 0; }

@media (min-width: 56rem) {
  .steps { grid-template-columns: repeat(3, 1fr); gap: 2.5rem; }
  .steps li { max-width: none; }
}

/* ---------- 4 · badges ---------- */
.badges { list-style: none; padding: 0; margin: 0; }
.badges li {
  display: grid;
  grid-template-columns: 7.5rem 1fr;
  gap: 0.6rem 1.75rem;
  padding: 1.15rem 0;
  border-top: 1px solid var(--line);
  align-items: start;
  max-width: none;
}

/* ---------- 7 · close ---------- */
.close p { max-width: var(--measure); }

/* ---------- the scroll reveal ---------- */
/* Guarded twice. @supports means a browser without scroll-driven animations
 * never hides anything; prefers-reduced-motion means a reader who asked for
 * stillness gets a static page. Both fall back to "everything visible", the
 * only acceptable failure for a page whose job is to be read. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .reveal {
      animation: rise linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 55%;
    }
    .versus li.reveal,
    .badges li.reveal { animation-range: entry 0% entry 40%; }
  }
}

@keyframes rise {
  from { opacity: 0; transform: translateY(1.25rem); }
  to { opacity: 1; transform: none; }
}

/* ---------- badges, as the app draws them ---------- */
/* The app renders each badge as a ringed glyph with the label beneath, in the
 * brand's primary colour — which for Peony is the wine. See
 * docs/ops/brand-sites.md §5.3 for the component this follows.
 * Active is the exception: a five-segment ring that fills through the earned
 * level, so it is drawn as a ring here too rather than flattened into a chip.
 *
 * SF Symbols do not exist on the web, so the glyphs are redrawn as paths and
 * coloured by these rules — never by attributes on the SVG, which would have
 * put the palette in ten places instead of one. */
.bdg {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
  text-align: center;
}
.bdg-mark {
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
  border: 2px solid var(--brand);
}
.bdg-mark svg { width: 1.5rem; height: 1.5rem; display: block; }
.bdg-label { font-size: 0.8rem; color: var(--hero-ink); line-height: 1.3; }

/* The glyph shapes. `fill` is a solid symbol; `knock` is the notch cut out of
 * it, painted in the ground behind the mark so it reads as a hole — which is
 * why the badges sit in a `band-alt`, on `--surface`; `tick` is a stroked
 * check, which the app draws heavy. */
.bdg-mark .fill { fill: var(--brand); }
.bdg-mark .knock {
  fill: none;
  stroke: var(--surface);
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.bdg-mark .tick {
  fill: none;
  stroke: var(--brand);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Active: the ring IS the badge, so it loses the surrounding circle. Segments
 * are arcs of one circle, normalised to pathLength 100 and rotated 72 apart. */
.bdg-mark.bdg-active { border: 0; }
.bdg-mark .ring { width: 3rem; height: 3rem; }
/* The unearned segments must still be VISIBLE — they are what makes the badge
 * read as "three of five" rather than as an arc of unknown length. This is the
 * one place --muted earns its keep on this site: it is a line, not a word. */
.ring .seg {
  fill: none;
  stroke: var(--muted);
  stroke-width: 4;
  stroke-linecap: round;
}
.ring .seg.on { stroke: var(--brand); }
.ring .lvl {
  fill: var(--brand);
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 600;
  text-anchor: middle;
  dominant-baseline: central;
}

@media (max-width: 40rem) {
  .badges li { grid-template-columns: 1fr; }
  .bdg { flex-direction: row; gap: 0.75rem; text-align: left; }
  .bdg-label { font-size: 0.95rem; }
}

/* ---------- reference tables ---------- */
/* The privacy notice's lawful-basis and retention maps. A three-column table is
   unreadable at 390px, so below 40rem each row becomes a block and each cell
   labels itself from `data-l` — content from an attribute, which the CSP allows
   because it is a rule in this file rather than markup. */
.matrix {
  width: 100%;
  border-collapse: collapse;
  margin: 0 0 1.5rem;
  font-size: 0.95rem;
}
.matrix th,
.matrix td {
  text-align: left;
  vertical-align: top;
  padding: 0.6rem 0.75rem 0.6rem 0;
  border-top: 1px solid var(--line);
}
.matrix th { font-weight: 600; color: var(--hero-ink); }
.matrix td:first-child { font-weight: 500; }

@media (max-width: 40rem) {
  .matrix thead { position: absolute; left: -9999px; }
  .matrix tr {
    display: block;
    padding: 0.75rem 0;
    border-top: 1px solid var(--line);
  }
  .matrix td {
    display: block;
    border: 0;
    padding: 0 0 0.35rem;
  }
  .matrix td[data-l]::before {
    content: attr(data-l) " — ";
    color: var(--hero-ink);
  }
  .matrix td:first-child[data-l]::before { content: none; }
}
