/* ============================================================
   Wed2Gether content pages (landing pages + blog)

   Loaded AFTER styles.css, which owns the tokens, the reset, the
   nav, the buttons and the type scale. Nothing here redefines a
   colour: every value below is a var() from that file, same as
   the homepage. Raw hex is banned here too.

   The homepage is a set-piece. These pages are the opposite:
   long-form reading, one column, quiet. The only decorated thing
   on the page is the answer block, and that is deliberate,
   because it is the passage the page exists to deliver.
   ============================================================ */

/* ---------- Document shell ---------- */

.doc__main {
  padding-block: clamp(2.5rem, 6vw, 5rem) 0;
}

/* Reading measure. 34rem lands around 70 characters at this size,
   which is the range long-form text stays comfortable in. */
.prose {
  max-width: 44rem;
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 4vw, 2.5rem);
}
.prose--index { max-width: 52rem; }

.prose__head {
  padding-bottom: clamp(1.5rem, 4vw, 2.5rem);
  margin-bottom: clamp(1.5rem, 4vw, 2.5rem);
  border-bottom: 1px solid var(--color-border);
}
.prose__head .eyebrow { margin-bottom: 0.875rem; }
.prose__head .eyebrow a { color: inherit; text-decoration-color: var(--color-accent-ink); }
.prose__head .display {
  font-size: clamp(2.5rem, 6vw, 4.25rem);
  margin-bottom: 1rem;
}
.prose__head .lede { font-size: 1.1875rem; max-width: 34rem; }

/* ---------- Long-form typography ---------- */

.prose h2 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.7rem, 3.4vw, 2.2rem);
  line-height: 1.2;
  letter-spacing: -0.005em;
  margin-top: 2.75rem;
  margin-bottom: 0.875rem;
  text-wrap: balance;
}
.prose h3 {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 1.0625rem;
  line-height: 1.35;
  margin-top: 1.75rem;
  margin-bottom: 0.5rem;
}
.prose p { margin-bottom: 1.125rem; }
.prose p:last-child { margin-bottom: 0; }

.prose a {
  color: var(--color-primary);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  /* ⚠️ DEEP GOLD, NOT GOLD. `--color-accent` is 2.2:1 on white, so a gold
     underline simply is not there and the link loses half its affordance.
     `--color-accent-ink` is 3.2:1, which clears the 3:1 floor for a
     non-text indicator. */
  text-decoration-color: var(--color-accent-ink);
  transition: text-decoration-color 160ms var(--ease-out);
}
.prose a:hover { text-decoration-color: var(--color-primary); }

.prose strong { font-weight: 700; }
.prose em { font-style: italic; }
.prose code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.9em;
  background: var(--color-soft);
  padding: 0.1em 0.35em;
  border-radius: 4px;
}

.prose ul, .prose ol {
  margin-bottom: 1.125rem;
  padding-left: 1.4rem;
}
.prose ul { list-style: disc; }
.prose ol { list-style: decimal; }
.prose li { margin-bottom: 0.5rem; padding-left: 0.25rem; }
.prose li::marker { color: var(--color-accent-ink); }
.prose ol li::marker { color: var(--color-muted); font-variant-numeric: tabular-nums; }

.prose blockquote {
  margin: 1.75rem 0;
  padding-left: 1.25rem;
  border-left: 2px solid var(--color-accent);
  font-family: var(--font-display);
  font-style: italic;
  font-size: 1.35rem;
  color: var(--color-foreground);
}
.prose blockquote p { margin-bottom: 0.5rem; }

.prose hr {
  border: 0;
  border-top: 1px solid var(--color-border);
  margin: 2.5rem 0;
}

/* ---------- The answer block ----------
   The one passage on the page written to be lifted out and quoted
   without the rest of the page around it. It gets the only real
   decoration on the page so a reader skimming for the answer finds
   it in the first screenful, which is the same thing a retrieval
   system is doing. */

