/* ===========================================================================
   Page styling.

   Colours, fonts, spacing and layout all come from custom properties that the
   Worker writes into a <style> block per request — so editing settings in
   /admin restyles this file's output without touching this file.

   The values below are fallbacks only, used if that block is ever missing.
   Derived shades (hover, strong border, focus ring) are computed with
   color-mix so the editor only has to expose one colour per role.
   =========================================================================== */

:root {
  --bg: #fbfbfa;
  --bg-card: #ffffff;
  --bg-subtle: #f4f4f2;
  --text: #1a1a19;
  --text-muted: #6b6a66;
  --border: #e3e2de;
  --accent: #1a1a19;
  --accent-text: #ffffff;

  --font: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --font-size: 16px;
  --radius: 12px;
  --radius-lg: 18px;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.04), 0 8px 24px rgba(0, 0, 0, 0.06);
  --card-width: 432px;
  --amount-cols: 3;
  --pad: 24px;
  --gap: 8px;
  --page-fill: auto;
}

/* Derived from the eight editable colours above. */
:root {
  --bg-subtle-hover: color-mix(in srgb, var(--bg-subtle) 92%, var(--text));
  --border-strong: color-mix(in srgb, var(--border) 65%, var(--text));
  --accent-ring: color-mix(in srgb, var(--accent) 18%, transparent);
  --success: color-mix(in srgb, var(--accent) 40%, #1c7c54);
}

/* ===========================================================================
   Base
   =========================================================================== */

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

html,
body {
  margin: 0;
  padding: 0;
}

body {
  min-height: 100dvh;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: var(--font-size);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

[hidden] {
  display: none !important;
}

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

/* ===========================================================================
   Layout
   =========================================================================== */

/*
 * The window, split into the page and the footer under it.
 *
 * The footer used to live inside the centred column, which made it one more
 * thing being centred: on a short page it floated in the middle of the window
 * with the card, and it could never be wider than the card it sat under. Out
 * here it is the bottom of the window, full width, and the page above it takes
 * whatever room is left.
 */
.shell {
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
}

/*
 * Centred vertically by auto margins rather than by justify-content.
 *
 * `justify-content: center` on a column taller than the window pushes the top
 * of the content above the scroll origin, where no amount of scrolling can
 * reach it — the heading is simply gone. Auto margins collapse to nothing once
 * the content fills the window, so a long page scrolls from its true top.
 */
.page {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: 24px;
  /* Nothing, rather than the window's height: the shell is what fills the
     window now, and a page that still claimed the whole of it would push the
     footer below the fold on every short page. */
  min-height: 0;
  padding: 44px 20px;
}

.page > :first-child {
  margin-top: var(--page-fill);
}

/*
 * A hidden thing at the top hands the spacing on.
 *
 * The rule above is what centres the page, and it picks the first child
 * whether or not that child is drawn. Put anything hidden at the top — a
 * notice that is usually off — and the space it was meant to carry vanishes
 * with it, pinning the whole page to the top of the window.
 */
.page > [hidden]:first-child + * {
  margin-top: var(--page-fill);
}

.page > :last-child {
  margin-bottom: var(--page-fill);
}

.header {
  max-width: var(--card-width);
  text-align: center;
}

.header__name {
  margin: 0;
  font-size: 1.75em;
  font-weight: 650;
  letter-spacing: -0.02em;
}

.header__tagline {
  margin: 8px 0 0;
  color: var(--text-muted);
  font-size: 0.975em;
}

/* The fee, stated before anyone reaches the card fields. */
.header__breakdown {
  margin: 4px 0 0;
  color: var(--text-muted);
  font-size: 0.8125em;
}

.card {
  width: 100%;
  max-width: var(--card-width);
  padding: var(--pad);
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
}

/* With nothing in it but links, the card is a box drawn round some buttons.
   The buttons are the page, so the box goes and they stand on their own. */
.card--bare {
  padding: 0;
  background: none;
  border: none;
  box-shadow: none;
}

/* ===========================================================================
   The demonstration strip

   Only ever drawn inside a sandbox (see demo.js). It sits above everything,
   in the page's own colours rather than a colour of its own, because a copy
   of somebody's site should still look like the site — the words are what say
   it is a copy, not a stripe of red across the top.
   =========================================================================== */

.demobar {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  align-items: baseline;
  justify-content: center;
  width: 100%;
  margin: 0;
  padding: 10px 20px;
  background: var(--bg-subtle);
  border-bottom: 1px solid var(--border);
  color: var(--text-muted);
  font-size: 0.8125em;
  line-height: 1.45;
  text-align: center;
}

.demobar__go {
  color: var(--accent);
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  border-bottom: 1px solid transparent;
}

.demobar__go:hover,
.demobar__go:focus-visible {
  border-bottom-color: currentColor;
}

/* ===========================================================================
   The footer

   One footer, built by the server for every page (see src/footer.js). Full
   width, below the page rather than inside it, and never overlapping what is
   above it: it is the last item in a flex column, so it cannot be.

   Columns on a wide screen, stacked on a narrow one. The columns are laid out
   by `auto-fit`, so the number of them follows how many there are rather than
   being written down here — a site with one column gets one column, not one
   column and three empty tracks.
   =========================================================================== */

.footer {
  width: 100%;
  margin-top: auto;
  padding: 28px 20px 32px;
  border-top: 1px solid var(--border);
  background: var(--bg);
  color: var(--text-muted);
  font-size: 0.8125em;
}

.footer__inner {
  width: 100%;
  max-width: 980px;
  margin: 0 auto;
}

.footer__nav {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 22px 32px;
  margin: 0 0 24px;
  text-align: left;
}

.footer__heading {
  margin: 0 0 10px;
  color: var(--text);
  font-size: 1em;
  font-weight: 650;
  letter-spacing: 0.02em;
}

.footer__list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.footer__item + .footer__item {
  margin-top: 7px;
}

.footer__link {
  color: var(--text-muted);
  text-decoration: none;
  /* The underline is drawn on hover rather than removed on hover, so the link
     does not change width when somebody points at it. */
  border-bottom: 1px solid transparent;
  transition: color 0.15s ease, border-color 0.15s ease;
}

.footer__link:hover,
.footer__link:focus-visible {
  color: var(--accent);
  border-bottom-color: currentColor;
}

/* The line above the copyright, and the copyright itself: smaller, centred,
   and separated from the columns by a rule rather than by a gap, so the two
   halves of the footer read as two halves. */
.footer__copyright {
  margin: 0;
  padding-top: 18px;
  border-top: 1px solid var(--border);
  font-size: 0.925em;
  text-align: center;
}

/* Which release this is. Quieter than the copyright above it and sitting
   right under it, so it reads as a note about the page rather than as part of
   the page. */
.footer__version {
  margin: 4px 0 0;
  text-align: center;
  color: var(--muted);
}

.footer__version small {
  font-size: 0.78em;
  letter-spacing: 0.02em;
}

/* With no columns at all — a new site, nothing written in yet — the rule
   above the copyright would be a second line directly under the one at the
   top of the footer. One line is enough. */
.footer__inner > .footer__copyright:only-child {
  padding-top: 0;
  border-top: none;
}

/* On a narrow screen the columns stack, and left-aligned headings in a single
   stacked column read better centred. */
@media (max-width: 520px) {
  .footer {
    padding: 24px 20px 28px;
  }

  .footer__nav {
    grid-template-columns: 1fr;
    gap: 18px;
    text-align: center;
  }
}

/*
 * The note at the foot of the page — about the payment apps, or about Stripe
 * on the checkout. Part of the page it is about rather than part of the
 * footer, so it stays with the card and does not travel to every other page.
 */
.footer__tip {
  max-width: var(--card-width);
  margin: 6px 0;
  padding: 10px 14px;
  background: var(--bg-subtle);
  border-radius: var(--radius);
  color: var(--text-muted);
  font-size: 0.8125em;
  text-align: center;
}

.footer__tip:empty {
  display: none;
}

/* Visibility toggles from settings, applied as body classes so that the
   server render and the editor's live preview stay in agreement. */
.hide-step-numbers .step__number {
  display: none;
}

.hide-footer-tip .footer__tip {
  display: none;
}

/* ===========================================================================
   Steps
   =========================================================================== */

.step + .step {
  margin-top: calc(var(--pad) + 2px);
  padding-top: calc(var(--pad) - 2px);
  border-top: 1px solid var(--border);
}

.step__heading {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 0 0 14px;
  font-size: 0.9375em;
  font-weight: 600;
}

.step__number {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 1.35em;
  height: 1.35em;
  background: var(--bg-subtle);
  border-radius: 50%;
  color: var(--text-muted);
  font-size: 0.8em;
  font-weight: 600;
}

.step__hint {
  margin: -6px 0 12px;
  color: var(--text-muted);
  font-size: 0.8125em;
}

/* ===========================================================================
   Amounts
   =========================================================================== */

.amounts {
  display: grid;
  grid-template-columns: repeat(var(--amount-cols), 1fr);
  gap: var(--gap);
}

.amount {
  padding: 12px 4px;
  background: var(--bg-subtle);
  color: var(--text);
  border: 1px solid transparent;
  border-radius: var(--radius);
  font: inherit;
  font-weight: 550;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

.amount:hover {
  background: var(--bg-subtle-hover);
}

.amount[aria-pressed='true'] {
  background: var(--bg-card);
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-ring);
}

.amount--custom {
  grid-column: 1 / -1;
}

/* ===========================================================================
   Custom amount field
   =========================================================================== */

.field {
  display: block;
  margin-top: 12px;
}

.field__label {
  display: block;
  margin-bottom: 6px;
  color: var(--text-muted);
  font-size: 0.8125em;
  font-weight: 500;
}

.field__input {
  width: 100%;
  padding: 11px 13px 11px 28px;
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  font: inherit;
  font-variant-numeric: tabular-nums;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.field__input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-ring);
}

.field__hint {
  margin: 6px 0 0;
  color: var(--text-muted);
  font-size: 0.75em;
}

/* Same thing, inside a <label> where a <p> would be invalid markup. */
.field__note {
  display: block;
  margin-top: 6px;
  color: var(--text-muted);
  font-size: 0.75em;
  line-height: 1.5;
}

.currency {
  position: relative;
  display: block;
}

.currency__symbol {
  position: absolute;
  top: 50%;
  left: 13px;
  transform: translateY(-50%);
  color: var(--text-muted);
  pointer-events: none;
}

/* ===========================================================================
   Payment methods
   =========================================================================== */

.methods {
  display: flex;
  flex-direction: column;
  gap: var(--gap);
  transition: opacity 0.15s ease;
}

.methods.is-disabled {
  opacity: 0.45;
}

.method {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}

.method__button {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  padding: 13px 15px;
  background: var(--bg-card);
  color: var(--text);
  border: none;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background-color 0.15s ease;
}

.method__button:hover:not(:disabled) {
  background: var(--bg-subtle);
}

.method__button:disabled {
  cursor: not-allowed;
}

.method__text {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

.method__name {
  font-weight: 600;
}

.method__note {
  color: var(--text-muted);
  font-size: 0.75em;
  line-height: 1.35;
}

.method__action {
  flex-shrink: 0;
  padding: 7px 12px;
  background: var(--accent);
  color: var(--accent-text);
  border-radius: calc(var(--radius) * 0.6);
  font-size: 0.8125em;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ===========================================================================
   Expanded detail (Zelle, Apple Cash)
   =========================================================================== */

.method__detail {
  padding: 4px 15px 15px;
  background: var(--bg-card);
  border-top: 1px solid var(--border);
}

/* Label on its own line so long emails get the full width to themselves. */
.copyrow {
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-areas:
    'label button'
    'value value';
  align-items: center;
  gap: 3px 10px;
  margin: 12px 0;
  padding: 10px 12px;
  background: var(--bg-subtle);
  border-radius: calc(var(--radius) * 0.6);
}

.copyrow__label {
  grid-area: label;
  color: var(--text-muted);
  font-size: 0.6875em;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.copyrow__value {
  grid-area: value;
  min-width: 0;
  overflow-wrap: break-word;
  font-size: 0.875em;
  font-weight: 550;
}

.copyrow__button {
  grid-area: button;
  padding: 5px 11px;
  background: var(--bg-card);
  color: var(--text);
  border: 1px solid var(--border-strong);
  border-radius: calc(var(--radius) * 0.45);
  font: inherit;
  font-size: 0.75em;
  font-weight: 600;
  cursor: pointer;
}

.copyrow__button.is-copied {
  color: var(--success);
  border-color: var(--success);
}

.steps {
  margin: 0;
  padding-left: 20px;
  color: var(--text-muted);
  font-size: 0.8125em;
}

.steps li + li {
  margin-top: 5px;
}

.detail__action {
  display: block;
  margin-top: 13px;
  padding: 11px;
  background: var(--accent);
  color: var(--accent-text);
  border-radius: var(--radius);
  font-size: 0.875em;
  font-weight: 600;
  text-align: center;
  text-decoration: none;
}

@media (prefers-reduced-motion: reduce) {
  * {
    transition: none !important;
  }
}

/* Shown inside a payment row when starting a card payment fails. */
.method__error {
  margin: 0;
  padding: 0 15px 12px;
  color: color-mix(in srgb, var(--text) 35%, #b3261e);
  font-size: 0.8125em;
}

/* ===========================================================================
   Result page (after a card payment)
   =========================================================================== */

.result {
  text-align: center;
}

.result__badge {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin: 0 auto 16px;
  background: var(--bg-subtle);
  border-radius: 50%;
  color: var(--success);
  font-size: 1.25em;
}

.result__title {
  margin: 0 0 8px;
  font-size: 1.25em;
  font-weight: 650;
}

.result__body {
  margin: 0;
  color: var(--text-muted);
  font-size: 0.9375em;
}

.link {
  display: inline-block;
  margin-top: 20px;
  color: var(--text);
  font-size: 0.875em;
  text-decoration: none;
  border-bottom: 1px solid var(--border-strong);
  padding-bottom: 1px;
}

.link:hover {
  border-color: var(--accent);
}

.result__badge--muted {
  color: var(--text-muted);
}

/* ===========================================================================
   Home page form
   =========================================================================== */

/* The payment page's amount box has a currency symbol; these don't. */
.field__input--plain {
  padding-left: 13px;
}

.trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form__note {
  margin: 12px 0 0;
  font-size: 0.8125em;
}

.form__note.is-error {
  color: color-mix(in srgb, var(--text) 30%, #b3261e);
}

.form__thanks {
  margin: 0;
  padding: 8px 0;
  color: var(--text);
  font-size: 0.9375em;
  text-align: center;
}

/* A box the height of its text. `overflow-y: hidden` is load-bearing: it is
   what makes scrollHeight the height of the writing rather than the height of
   the box, which is how settings-client.js measures. `min-height` keeps an
   empty one looking like somewhere to write a paragraph, and the drag handle
   goes because there is nothing left for it to do. */
.field__textarea {
  width: 100%;
  min-height: 84px;
  padding: 11px 13px;
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  font: inherit;
  resize: none;
  overflow-y: hidden;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.field__textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-ring);
}

.submit {
  width: 100%;
  margin-top: 18px;
  padding: 13px;
  background: var(--accent);
  color: var(--accent-text);
  border: none;
  border-radius: var(--radius);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  transition: opacity 0.15s ease;
}

.submit:hover:not(:disabled) {
  opacity: 0.88;
}

.submit:disabled {
  opacity: 0.55;
  cursor: progress;
}

/* ===========================================================================
   One-time / monthly choice
   =========================================================================== */

.frequency {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px;
  margin-bottom: var(--gap);
  padding: 4px;
  background: var(--bg-subtle);
  border-radius: var(--radius);
}

.frequency__option {
  padding: 9px 4px;
  background: transparent;
  color: var(--text-muted);
  border: none;
  border-radius: calc(var(--radius) * 0.75);
  font: inherit;
  font-size: 0.875em;
  font-weight: 600;
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
}

.frequency__option[aria-pressed='true'] {
  background: var(--bg-card);
  color: var(--text);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
}

.monthly-note {
  margin: -4px 0 12px;
  color: var(--text-muted);
  font-size: 0.75em;
}

/* ===========================================================================
   The card page (/checkout)
   =========================================================================== */

.checkout-card {
  text-align: center;
}

/* Stripe draws its form inside here. The form itself lives in an iframe, so
   its own colours come from your Stripe branding settings, not from this file. */
.checkout {
  min-height: 220px;
}

.checkout__status {
  margin: 0;
  padding: 24px 0;
  color: var(--text-muted);
  font-size: 0.875em;
}

.checkout__status--error {
  color: var(--text);
  padding: 8px 0 16px;
}

.checkout__back {
  display: inline-block;
  margin-top: 8px;
  color: var(--text-muted);
  font-size: 0.8125em;
  text-decoration: none;
  border-bottom: 1px solid var(--border);
  padding-bottom: 1px;
}

.checkout__back:hover {
  color: var(--text);
  border-color: var(--border-strong);
}

/* ===========================================================================
   Social links
   =========================================================================== */

/* A business's address and hours, under its name. */
.trade {
  display: block;
  margin: 10px 0 0;
  color: var(--text-muted);
  font-size: 0.875em;
  font-style: normal;
  line-height: 1.5;
}

.trade span {
  display: block;
}

/* In the header now, so the spacing is the header's rather than a section's
   of its own. */
.socials {
  width: 100%;
  max-width: var(--card-width);
  margin: 14px auto 0;
  text-align: center;
}

.socials__heading {
  margin: 0 0 8px;
  color: var(--text-muted);
  font-size: 0.8125em;
  font-weight: 500;
}

.socials__row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
}

.socials__link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  color: var(--text-muted);
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  transition: color 0.12s ease, border-color 0.12s ease, transform 0.12s ease;
}

.socials__link:hover {
  color: var(--text);
  border-color: var(--border-strong, var(--text-muted));
  transform: translateY(-1px);
}

.socials__link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.socials__icon {
  width: 20px;
  height: 20px;
  display: block;
}

/* Readable by a screen reader, invisible to everyone else. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ===========================================================================
   An invoice, when the page is showing one
   =========================================================================== */

/* An invoice leaves one step, so the numbering and the divider between the
   two steps stop making sense. */
.is-invoice .step + .step {
  margin-top: 0;
  padding-top: 0;
  border-top: none;
}

.is-invoice .step__number {
  display: none;
}

.is-invoice .header__tagline:empty {
  display: none;
}

.invoice {
  padding-bottom: calc(var(--pad) - 2px);
  margin-bottom: calc(var(--pad) - 8px);
  border-bottom: 1px solid var(--border);
  text-align: center;
}

.invoice__label {
  margin: 0;
  color: var(--text-muted);
  font-size: 0.8125em;
}

.invoice__amount {
  margin: 4px 0 2px;
  font-size: 2.1em;
  font-weight: 650;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}

.invoice__what {
  margin: 0;
  font-size: 0.975em;
}

/* What an invoice is made of, when it carries tax. */
.invoice__lines {
  margin: 12px 0 0;
  padding: 10px 12px;
  background: var(--bg-subtle);
  border-radius: var(--radius);
  font-size: 0.875em;
  text-align: left;
}

.invoice__line {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  color: var(--text-muted);
}

.invoice__line dt,
.invoice__line dd {
  margin: 0;
}

.invoice__line dd {
  font-variant-numeric: tabular-nums;
}

.invoice__line--total {
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px solid var(--border);
  color: var(--text);
  font-weight: 600;
}

/* Who is billing, for a page set up as a business. */
.invoice__from {
  display: block;
  margin: 12px 0 0;
  color: var(--text-muted);
  font-size: 0.8125em;
  font-style: normal;
  text-align: left;
}

.invoice__from span {
  display: block;
}

.invoice__note {
  margin: 10px 0 0;
  padding: 10px 12px;
  background: var(--bg-subtle);
  border-radius: var(--radius);
  color: var(--text-muted);
  font-size: 0.8125em;
  text-align: left;
  white-space: pre-wrap;
}

.invoice__due {
  margin: 10px 0 0;
  color: var(--text-muted);
  font-size: 0.8125em;
}

.invoice__due.is-late {
  color: var(--text);
  font-weight: 550;
}

/* ===========================================================================
   Nothing here (404)
   =========================================================================== */

.result__actions {
  display: grid;
  gap: 4px;
  margin-top: 4px;
}

.result__actions .submit {
  display: block;
  text-align: center;
  text-decoration: none;
}

.result__link {
  justify-self: center;
}

/* ===========================================================================
   Support assistant

   A button fixed to the corner of the page, and the panel it opens. It sits
   above everything, so it is deliberately the only thing on the site with a
   z-index — anything else that needed one would be competing with the help.
   =========================================================================== */

.agent-open {
  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 10px 16px;
  background: var(--accent);
  color: var(--accent-text);
  border: none;
  border-radius: 999px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18);
  font: inherit;
  font-size: 0.875em;
  font-weight: 600;
  cursor: pointer;
  transition: opacity 0.15s ease, transform 0.15s ease;
}

.agent-open:hover {
  opacity: 0.9;
  transform: translateY(-1px);
}

.agent-open__icon {
  width: 15px;
  height: 15px;
  fill: currentColor;
}

.agent {
  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index: 41;
  display: flex;
  flex-direction: column;
  width: min(370px, calc(100vw - 32px));
  max-height: min(560px, calc(100vh - 32px));
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.24);
  overflow: hidden;
}

.agent[hidden] {
  display: none;
}

.agent__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 13px 14px 13px 16px;
  border-bottom: 1px solid var(--border);
}

.agent__title {
  margin: 0;
  font-size: 0.9375em;
  font-weight: 650;
}

.agent__close {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  background: none;
  border: none;
  border-radius: 50%;
  color: var(--text-muted);
  font: inherit;
  font-size: 1.125em;
  line-height: 1;
  cursor: pointer;
}

.agent__close:hover {
  background: var(--bg-subtle);
  color: var(--text);
}

.agent__log {
  flex: 1;
  min-height: 120px;
  padding: 14px 16px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.agent__msg {
  max-width: 88%;
  padding: 9px 12px;
  border-radius: var(--radius);
  font-size: 0.875em;
  line-height: 1.5;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.agent__msg--them {
  align-self: flex-start;
  background: var(--bg-subtle);
  color: var(--text);
}

.agent__msg--you {
  align-self: flex-end;
  background: var(--accent);
  color: var(--accent-text);
}

.agent__msg--problem {
  align-self: flex-start;
  background: none;
  border: 1px solid var(--border);
  color: var(--text-muted);
}

/* Three dots while it is thinking. Kept as text so it needs no extra markup. */
.agent__msg--waiting {
  color: var(--text-muted);
  font-style: italic;
}

.agent__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 0 16px 12px;
}

.agent__chip {
  padding: 7px 11px;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--text);
  font: inherit;
  font-size: 0.8125em;
  cursor: pointer;
  text-align: left;
}