.answer {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-primary);
  border-radius: var(--radius);
  padding: clamp(1.25rem, 3vw, 1.75rem);
  margin-bottom: 2rem;
}
.answer__q {
  font-family: var(--font-display);
  font-size: 1.4rem !important;
  font-weight: 600;
  line-height: 1.3;
  margin-top: 0 !important;
  margin-bottom: 0.625rem !important;
}
.answer p { margin-bottom: 0.75rem; }
.answer p:last-child { margin-bottom: 0; }

/* ---------- Aside ---------- */

.note {
  background: var(--color-soft);
  border-radius: var(--radius);
  padding: 1.125rem 1.25rem;
  margin: 2rem 0;
  font-size: 1rem;
  color: var(--color-foreground);
}
.note p:last-child { margin-bottom: 0; }

/* ---------- Table of contents ---------- */

.toc {
  margin-bottom: 2.5rem;
  padding: 1.125rem 1.25rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
}
.toc__label {
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.24em;
  color: var(--color-muted);
  margin-bottom: 0.625rem;
}
.toc ul {
  display: flex;
  flex-direction: column;
  gap: 0.4375rem;
  list-style: none;
  padding: 0;
  margin: 0;
  font-size: 0.9375rem;
}
.toc li { margin: 0; padding: 0; }
.toc a {
  color: var(--color-muted);
  text-decoration: none;
  transition: color 160ms var(--ease-out);
}
.toc a:hover { color: var(--color-primary); }

/* ---------- Tables ---------- */

/* The wrapper scrolls, not the page. A wide comparison table on a
   375px phone must never make the whole document pan sideways. */
/*
 * ⚠️ THE SHADOW ON THE RIGHT EDGE IS NOT DECORATION. It is the only thing
 * telling a phone reader there are more columns.
 *
 * The wrapper always scrolled correctly, so nothing was ever cut off — but on a
 * 375px phone a 32rem table shows about two of its three columns with a clean
 * vertical edge, which reads as the end of the table. A reader has no reason to
 * swipe, so the last column is content nobody sees. Found 2026-08-12.
 *
 * `background-attachment: local` on the two gradient "covers" and `scroll` on
 * the two shadows is the standard CSS-only trick: the covers move with the
 * content and hide the shadow when you are at that end, so the hint appears
 * only on the side that actually has more to show, with no JavaScript and no
 * scroll listener.
 */
.tablewrap {
  overflow-x: auto;
  margin: 1.75rem 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background:
    linear-gradient(to right, var(--color-surface) 30%, rgba(255, 255, 255, 0)),
    linear-gradient(to left, var(--color-surface) 30%, rgba(255, 255, 255, 0)) 100% 0,
    radial-gradient(farthest-side at 0 50%, rgba(0, 0, 0, 0.12), rgba(0, 0, 0, 0)),
    radial-gradient(farthest-side at 100% 50%, rgba(0, 0, 0, 0.12), rgba(0, 0, 0, 0)) 100% 0;
  background-repeat: no-repeat;
  background-size:
    2.5rem 100%,
    2.5rem 100%,
    0.875rem 100%,
    0.875rem 100%;
  background-attachment: local, local, scroll, scroll;
  background-color: var(--color-surface);
  -webkit-overflow-scrolling: touch;
}
.tablewrap table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9375rem;
  min-width: 32rem;
}
.tablewrap th, .tablewrap td {
  text-align: left;
  padding: 0.75rem 1rem;
  vertical-align: top;
  border-bottom: 1px solid var(--color-border);
}
.tablewrap th {
  font-weight: 500;
  font-size: 0.8125rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-muted);
  white-space: nowrap;
}
.tablewrap tbody tr:last-child td { border-bottom: 0; }
.tablewrap td:first-child { font-weight: 500; }

/* ---------- FAQ ----------
   Answers are visible, never collapsed. A question a reader has to
   click is a question an assistant is less likely to quote, and
   these are written to survive being lifted out one at a time. */