.agent__chip:hover {
  border-color: var(--border-strong);
}

.agent__form {
  display: flex;
  gap: 8px;
  padding: 12px 14px;
  border-top: 1px solid var(--border);
}

.agent__input {
  flex: 1;
  min-width: 0;
  padding: 10px 12px;
  background: var(--bg);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  color: var(--text);
  font: inherit;
  font-size: 0.875em;
}

.agent__input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-ring);
}

.agent__send {
  padding: 0 14px;
  background: var(--accent);
  color: var(--accent-text);
  border: none;
  border-radius: var(--radius);
  font: inherit;
  font-size: 0.875em;
  font-weight: 600;
  cursor: pointer;
}

.agent__send:disabled {
  opacity: 0.5;
  cursor: progress;
}

.agent__foot {
  margin: 0;
  padding: 0 16px 12px;
  color: var(--text-muted);
  font-size: 0.75em;
  text-align: center;
}

/* ===========================================================================
   Events: a goal and how close it is
   =========================================================================== */

.goal {
  padding-bottom: var(--pad);
  margin-bottom: var(--pad);
  border-bottom: 1px solid var(--border);
  text-align: center;
}

.goal__title {
  margin: 0 0 6px;
  font-size: 1.25em;
  font-weight: 650;
}

.goal__blurb {
  margin: 0 0 14px;
  color: var(--text-muted);
  font-size: 0.9375em;
  line-height: 1.5;
  white-space: pre-wrap;
  text-align: left;
}