.faq {
  margin-top: 1.5rem;
  border-top: 1px solid var(--color-border);
}
.faq__item {
  padding: 1.375rem 0;
  border-bottom: 1px solid var(--color-border);
}
.faq__q {
  font-family: var(--font-sans) !important;
  font-weight: 700;
  font-size: 1.0625rem !important;
  margin-top: 0 !important;
  margin-bottom: 0.5rem !important;
}
.faq__a {
  color: var(--color-muted);
  margin-bottom: 0 !important;
}

/* ---------- Plan cards ----------
   Rendered from the plans parsed out of the app's tier-config.ts. Three
   columns that collapse to one, hairline borders rather than shadows, and no
   "most popular" badge: the highest tier is marked only by a lilac rule,
   because a badge is a sales device and this page is a price list. */

.plans {
  display: grid;
  gap: 1rem;
  /* 10.5rem, not 13rem: inside the 44rem reading measure minus its inline
     padding there is ~197px per column at three across, so a 13rem minimum
     silently dropped the third card onto its own row. */
  grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr));
  margin: 2rem 0;
}
.plan-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-top: 3px solid var(--color-border);
  border-radius: var(--radius);
  padding: 1.25rem;
}
/* Diamond: a solid-lilac card with sparkles, at Brad's direction 2026-08-17.
   This supersedes the hairline-only note above for THIS card; the other two
   stay quiet, which is what makes this one read as the destination. */
.plan-card--top {
  position: relative;
  overflow: hidden;
  background: var(--color-primary);
  border-color: var(--color-primary);
  border-top-color: var(--color-primary);
  color: var(--color-primary-foreground);
}
.plan-card--top .plan-card__name { color: var(--color-primary-foreground); }
.plan-card--top .plan-card__price span,
.plan-card--top .plan-card__adds { color: color-mix(in srgb, var(--color-primary-foreground) 70%, transparent); }
.plan-card--top .plan-card__list li::before { background: var(--color-accent); }
/* The inverted action: a purple button vanishes on the purple card */
.btn--invert { background: var(--color-primary-foreground); color: var(--color-primary); }
.btn--invert:hover { transform: translateY(-2px); box-shadow: 0 14px 32px rgba(0, 0, 0, 0.28); }

/* ---------- One styled button, on the top tier ----------
   Brad, 2026-09-09, after seeing gold on Gold and a faceted white on Diamond:
   "just make the diamond button gold and the other two plain".

   So the metallic treatment moved UP a card and the two below it went back to
   the plain outline. Silver and Gold still get a `btn--tier-*` class from the
   generator; it simply has no rules, which is the documented fallback and the
   hook if either is ever styled again.

   ⚠️ DO NOT PUT THIS BACK ON `.btn--tier-gold`. It was there for about an hour
   and Brad reversed it. Two styled buttons flatten the escalation: with one
   plain, one gold and one faceted, the eye has no order to follow. One styled
   button and two quiet ones is the order.

   ⚠️ TWO CLASSES, NOT ONE, AND `.prose a` IS WHY. On /pricing/ these buttons
   are anchors inside .prose, and `.prose a { color: var(--color-primary) }` is
   0,1,1 while a lone `.btn--tier-diamond` is 0,1,0. When the gold treatment sat
   on one class its label came out PURPLE on the pricing page and ink on the home
   page, from the same stylesheet: 4.35:1 on the gradient's dark stop, which
   fails at narrow card widths. `.btn.btn--tier-diamond` is 0,2,0 and wins
   wherever the button is placed.

   The measurement that caught it: the same button reported 5.32 on the home page
   and 4.35 on /pricing/. A single-page check would have missed it entirely.

   ⚠️ THE GOLD GRADIENT STOPS AT #be8423 AND THE MISSING STOP IS THE WHOLE
   POINT. The brand's metallic gradient (BRAND-IDENTITY.md) ends on #a9701a,
   where ink measures 3.96:1 and a 15px button label is under the 4.5 floor.
   That is exactly why the brand doc says a gradient belongs on a mark or a rule
   and NEVER on a control. Bounded at deep gold it holds 5.14:1 at its darkest
   and still reads as metal. Do not "complete" the gradient.

   ⚠️ INK ON GOLD, NEVER WHITE. White on gold is 2.21:1. Ink is 5.1 to 10.5
   across every stop used here.

   ⚠️ THE HOVER RULE IS NOT OPTIONAL. `.btn--invert:hover` is a two-selector
   rule and would beat a single-class one, so the button would flash back to
   white under the cursor.

   The deep-gold ring is now DECORATION, not a fix. It was load-bearing when
   this sat on the white Gold card, where gold is 2.21:1 against the surface and
   the button's own edge failed the 3:1 floor for identifying a control. On the
   brand-purple Diamond card the fill is already 6.29:1 against the ground, so
   the boundary passes without it; it stays because a darker rim is what makes
   the fill read as metal rather than as flat yellow. */
/* ⚠️ AND `.prose a` UNDERLINES THEM TOO. On /pricing/ these pills came out
   with a link underline through the label while the identical markup on the
   home page did not, because there the buttons are not inside .prose. It reads
   as a bug rather than a style: a pill that looks like a link. Pre-existing,
   and it applies to all three buttons, not just the styled one.
   0,2,0 beats `.prose a` at 0,1,1. */
.prose .btn { text-decoration: none; }

.btn.btn--tier-diamond {
  background: linear-gradient(
    135deg,
    var(--color-accent-light) 0%,
    var(--color-accent) 46%,
    var(--color-accent-ink) 100%
  );
  color: var(--color-accent-foreground);
  box-shadow: inset 0 0 0 1px var(--color-accent-ink);
}
.btn.btn--tier-diamond:hover {
  background: linear-gradient(
    135deg,
    var(--color-accent-light) 0%,
    var(--color-accent) 62%,
    var(--color-accent-ink) 100%
  );
  color: var(--color-accent-foreground);
  transform: translateY(-2px);
  box-shadow: inset 0 0 0 1px var(--color-accent-ink), 0 12px 26px rgba(0, 0, 0, 0.35);
}

/* Diamond sparkles: four-point stars, twinkling on a stagger. Positions and
   per-star delay/scale come inline from the generator. */
.spark { position: absolute; inset: 0; pointer-events: none; }
.spark i {
  position: absolute;
  width: 11px;
  height: 11px;
  background: color-mix(in srgb, var(--color-accent) 55%, var(--color-primary-foreground));
  clip-path: polygon(50% 0, 61% 39%, 100% 50%, 61% 61%, 50% 100%, 39% 61%, 0 50%, 39% 39%);
  opacity: 0;
  transform: scale(var(--s, 1));
  animation: spark-twinkle 3.6s ease-in-out infinite;
  animation-delay: var(--d, 0s);
}
@keyframes spark-twinkle {
  0%, 100% { opacity: 0; transform: scale(calc(var(--s, 1) * 0.35)) rotate(0deg); }
  50% { opacity: 0.95; transform: scale(var(--s, 1)) rotate(24deg); }
}
@media (prefers-reduced-motion: reduce) {
  .spark i { animation: none; opacity: 0.45; }
}
/* Fraunces italic, like the couple names in the app itself, rather than the
   tracked small caps every SaaS pricing card defaults to. The tier names are
   the one place on a price list where a little romance is honest. */