.goal__bar {
  height: 10px;
  background: var(--bg-subtle);
  border-radius: 999px;
  overflow: hidden;
}

.goal__fill {
  height: 100%;
  min-width: 3px;
  background: var(--accent);
  border-radius: 999px;
  transition: width 0.4s ease;
}

.goal__figures {
  margin: 10px 0 0;
  font-size: 0.9375em;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.goal__figures.is-reached {
  color: var(--success);
}

.goal__ends {
  margin: 4px 0 0;
  color: var(--text-muted);
  font-size: 0.8125em;
}

/* The way in to an event, from the page that advertises it. */
.events {
  display: grid;
  gap: 8px;
  width: 100%;
  max-width: var(--card-width);
  margin: 0 auto 14px;
}

.events__item {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 4px 12px;
  padding: 12px 14px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  color: var(--text);
  text-decoration: none;
  transition: border-color 0.15s ease;
}

.events__item:hover {
  border-color: var(--border-strong);
}

.events__name {
  font-weight: 600;
  font-size: 0.9375em;
}

.events__progress {
  color: var(--text-muted);
  font-size: 0.8125em;
  font-variant-numeric: tabular-nums;
  align-self: center;
}

.events__bar {
  grid-column: 1 / -1;
  height: 6px;
  margin-top: 4px;
  background: var(--bg-subtle);
  border-radius: 999px;
  overflow: hidden;
}

.events__fill {
  display: block;
  height: 100%;
  background: var(--accent);
  border-radius: 999px;
}

/* ===========================================================================
   Reading pages: terms, privacy, about
   =========================================================================== */

/* The gate. Its own card, in the site's theme, with nothing else on the page —
   there is nothing else to show, which is the point. */
.locked {
  width: 100%;
  max-width: 420px;
  text-align: center;
}

.locked__title {
  margin: 0 0 8px;
  font-size: 1.4em;
  font-weight: 650;
  letter-spacing: -0.02em;
}

.locked__blurb {
  margin: 0 0 4px;
  color: var(--text-muted);
  font-size: 0.925em;
  white-space: pre-wrap;
}

/* The wait. Bigger and darker than the date under it, because "opens in 3
   hours" is what somebody at a locked door actually wants to know. */
.locked__countdown {
  margin: 10px 0 2px;
  color: var(--text);
  font-size: 1.0625em;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.locked__until {
  margin: 0 0 14px;
  color: var(--text-muted);
  font-size: 0.8125em;
}

/* With nothing to count down to there is no heading for the date to sit
   under, so it keeps the room the countdown would have had. */
.locked__countdown[hidden] + .locked__until {
  margin-top: 10px;
}

.locked .field {
  text-align: left;
}

/* The trail at the top of a reading page: where this is, and the way back. */
.crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 14px;
  font-size: 0.85em;
  color: var(--text-muted);
}

.crumbs__sep {
  color: var(--border);
}

.crumbs__here {
  color: var(--text-muted);
}

/* Reading pages start at the top whatever the theme says. */
.page--reading {
  align-items: flex-start;
  padding-top: 48px;
  padding-bottom: 48px;
  --page-fill: 0;
}

.prose {
  width: 100%;
  max-width: 680px;
  margin: 0 auto;
  padding: var(--pad);
  background: var(--bg-card);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
}

.prose__title {
  margin: 0 0 4px;
  font-size: 1.5em;
  font-weight: 650;
}

.prose__updated {
  margin: 0 0 24px;
  color: var(--text-muted);
  font-size: 0.8125em;
}

.prose__heading {
  margin: 28px 0 8px;
  font-size: 1.0625em;
  font-weight: 650;
}

.prose__p {
  margin: 0 0 14px;
  font-size: 0.9375em;
  line-height: 1.65;
  /* Single line breaks inside a paragraph are kept, because somebody writing a
     policy in a plain box uses them to mean something. */
  white-space: pre-wrap;
}

.prose__list {
  margin: 0 0 14px;
  padding-left: 22px;
  font-size: 0.9375em;
  line-height: 1.65;
}

.prose__list li {
  margin-bottom: 6px;
}

.prose__nav {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
  margin-top: 28px;
  padding-top: 18px;
  border-top: 1px solid var(--border);
}

.prose__link {
  margin-top: 0;
}

/* The agreement box on the request form. */
.agree__row {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  font-size: 0.875em;
  line-height: 1.5;
}

.agree__link {
  margin-top: 0;
}

/* The About text on the home page, above the form. */
/* The way on to the About page, under the introduction. */
.header__more {
  margin: 10px 0 0;
  font-size: 0.925em;
}

/* ===========================================================================
   Gift lists

   A list is a column of things rather than one card, so it is allowed to be
   wider than a payment page — but it keeps the same colours, the same corners
   and the same type, because it is the same person's page.
   =========================================================================== */

.page--wide .header {
  max-width: 560px;
}

.gifts {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
  max-width: 560px;
}

.gifts__blurb {
  margin: 10px 0 0;
  color: var(--text-muted);
  white-space: pre-line;
}

.gifts__how {
  max-width: 560px;
  margin: 0;
  color: var(--text-muted);
  font-size: 0.86rem;
  text-align: center;
}

.gifts__empty {
  color: var(--text-muted);
}

.gift {
  padding: var(--pad);
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
}

/* Taken things stay on the list — crossing them out is the point — but they
   step back so the things still wanted are what you read. */
.gift--bought {
  opacity: 0.62;
}

.gift__top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.gift__name {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 650;
}

.gift--bought .gift__name {
  text-decoration: line-through;
  text-decoration-thickness: 1px;
}

.gift__mark {
  flex: none;
  padding: 3px 9px;
  border-radius: 99px;
  font-size: 0.72rem;
  font-weight: 650;
  letter-spacing: 0.02em;
  white-space: nowrap;
}

.gift__mark--bought {
  background: var(--bg-subtle);
  color: var(--text-muted);
}

.gift__mark--thinking {
  background: var(--bg-subtle);
  color: var(--text);
}

.gift__note {
  margin: 6px 0 0;
  color: var(--text-muted);
  font-size: 0.88rem;
}

.gift__links {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 12px;
}

.gift__link {
  padding: 6px 12px;
  background: var(--bg-subtle);
  color: var(--text);
  border-radius: 99px;
  font-size: 0.82rem;
  text-decoration: none;
}

.gift__link:hover {
  background: var(--accent);
  color: var(--accent-text);
}

/* The same button as the one that takes a payment, because it is the same
   page and the theme decides what a button looks like here. Left to the
   browser it would come out in the browser's own blue, which belongs to no
   theme anybody chose. */
.gift__take {
  width: 100%;
  margin-top: 14px;
  padding: 12px;
  background: var(--accent);
  color: var(--accent-text);
  border: none;
  border-radius: var(--radius);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  transition: opacity 0.15s ease;
}

.gift__take:hover:not(:disabled) {
  opacity: 0.88;
}

.gift__take:disabled {
  opacity: 0.55;
  cursor: progress;
}

/* The form for saying you have got one. */
.giftbox {
  width: calc(100% - 32px);
  max-width: 460px;
  padding: 0;
  background: var(--bg-card);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}

.giftbox::backdrop {
  background: rgba(0, 0, 0, 0.45);
}

.giftbox__form {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 24px;
}

.giftbox__title {
  margin: 0;
  font-size: 1.1rem;
}

.giftbox__note {
  margin: 0;
  color: var(--text-muted);
  font-size: 0.84rem;
}

.giftbox__row {
  display: flex;
  gap: 10px;
}

.giftbox__row .giftbox__field {
  flex: 1;
  min-width: 0;
}

.giftbox__field {
  display: flex;
  flex-direction: column;
  gap: 5px;
  font-size: 0.82rem;
  color: var(--text-muted);
}

.giftbox__field input {
  padding: 10px 12px;
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font: inherit;
  font-size: 1rem;
}

.giftbox__sure {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0;
  padding: 0;
  border: none;
}

.giftbox__sure legend {
  padding: 0 0 8px;
  color: var(--text-muted);
  font-size: 0.82rem;
}

.giftbox__sure input[type='radio'] {
  margin-top: 2px;
  accent-color: var(--accent);
}

.giftbox__option {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 11px 13px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  cursor: pointer;
}

.giftbox__option:has(input:checked) {
  border-color: var(--accent);
  background: var(--bg-subtle);
}

.giftbox__option > span {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.giftbox__hint {
  color: var(--text-muted);
  font-size: 0.78rem;
}

.giftbox__error {
  margin: 0;
  color: #b3261e;
  font-size: 0.85rem;
}

.giftbox__actions {
  display: flex;
  gap: 8px;
  margin-top: 4px;
}

.giftbox__button {
  flex: 1;
  padding: 12px;
  background: var(--bg-subtle);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  transition: opacity 0.15s ease, background-color 0.15s ease;
}

.giftbox__button:hover:not(:disabled) {
  background: var(--bg-subtle-hover);
}

.giftbox__button--go {
  background: var(--accent);
  color: var(--accent-text);
  border-color: transparent;
}

.giftbox__button--go:hover:not(:disabled) {
  background: var(--accent);
  opacity: 0.88;
}

.giftbox__button:disabled {
  opacity: 0.55;
  cursor: progress;
}

/* ===========================================================================
   Things on a list that are bought here

   A picture, a price and a button. The price is shown broken into its parts
   whenever it has parts, because a total that turns out to have had tax and
   delivery folded into it is where people stop trusting a page.
   =========================================================================== */

.gift__picture {
  display: block;
  width: 100%;
  max-height: 260px;
  margin: 12px 0 0;
  object-fit: contain;
  border-radius: var(--radius);
  background: var(--bg-subtle);
}

.gift__about {
  margin: 10px 0 0;
  color: var(--text);
  font-size: 0.9rem;
  white-space: pre-line;
}

.gift__price {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 12px 0 0;
  font-size: 1.15rem;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
}

.gift__parts {
  color: var(--text-muted);
  font-size: 0.78rem;
  font-weight: 400;
}

.gift__trouble {
  margin: 8px 0 0;
  color: #b3261e;
  font-size: 0.85rem;
}

/* ===========================================================================
   Where your parcel has got to

   Read in a hurry, usually on a phone, usually by somebody who wants one
   fact. The newest line is the loudest thing on the page and everything else
   is below it in the order it happened.
   =========================================================================== */

.track__label {
  margin: 0;
  color: var(--text-muted);
  font-size: 0.8rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.track__state {
  margin: 6px 0 0;
  font-size: 1.05rem;
  font-weight: 600;
}

.track {
  margin-top: var(--gap);
}

.track__steps {
  margin: 0;
  padding: 0 0 0 22px;
  list-style: none;
  border-left: 2px solid var(--border);
}

.step {
  position: relative;
  padding: 0 0 18px;
}

.step:last-child {
  padding-bottom: 0;
}

/* The dot on the line. Drawn rather than bulleted, so the newest one can be
   the filled one without the list changing shape. */
.step::before {
  position: absolute;
  top: 4px;
  left: -29px;
  width: 12px;
  height: 12px;
  background: var(--bg);
  border: 2px solid var(--border);
  border-radius: 50%;
  content: '';
}

.step--now::before {
  background: var(--accent);
  border-color: var(--accent);
}

.step__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}

.step__what {
  font-weight: 600;
}

.step--now .step__what {
  color: var(--accent);
}

.step__when {
  flex: none;
  color: var(--text-muted);
  font-size: 0.8rem;
}

.step__where,
.step__note {
  margin: 3px 0 0;
  font-size: 0.88rem;
}

.step__note {
  color: var(--text-muted);
}

.track__card {
  margin-top: var(--gap);
  padding: var(--pad);
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}

.track__heading {
  margin: 0 0 8px;
  font-size: 0.8rem;
  color: var(--text-muted);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.track__number {
  margin: 0;
  font-size: 1.05rem;
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}

.track__who {
  margin: 4px 0 0;
  color: var(--text-muted);
  font-size: 0.85rem;
}

.track__out {
  display: inline-block;
  margin-top: 10px;
  color: var(--accent);
  font-size: 0.88rem;
}

.track__lines {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 6px 16px;
  margin: 0;
  font-size: 0.92rem;
}

.track__lines dt {
  color: var(--text-muted);
}

.track__lines dd {
  margin: 0;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.track__lines .track__total {
  padding-top: 6px;
  border-top: 1px solid var(--border);
  color: var(--text);
  font-weight: 650;
}

.track__address {
  display: flex;
  flex-direction: column;
  font-size: 0.92rem;
  font-style: normal;
}

.track__note {
  margin: var(--gap) 0 0;
  color: var(--text-muted);
  font-size: 0.85rem;
  text-align: center;
}

/* ===========================================================================
   A page that is a menu

   When a part of a page lives at its own address, these are the ways through
   to it. Big targets, because this is the whole of what some pages are.
   =========================================================================== */

.menu {
  display: block;
  width: 100%;
  max-width: var(--card-width);
  margin: 0 auto var(--gap);
}

.menu__hint {
  margin: 0 0 8px;
  color: var(--text-muted);
  font-size: 0.9em;
  text-align: center;
}

.menu__row {
  display: grid;
  gap: 8px;
}

/* Every way off this page is the same button: the page's own colour, full
   width, one size. A column of identical buttons is the whole idea of a page
   like this — the moment one of them is a different shade, it reads as a
   different kind of thing, and a reader starts wondering what they missed. */
.menu__one,
.links__one {
  display: block;
  padding: 16px 18px;
  background: var(--accent);
  color: var(--accent-text);
  border: 1px solid transparent;
  border-radius: var(--radius);
  font-size: 1.02em;
  font-weight: 600;
  text-align: center;
  text-decoration: none;
  transition: opacity 0.15s ease, transform 0.08s ease;
}

.menu__one:hover,
.links__one:hover {
  opacity: 0.88;
}

.menu__one:active,
.links__one:active {
  transform: scale(0.99);
}

/* A way through to another list of links is not a way off the site, so it is
   drawn as the outline of a button rather than a filled one. The difference
   is deliberate and it is the only one on the page. */
.links__one--list {
  background: transparent;
  color: var(--text);
  border-color: var(--border);
}

.links__one--list:hover {
  opacity: 1;
  background: var(--bg-subtle);
}

/* Said to whoever locked the page, on the page, because they are the one
   person the lock lets through and so the one person who cannot otherwise
   tell it worked. Marked out from the page's own content rather than styled
   to blend in: it is about the page, not part of it. */
.locked-note {
  width: 100%;
  max-width: var(--card-width);
  margin: 0 0 var(--gap);
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-subtle);
  color: var(--text-muted);
  font-size: 0.86em;
  text-align: center;
}

/* What an empty catalogue says. Quiet, because it is a statement of fact to
   whoever made it rather than an apology to a visitor — a visitor is never
   sent here, since the links page only offers the ones with something in. */
.links__nothing {
  margin: 0;
  color: var(--text-muted);
  font-size: 0.9em;
  text-align: center;
}

.links__heading {
  margin: 0 0 2px;
  font-size: 1.05em;
  font-weight: 650;
  text-align: center;
}

.links {
  display: grid;
  gap: 10px;
}

/* Inside the card the links sit above the steps, so they need a parting line
   when there is something under them — and only then. */
.links:not(.links--alone):not(:last-child) {
  margin-bottom: var(--gap);
  padding-bottom: var(--gap);
  border-bottom: 1px solid var(--border);
}

.menu__back {
  margin: var(--gap) 0 0;
  text-align: center;
}

.menu__back a {
  color: var(--text-muted);
  font-size: 0.9em;
  text-decoration: none;
}

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

/* The reference on the something-went-wrong page: there to be read out or
   pasted into a message, so it is set apart and easy to select. */
.result__ref {
  margin-top: 10px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.85em;
  user-select: all;
}