.plan-card__name {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 1.55rem;
  line-height: 1;
  color: var(--color-foreground);
  margin-bottom: 0.5rem !important;
}
.plan-card__price {
  font-family: var(--font-display);
  font-size: 2.3rem;
  line-height: 1;
  margin-bottom: 0.875rem !important;
  font-variant-numeric: tabular-nums;
}
.plan-card__price span {
  font-family: var(--font-sans);
  font-size: 0.8125rem;
  color: var(--color-muted);
  margin-left: 0.375rem;
  letter-spacing: 0.04em;
}
.plan-card__adds {
  font-size: 0.8125rem;
  color: var(--color-muted);
  margin-bottom: 0.5rem !important;
}
.plan-card__list {
  list-style: none !important;
  padding-left: 0 !important;
  margin-bottom: 0 !important;
  font-size: 0.9375rem;
}
.plan-card__list li {
  padding-left: 1rem;
  margin-bottom: 0.3125rem;
  position: relative;
}
.plan-card__list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.6em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  /* Deep gold: these dots are on a white card. The Diamond card overrides
     back to full gold below, because that card's ground is brand purple and
     gold reads at 6.3:1 on it. */
  background: var(--color-accent-ink);
}
/* The card is a flex column so the button sits on the baseline of the tallest
   card rather than immediately under a short feature list, which is what makes
   three cards of different lengths read as one row.

   ⚠️ THE LIST GROWS. THE BUTTON DOES NOT GET margin-top: auto, AND THAT IS THE
   FIX, NOT A STYLE CHOICE (2026-09-09).

   This comment claimed the buttons lined up and for weeks they did not: Silver
   has eight features, Gold five, Diamond six, so each button sat directly under
   its own list at three different heights. Brad sent a screenshot.

   The cause was specificity, invisible in a diff. `.plan-card__cta` set
   `margin-top: auto`, and the rule right below it, `.plan-card__cta.btn`, set
   `margin-top: 1.25rem`. Two class selectors beat one, so the fixed margin won
   every time and the `auto` never applied to a single button on the site. The
   CTA is always rendered with `btn`, so the looser rule could never win.

   Growing the LIST instead of auto-margining the button avoids the collision
   completely: `auto` and a fixed margin cannot both live on the same side, but
   flex-grow and a fixed margin can. It also leaves the no-CTA case alone, which
   an auto margin plus a spacer on the list would not: `:::plans` without `cta`
   renders no button, and a bottom margin on the list would then hang inside the
   card as dead space.

   *Re-check by measuring, not by looking:* the three buttons' getBoundingClientRect().top
   must be equal, at every width where the cards are still in one row. */
.plan-card { display: flex; flex-direction: column; }
.plan-card__cta {
  padding-top: 1rem;
  align-self: stretch;
  justify-content: center;
}
.plan-card__list { flex: 1 1 auto; }
.plan-card__cta.btn { margin-top: 1.25rem; padding-top: 0; min-height: 2.75rem; font-size: 0.9375rem; }

/* ---------- Feature comparison ----------
   Generated from the app's FEATURE_MIN_TIER, so a tick can never disagree with
   what the route gates actually allow.

   The scroll shadow is the app's own trick: `background-attachment: local` on
   the gradient layers means the hint appears only on the side that really has
   more to show, with no JavaScript and no scroll listener. */
.compare {
  overflow-x: auto;
  border-radius: var(--radius-photo);
  /*
   * ⚠️ `position: relative` IS LOAD-BEARING, not decoration. Every cell in this
   * table carries a `.vh` label, and `.vh` is `position: absolute`. With no
   * positioned ancestor their containing block is the viewport, so they are NOT
   * clipped by this scroll container: they sit at their static position out at
   * x≈454 on a 375px phone and push the whole document sideways.
   *
   * The symptom is the confusing part. The table itself scrolls correctly, the
   * page still scrolls sideways, and every element the measurement blames is
   * inside the container that is visibly working. Cost a debugging pass
   * 2026-08-17. Making this the containing block clips them with everything
   * else.
   */
  position: relative;
  margin: 2rem 0;
  background:
    linear-gradient(to right, var(--color-background) 30%, transparent),
    linear-gradient(to left, var(--color-background) 30%, transparent) 100% 0,
    radial-gradient(farthest-side at 0 50%, rgba(42, 22, 54, 0.14), transparent),
    radial-gradient(farthest-side at 100% 50%, rgba(42, 22, 54, 0.14), transparent) 100% 0;
  background-repeat: no-repeat;
  background-size: 2.5rem 100%, 2.5rem 100%, 0.75rem 100%, 0.75rem 100%;
  background-attachment: local, local, scroll, scroll;
}
.compare__table {
  border-collapse: collapse;
  width: 100%;
  min-width: 30rem;
  font-size: 0.9375rem;
}
.compare__table th,
.compare__table td { padding: 0.6rem 0.75rem; text-align: left; }
.compare__table thead th {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.15rem;
  border-bottom: 2px solid var(--color-border);
  white-space: nowrap;
}
.compare__table thead th span {
  display: block;
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: 0.8125rem;
  color: var(--color-muted);
  font-variant-numeric: tabular-nums;
}
.compare__table tbody th {
  font-weight: 400;
  color: var(--color-foreground);
  padding-left: 0;
}
.compare__table tbody tr + tr th,
.compare__table tbody tr + tr td { border-top: 1px solid var(--color-border); }
.compare__table td { text-align: center; width: 6.5rem; }
/* The paid column carries a tint down its full height rather than a border, so
   the eye follows one column instead of reading a boxed cell at a time. */
.compare__table .is-top { background: color-mix(in srgb, var(--color-soft) 55%, transparent); }
.compare__table thead .is-top { background: var(--color-soft); }
.tick { color: var(--color-primary); font-weight: 700; }
/* ⚠️ MUTED, NOT GOLD. This dash is the table's "not included" and a sighted
   reader has nothing else to go on, so it is text, not decoration. Gold is
   2.2:1 on white and the column read as blank. */
.dash { color: var(--color-muted); }

/* Visually hidden, but read aloud. A row of four blank cells tells a screen
   reader nothing, and this table is the page's main commercial claim. */
.vh {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---------- Byline and author ---------- */

.byline {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.25rem;
  margin-top: 1.25rem;
  font-size: 0.875rem;
  color: var(--color-muted);
}
.byline b { color: var(--color-foreground); font-weight: 500; }
.byline__updated { color: var(--color-primary); }

.prose__foot {
  margin-top: 3rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--color-border);
}
.authorbox {
  font-size: 0.9375rem;
  color: var(--color-muted);
}
.authorbox b { color: var(--color-foreground); }

/* ---------- Blog index ---------- */

/* Scoped under .prose because `.prose ul` sets list-style and padding, and a
   bare `.postlist` loses that specificity contest. It shipped once with a
   lilac bullet floating beside every post date. */
.prose .postlist {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
}
.prose .postlist__item {
  padding: 1.75rem 0;
  margin: 0;
  border-bottom: 1px solid var(--color-border);
}
.prose .postlist__item:first-child { padding-top: 0; }
.postlist__meta {
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  color: var(--color-muted);
  margin-bottom: 0.5rem;
}
.postlist__item h2 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.55rem, 3.3vw, 2rem);
  line-height: 1.2;
  margin-bottom: 0.5rem;
}
.postlist__item h2 em { font-style: italic; color: var(--color-primary); }
.postlist__item h2 a { text-decoration: none; }
.postlist__item h2 a:hover { color: var(--color-primary); }
.postlist__item > p { color: var(--color-muted); margin: 0; }

/* ---------- Closing CTA ---------- */

.cta {
  margin-top: clamp(3.5rem, 8vw, 6rem);
  padding-block: clamp(3rem, 7vw, 5rem);
  background: var(--color-surface);
  border-top: 1px solid var(--color-border);
  text-align: center;
}
.cta__inner { display: grid; justify-items: center; gap: 1rem; }
.cta .display { max-width: 26rem; }
.cta .lede { max-width: 30rem; }
.cta .btn { margin-top: 0.5rem; }
.cta__note {
  font-size: 0.875rem;
  color: var(--color-muted);
  max-width: 26rem;
}

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

.footer__links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.25rem;
  font-size: 0.875rem;
}
.footer__links a {
  color: var(--color-muted);
  text-decoration: none;
  transition: color 160ms var(--ease-out);
}
.footer__links a:hover { color: var(--color-primary); }

@media (max-width: 48rem) {
  .footer__links { justify-content: center; }
}
