/* Design decisions applied on top of the mirrored Squarespace CSS.
 *
 * Kept in its own file so what is "the old site" and what is "a change we
 * made" never get confused, and so any of it can be lifted out in one move.
 *
 * ---------------------------------------------------------------------
 * SECONDARY BUTTON — soft grey fill
 *
 * Before: black fill (identical to primary) with 2rem vertical against
 * 1.6rem horizontal padding, giving a 173×91 slab that read as a squashed
 * primary rather than a quieter tier.
 *
 * After: lightAccent #F4F4F3 with black text — 19.08:1, so legibility is
 * not in question — at primary's padding rhythm so both tiers share a
 * 59px height. The hover darkens the fill rather than changing hue, which
 * is what stops a pale fill reading as disabled.
 */

:root {
  /* padding first, through the site's own variables rather than around them */
  --secondary-button-padding-x: 3.1rem;
  --secondary-button-padding-y: 1rem;
  --secondaryButtonBackgroundColor: #f4f4f3;
  --secondaryButtonTextColor: #000000;
}

/* Colour needs the same selector list the site uses for its own button
   rules; anything less specific loses to the theme block. */
#siteWrapper.site-wrapper .sqs-button-element--secondary,
.sqs-modal-lightbox .sqs-modal-lightbox-content .sqs-button-element--secondary,
body .sqs-block-form-lightbox .form-button-wrapper .sqs-button-element--secondary {
  background-color: #f4f4f3;
  color: #000000;
  border: 0;
  transition: background-color 0.15s ease;
}

#siteWrapper.site-wrapper .sqs-button-element--secondary:hover,
.sqs-modal-lightbox .sqs-modal-lightbox-content .sqs-button-element--secondary:hover,
body .sqs-block-form-lightbox .form-button-wrapper .sqs-button-element--secondary:hover {
  background-color: #e4e4e2;
  color: #000000;
}

#siteWrapper.site-wrapper .sqs-button-element--secondary:focus-visible {
  outline: 2px solid #000000;
  outline-offset: 3px;
}

/* ---------------------------------------------------------------------
 * HOMEPAGE — the nav row sits midway between the top and the tiles
 *
 * The header floats over the page (position: absolute), and the runtime
 * made room for it by padding the first section with the header's height,
 * which the scrape froze inline at its 1440 value, 193.016px. The gallery
 * then adds its own 3.3vw above the tiles. So the space under the nav row
 * was the header's lower padding plus whatever the frozen number and the
 * 3.3vw came to: 98px against 50px above it at 1440, 104 against 23 at 390,
 * and 146 against 23 once the announcement bar was dismissed, because the
 * header shrinks by the bar and the frozen padding does not.
 *
 * The header's own padding above and below its row is equal, so the row is
 * centred between the top (the bar's foot, or the page top without it) and
 * the tiles exactly when the tiles start at the header's bottom edge. So,
 * as /herald does, the header takes its place in the flow and the frozen
 * padding and the gallery's top padding go: the tiles then start where the
 * header ends at every width, with the bar or without it, and with no
 * script to measure anything. Homepage only (`homepage` is on its body and
 * no other page's). */
body.homepage #header {
  position: relative;
}

body.homepage article.sections > section.page-section:first-child {
  padding-top: 0 !important;
}

body.homepage article.sections > section.page-section:first-child .portfolio-grid-overlay {
  padding-top: 0;
}

/* ---------------------------------------------------------------------
 * NAVIGATION — Wallpapers leaves the site
 *
 * The Wallpapers item goes to Gumroad in a new tab (2026-09-24), and says so
 * with a small arrow after the word: IBM Plex Mono's own U+2197, so it is the
 * nav's type and colour, set at three quarters of the item's size and raised
 * so its tip stands at the capitals' height, as a mark rather than a letter.
 * In ems, so it follows the header's nav and the larger mobile menu alike.
 * The words "(opens in a new tab)" after it are for a screen reader only.
 */
.mp-nav-out {
  position: relative;
  top: -0.18em;
  margin-left: 0.1em;
  font-size: 0.75em;
}

/* ---------------------------------------------------------------------
 * GALLERY — a lone tile spans the grid
 *
 * The gallery is being rebuilt one app at a time and holds a single tile for
 * now. In the site's two-column grid that tile sat in the left column with
 * nothing beside it, which reads as a tile gone missing rather than as a
 * gallery of one. While it is alone it takes both columns at 2:1. As soon as
 * a second tile exists this stops matching, and the grid is the site's own
 * square two-up again.
 *
 * An icon tile is excluded, and that exclusion is the point of the selector:
 * the tiles are now an app's icon on a shared ground, and a square icon
 * stretched across two columns at 2:1 is not a wide tile, it is a stretched
 * icon. The rule is kept rather than deleted because it earns its place again
 * the next time the gallery is down to a single tile that is a picture.
 */

#gridThumbs .grid-item:only-child:not(.grid-item--icon) {
  grid-column: 1 / -1;
  padding-bottom: 50%;
}

#gridThumbs .grid-item:only-child:not(.grid-item--icon) .grid-image {
  padding-bottom: 50%;
}

/* ---------------------------------------------------------------------
 * GALLERY — the app's name, at the second heading size
 *
 * The site's own label is the app name alone, in white DIN over a black
 * overlay, and both are opacity 0 until the tile is hovered. A second line
 * saying what each app is was tried under the name and taken out
 * (2026-09-24, Adam): the name is the label, and it is set larger instead.
 * The site sizes the label at its heading-3 value; here it takes the
 * heading-2 value through the site's own formula, so it grows and shrinks
 * with the viewport exactly as every h2 on the site does.
 */

#gridThumbs {
  --portfolio-grid-overlay-title-font-font-size-value: var(--heading-2-size-value);
}

/* A label that exists only on hover does not exist on a phone, where there is
   no pointer to hover with: the name was invisible there, on every tile.
   Where the pointer cannot hover it is always shown.
 *
 * Not as the hover shows them, though. On hover the site lays its 75% black
 * over the whole tile and centres the label on it, which is fine for a
 * moment under a pointer and would leave a phone with four black squares.
 * So on touch the label moves to the tile's foot, the quiet band under the
 * icon that gallerytile.py leaves for it, and is set in black straight on
 * the ground, with no overlay at all (Adam, 2026-10-04: the 75% black
 * fading up behind it read as a smear). The ground is known, the site's
 * #F4F4F3 graded a few levels, so black on it is 19:1 everywhere.
 *
 * The label is a column flexbox (the site's), so its foot is justify-content.
 * An earlier version used align-items, which in a column is the cross axis:
 * it pushed each line to the right edge instead, over the icon.
 *
 * The label is one line, the name at the heading-2 size, and starts below
 * the icon at every width (at 390 the icon ends 23px above it). */
@media (hover: none) {
  #gridThumbs .grid-item .portfolio-text {
    opacity: 1;
    top: auto;
    justify-content: flex-end;
    padding: 2.5rem 7% 0.75rem;
    background: none;
  }

  #gridThumbs .grid-item .portfolio-title {
    color: #000;
  }
}

/* The announcement bar's close button. Squarespace's was a "×" in
   Helvetica at weight 100 and the bar's 13px, in a 36px box pinned to the
   bar's top: a hairline speck sitting 3px above the words' middle, its
   target under 44px, and in a face the page uses nowhere else.
 *
 * Now the box is the bar's whole height and 44px wide, and the cross is two
 * strokes drawn in the words' colour, as tall as their capitals (0.7em) and
 * a little firmer than their stems (0.1em), centred on the bar's middle.
 * Its right edge stands on the page's margin, where the header's last item
 * (the nav, or the menu button) ends, so the bar and the header share one
 * edge: the box reaches past the margin by what the 44px leaves either side
 * of the cross. */
.sqs-announcement-bar .sqs-announcement-bar-close {
  top: 0;
  bottom: 0;
  height: auto;
  width: 44px;
  right: calc(var(--pagePadding) - 22px + 0.35em);
}

@media only screen and (pointer: coarse) and (max-width: 1024px), screen and (max-width: 799px) {
  .sqs-announcement-bar .sqs-announcement-bar-close {
    right: calc(6vw - 22px + 0.35em);
  }
}

.sqs-announcement-bar .sqs-announcement-bar-close::before,
.sqs-announcement-bar .sqs-announcement-bar-close::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0.89em;
  height: 0.1em;
  padding: 0;
  background: currentColor;
  transform: translate(-50%, -50%) rotate(45deg);
}

.sqs-announcement-bar .sqs-announcement-bar-close::after {
  transform: translate(-50%, -50%) rotate(-45deg);
}

/* The announcement bar's foot, where the page under it is as dark as the
   bar (graft.BAR_EDGE says which pages and why): a 1px hairline inside the
   bar's own box, so nothing moves, and gone with the bar when it is
   dismissed. White at 12% reads as a quiet edge on the near-black pages;
   8% all but vanished and 16% read as a border. The light one is the
   site's #e4e4e2, for a light bar over a light page, which no page has. */
body.mp-bar-edge-dark .sqs-announcement-bar {
  box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.12);
}

body.mp-bar-edge-light .sqs-announcement-bar {
  box-shadow: inset 0 -1px 0 #e4e4e2;
}

/* The footer's wordmark is one word and never breaks. On About and Support
   its block spans four of the 24 columns (the homepage's spans six), which
   from 768 to about 930 is narrower than the word, and the site's
   overflow-wrap: break-word split it as "micropixe / ls". The columns to its
   right are empty up to the social icons, so it simply runs on into them. */
main p.header-title-text {
  white-space: nowrap;
}

/* The footer's icons are one row, too. Five of them (Threads and last.fm
   joined Dribbble, Twitter and GitHub, 2026-09-24) take 176px, more than
   their block at 1024, 768 and 390 on About and Support and at 768 and 390
   on the homepage, where the site's flex-wrap dropped GitHub, or two, onto
   a second line. The row stays against the block's right edge and runs on to
   the left, into the empty columns between it and the wordmark. The
   component stylesheet's rule names the block, so this names it too. */
main .sqs-block[data-definition-name="website.components.socialLinks"] .sqs-svg-icon--list {
  flex-wrap: nowrap;
}

/* ...at their own size: on one line in too narrow a block, flexbox would
   otherwise shrink them, to 10px at 768 on About. */
main .sqs-block[data-definition-name="website.components.socialLinks"] .sqs-svg-icon--wrapper {
  flex-shrink: 0;
}

/* The icons are quiet at rest: a grey, not the footer's black or white,
   and the full colour again under the pointer and on keyboard focus
   (2026-09-24, Adam: they stood out too much). #7d7d7d on the light
   footers (4.1:1 on Support's white, 3.7:1 on the homepage's #f4f4f3) and
   #6d6d6d on About's black (4.1:1), both over WCAG's 3:1 for an icon. The
   block colours each icon through its own custom properties, set by a rule
   naming the block's id, so these name #siteWrapper to outrank it; when a
   sibling is hovered Squarespace draws the rest with the "fade" colour,
   which is the rest grey too, so only the icon under the pointer changes. */
#siteWrapper main .sqs-block[data-definition-name="website.components.socialLinks"] .sqs-svg-icon--wrapper {
  --mp-social-rest: #7d7d7d;
  --si-fill-icon: var(--mp-social-rest);
  --si-fill-icon-fade: var(--mp-social-rest);
  --si-fill-icon-hover: var(--si-primary);
}

#siteWrapper main [data-section-theme="black"] .sqs-block[data-definition-name="website.components.socialLinks"] .sqs-svg-icon--wrapper {
  --mp-social-rest: #6d6d6d;
}

#siteWrapper main .sqs-block[data-definition-name="website.components.socialLinks"] .sqs-svg-icon--wrapper:focus-visible {
  --si-fill-icon: var(--si-primary);
  --si-fill-icon-fade: var(--si-primary);
}

main .sqs-block[data-definition-name="website.components.socialLinks"] .sqs-use--icon {
  transition: fill 0.15s ease;
}

@media (prefers-reduced-motion: reduce) {
  main .sqs-block[data-definition-name="website.components.socialLinks"] .sqs-use--icon {
    transition: none;
  }
}

/* The footer's wordmark links home (build_mirror.footer_home_link, and
   graft.footer on the rebuilt pages), and looks exactly as it did: the
   paragraph's colour, no underline, on hover too. A ring shows on keyboard
   focus only, in the wordmark's own colour. */
#siteWrapper main p.header-title-text > a.mp-foot-home,
#siteWrapper main p.header-title-text > a.mp-foot-home:hover {
  color: inherit;
  text-decoration: none;
  background: none;
  border: 0;
}

a.mp-foot-home:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 4px;
}

a.mp-foot-home:focus:not(:focus-visible) {
  outline: none;
}

/* ---------------------------------------------------------------------
 * SUPPORT FORM — attachments, errors, sending, thanks
 *
 * The form is the mirrored Squarespace one, sent to NepTunes' support
 * pipeline by support-form.js. Everything added to it is built out of the
 * site's own form parts rather than drawn fresh: the attachment picker is a
 * .custom-form-element, which the site's stylesheet already gives the
 * fields' border, radius, padding, fill and hover; the error bars are
 * .form-field-error, which it already gives the fields' radius; and the
 * thanks is .form-submission-text, which it already gives its colour and
 * its entrance.
 *
 * What is left here is colour and size. Squarespace's own form draws an
 * error as white on red (#ce2c30) with the field tinted pink. This page is
 * monochrome, so the bar is white on black and the invalid field takes the
 * site's light grey fill, the same #f4f4f3 as the secondary button.
 */

/* The type roles, as the site sizes them. The site sets these on input,
   textarea and .description with !important inside two media queries; they
   are repeated as variables so the new parts can share them exactly. */
@media screen and (max-width: 767px) and (orientation: portrait) {
  .sqs-site-style-form {
    --mp-input-size: calc((var(--form-block-input-text-font-font-size-value) - 1) * calc(.012 * min(100vh, 900px)) + 1rem);
    --mp-description-size: calc((var(--form-block-description-text-font-font-size-value) - 1) * calc(.012 * min(100vh, 900px)) + 1rem);
  }
}
@media screen and (min-width: 768px), screen and (orientation: landscape) {
  .sqs-site-style-form {
    --mp-input-size: min(calc((var(--form-block-input-text-font-font-size-value) - 1) * 1.2vw + 1rem), max(calc((var(--form-block-input-text-font-font-size-value) - 1) * 0.012 * var(--maxPageWidth) + 1rem), calc(var(--form-block-input-text-font-font-size-value) * 1rem)));
    --mp-description-size: min(calc((var(--form-block-description-text-font-font-size-value) - 1) * 1.2vw + 1rem), max(calc((var(--form-block-description-text-font-font-size-value) - 1) * 0.012 * var(--maxPageWidth) + 1rem), calc(var(--form-block-description-text-font-font-size-value) * 1rem)));
  }
}

/* The honeypot. Its hiding rule lives in a stylesheet served from
   assets.squarespace.com; if that ever stops loading, a visible honeypot is a
   field real people fill in, and their messages are then silently dropped
   as spam. So it is hidden here as well. */
form[data-support-form] .btIyKrvyA6dTrftg {
  position: absolute;
  left: -5000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
}

.mp-visually-hidden,
.sqs-site-style-form form[data-support-form] .form-item input.mp-file-input {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  margin: -1px !important;
  padding: 0 !important;
  border: 0 !important;
  overflow: hidden !important;
  clip-path: inset(50%) !important;
  white-space: nowrap !important;
}

/* ---------------------------------------------------------------------
 * SEARCH — an h1 drawn as the h2 it was
 *
 * About's "Hello." and Support's "Support" were h2 on live, and neither page
 * had an h1. They are the h1 now (build_mirror.one_h1), and look exactly as
 * before: the site sets h1 and h2 apart only by size, line height and
 * colour, so this gives the h1 the h2's three, through the site's own
 * formulas for heading 2 (2-site.css). Everything else (face, weight,
 * spacing, case, margins) is the same rule for h1 and h2 already.
 */
h1.mp-h1-as-h2 {
  line-height: calc(var(--heading-font-line-height) * (1 + (1 - var(--heading-2-size-value))/25));
  color: var(--headingLargeColor);
}
@media screen and (max-width: 767px) and (orientation: portrait) {
  h1.mp-h1-as-h2 {
    font-size: calc((var(--heading-2-size-value) - 1) * calc(.012 * min(100vh, 900px)) + 1rem);
  }
}
@media screen and (min-width: 768px), screen and (orientation: landscape) {
  h1.mp-h1-as-h2 {
    font-size: min(calc((var(--heading-2-size-value) - 1) * 1.2vw + 1rem), max(calc((var(--heading-2-size-value) - 1) * 0.012 * var(--maxPageWidth) + 1rem), calc(var(--heading-2-size-value) * 1rem)));
  }
}

/* The hint beside "Attachments" is the same small grey role as "(required)"
   beside the others, and sits on the label's baseline the same way. */
.sqs-block[data-definition-name="website.components.form"] .form-wrapper .field-list .description.mp-hint {
  padding: 0;
}

/* The picker: a field-shaped drop target the input's own label draws, with
   "Choose files" inside it drawn as a compact secondary button, so that it
   reads as something to press rather than as text in an empty field.

   The zone stays a field: the site's border, radius, fill and hover, and
   the same height as the email field above it. That height comes from the
   line box (the input size at the body's 1.6em, 31.13px at 1440) plus the
   field's 5px padding and 1px border, 43.13px, and the button fills exactly
   that line box, so the zone cannot grow past the other fields. Its left
   padding matches the 5px above and below it, so the button sits on an
   even inset.

   The button is the secondary button (#f4f4f3 fill, black text, #e4e4e2
   on hover, 7.2px radius, the DIN stand-in at 400 with no tracking, which
   is what the Send button's computed style resolves to) at the input's
   size rather than the button's 1.5rem, with a short run of padding. It is
   not a <button>: the real control is still the visually hidden file
   input, which keeps the one tab stop, the "Attachments" name and the
   native picker, and this whole label, button included, opens it. */
.sqs-site-style-form form[data-support-form] .form-item .mp-file-pick {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  column-gap: 1.25ex;
  width: 100%;
  box-sizing: border-box;
  padding-left: 5px;
  cursor: pointer;
  container-type: inline-size;
  font-family: var(--form-block-input-text-font-font-family);
  font-size: var(--mp-input-size);
  line-height: var(--form-block-input-text-font-line-height);
  letter-spacing: var(--form-block-input-text-font-letter-spacing);
  color: #000;
}

.sqs-site-style-form form[data-support-form] .mp-file-pick-label {
  flex: none;
  display: block;
  padding: 0 0.85em;
  border-radius: var(--secondary-button-rounded-border-top-left-radius, 7.2px);
  background-color: #f4f4f3;
  color: #000;
  font-family: var(--secondary-button-font-font-family, "din-condensed-web");
  font-weight: var(--secondary-button-font-font-weight, 400);
  font-style: normal;
  letter-spacing: var(--secondary-button-font-letter-spacing, 0em);
  text-transform: none;
  /* the zone's line box, in px, whatever this font size is */
  line-height: inherit;
  white-space: nowrap;
  transition: background-color 0.15s ease;
}

/* Hovering anywhere in the zone presses on the button, since anywhere in
   the zone opens the picker. */
.sqs-site-style-form form[data-support-form] .mp-file-pick:hover .mp-file-pick-label {
  background-color: #e4e4e2;
}

.sqs-site-style-form form[data-support-form] .mp-file-pick-drop {
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  opacity: 0.55;
}

/* There is nothing to drag from on a phone. And where the zone is too
   narrow for the button and the whole phrase (about 16.5em of the zone's
   own type, with "Add more files" in the button), the phrase goes rather
   than being cut: at 390 the zone still has 18em, at 360 it has 16.3. The
   ellipsis above is only a backstop. */
@media (hover: none) {
  .sqs-site-style-form form[data-support-form] .mp-file-pick-drop {
    display: none;
  }
}

@container (max-width: 17em) {
  .sqs-site-style-form form[data-support-form] .mp-file-pick-drop {
    display: none;
  }
}

/* Focus sits on the hidden input, so the button draws it, as the secondary
   button does: 2px of black. Its offset is 1px rather than the secondary's
   3px, which would lay the ring against the zone's own border 5px out;
   at 1px it keeps 2px clear of that border. */
.sqs-site-style-form form[data-support-form] .mp-file-input:focus-visible + .mp-file-pick .mp-file-pick-label {
  outline: 2px solid #000;
  outline-offset: 1px;
}

/* A drag in progress: the zone takes the grey fill and a dashed border, and
   the button the hover grey, so it stays a shape on the grey. */
.sqs-site-style-form form[data-support-form] .form-item .mp-file-pick.mp-dragging {
  background-color: #f4f4f3;
  border-style: dashed;
}

.sqs-site-style-form form[data-support-form] .mp-file-pick.mp-dragging .mp-file-pick-label {
  background-color: #e4e4e2;
}

/* The chosen files: one row each, name, size and a way to take it back out. */
.sqs-site-style-form form[data-support-form] .mp-file-list {
  margin: 10px 0 0;
  padding: 0;
  list-style: none;
  font-family: var(--form-block-description-text-font-font-family);
  font-size: var(--mp-description-size);
  line-height: 1.5;
  letter-spacing: var(--form-block-description-text-font-letter-spacing);
}

.sqs-site-style-form form[data-support-form] .mp-file-list[hidden] {
  display: none;
}

.sqs-site-style-form form[data-support-form] .mp-file {
  display: flex;
  align-items: baseline;
  column-gap: 1.5ex;
  margin: 0;
  padding: 8px 0;
  border-bottom: 1px solid #e4e4e2;
}

.sqs-site-style-form form[data-support-form] .mp-file:first-child {
  border-top: 1px solid #e4e4e2;
}

.sqs-site-style-form form[data-support-form] .mp-file-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow-wrap: anywhere;
}

.sqs-site-style-form form[data-support-form] .mp-file-size {
  flex: none;
  opacity: 0.7;
  white-space: nowrap;
}

.sqs-site-style-form form[data-support-form] .mp-file-remove {
  flex: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  letter-spacing: inherit;
  color: #000;
  text-decoration: underline;
  text-underline-offset: 0.2em;
  cursor: pointer;
}

.sqs-site-style-form form[data-support-form] .mp-file-remove:focus-visible {
  outline: 2px solid #000;
  outline-offset: 2px;
}

/* An invalid field keeps its border and takes the light grey fill. */
.sqs-site-style-form form[data-support-form] .form-item.mp-invalid input:not([type=checkbox]):not([type=radio]),
.sqs-site-style-form form[data-support-form] .form-item.mp-invalid textarea {
  background-color: #f4f4f3;
}

/* The error bar, under a field or under the button: Squarespace's own
   layout (a mark, then the text, 6px by 10px), in black and white. */
.sqs-site-style-form form[data-support-form] .mp-field-error,
.sqs-site-style-form form[data-support-form] .mp-form-status {
  display: flex;
  align-items: flex-start;
  column-gap: 10px;
  margin: 8px 0 0;
  padding: 6px 10px;
  background: #000;
  color: #fff;
  font-family: var(--form-block-description-text-font-font-family);
  font-size: var(--mp-description-size);
  line-height: 1.5;
  letter-spacing: var(--form-block-description-text-font-letter-spacing);
  overflow-wrap: anywhere;
}

.sqs-site-style-form form[data-support-form] .mp-form-status {
  margin-top: 16px;
}

.sqs-site-style-form form[data-support-form] .mp-field-error[hidden],
.sqs-site-style-form form[data-support-form] .mp-form-status[hidden] {
  display: none;
}

.sqs-site-style-form form[data-support-form] .mp-error-icon {
  flex: none;
  width: 1em;
  height: 1em;
  margin-top: 0.25em;
}

.sqs-site-style-form form[data-support-form] .mp-form-status a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

/* Sending: the label says so, and the button stops answering. */
.sqs-site-style-form form[data-support-form][aria-busy="true"] .form-submit-button {
  cursor: progress !important;
  opacity: 0.7;
}

/* The thanks that replaces the form. The form's wrapper is display:grid
   from an id-scoped rule in the block's own <style>, which outranks the
   [hidden] attribute, so hiding it needs saying outright. */
.sqs-site-style-form .form-wrapper[hidden] {
  display: none !important;
}

.sqs-site-style-form .mp-thanks {
  font-family: var(--form-block-input-text-font-font-family);
  font-size: var(--mp-input-size);
  line-height: var(--form-block-input-text-font-line-height);
  letter-spacing: var(--form-block-input-text-font-letter-spacing);
}

.sqs-site-style-form .mp-thanks:focus {
  outline: none;
}

.sqs-site-style-form .mp-thanks p {
  margin: 0 0 0.75em;
}

.sqs-site-style-form .mp-thanks p:last-child {
  margin-bottom: 0;
}

.sqs-site-style-form .mp-thanks h3.mp-thanks-title {
  margin: 0 0 0.5em;
}

/* Without its script the form cannot send, so its button ships disabled and
   this line says where to write instead. */
.sqs-site-style-form .mp-noscript {
  margin: 16px 0 0;
  font-family: var(--form-block-description-text-font-font-family);
  font-size: var(--mp-description-size);
  line-height: 1.5;
  letter-spacing: var(--form-block-description-text-font-letter-spacing);
}

.sqs-site-style-form .mp-noscript a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

/* The site dims a disabled primary button to 0.8, with a 0.1s fade. Where
   script runs, the shipped disabled state lasts only until support-form.js
   has loaded, and a first paint in between would fade the button in. Until
   the script marks the form (aria-busy is set from then on), it keeps its
   full weight. With no script at all it stays dimmed, as it should. */
@media (scripting: enabled) {
  .sqs-site-style-form form[data-support-form]:not([aria-busy]) .form-submit-button[disabled] {
    opacity: 1 !important;
  }
}

/* ---------------------------------------------------------------------
 * SUPPORT FAQ — app, question, answer
 *
 * The old site answered these in a Squarespace accordion at the foot of
 * each app page. They are on /support now, above the form, as a tree that
 * faq.py renders from panelsrc/faq/<app>.md: the app is the first level,
 * each question the second, and the groups inside an app are small
 * subheadings that do not fold. It is <details>/<summary>, so it works with
 * no script, and it is scoped by its own mp-faq classes because this file
 * also loads on /herald, /batfi and /design-system.
 *
 * The look is the old accordion's, which this page already had: 1px rules
 * between the rows, 15px above and below each title, 30px under an answer,
 * and a 1px plus on the right that is a minus while the row is open. The
 * plus is 14px against a question, as it was, and 20px against the app's
 * name, which is set half as large again.
 *
 * The type is the site's own roles, not new ones. The app's name is the
 * site's h3, a question is the site's h4 size in the heading face (the
 * element is an h5, because it sits under the group's h4 and the page's
 * h2), a group is the Meta role the site sets code in, and an answer is the
 * body paragraph. The rules are black around an app and the light grey the
 * form's file list uses between questions, so the two levels read as two.
 * Nothing here is coloured: this is one of the three monochrome pages.
 */

/* The sizes, as the site computes them: the h3 size for the app, the h4 size
   for a question and the normal Meta size for a group, in the same two media
   queries the site's own h3, h4 and code rules use. */
@media screen and (max-width: 767px) and (orientation: portrait) {
  .mp-faq {
    --mp-faq-q-size: calc((var(--heading-4-size-value) - 1) * calc(.012 * min(100vh, 900px)) + 1rem);
    --mp-faq-app-size: calc((var(--heading-3-size-value) - 1) * calc(.012 * min(100vh, 900px)) + 1rem);
    --mp-faq-meta-size: calc((var(--normal-meta-size-value) - 1) * calc(.012 * min(100vh, 900px)) + 1rem);
  }
}
@media screen and (min-width: 768px), screen and (orientation: landscape) {
  .mp-faq {
    --mp-faq-q-size: min(calc((var(--heading-4-size-value) - 1) * 1.2vw + 1rem), max(calc((var(--heading-4-size-value) - 1) * 0.012 * var(--maxPageWidth) + 1rem), calc(var(--heading-4-size-value) * 1rem)));
    --mp-faq-app-size: min(calc((var(--heading-3-size-value) - 1) * 1.2vw + 1rem), max(calc((var(--heading-3-size-value) - 1) * 0.012 * var(--maxPageWidth) + 1rem), calc(var(--heading-3-size-value) * 1rem)));
    --mp-faq-meta-size: min(calc((var(--normal-meta-size-value) - 1) * 1.2vw + 1rem), max(calc((var(--normal-meta-size-value) - 1) * 0.012 * var(--maxPageWidth) + 1rem), calc(var(--normal-meta-size-value) * 1rem)));
  }
}

.mp-faq {
  border-bottom: 1px solid #000;
  color: #000;
}

.mp-faq-app {
  border-top: 1px solid #000;
}

.mp-faq summary {
  display: flex;
  justify-content: space-between;
  column-gap: 1em;
  padding: 15px 0;
  list-style: none;
  cursor: pointer;
}

.mp-faq summary::-webkit-details-marker {
  display: none;
}

.mp-faq summary:focus-visible {
  outline: 2px solid #000;
  outline-offset: 2px;
}

/* A linked question is scrolled to with a little air above it. */
.mp-faq details {
  scroll-margin-top: 1rem;
}

.mp-faq .mp-faq-app-summary {
  align-items: center;
}

.mp-faq .mp-faq-app-title {
  margin: 0;
}

/* An app's link target: an empty anchor at the top of its branch, so that a
   link to it opens the branch with no script (faq.py says why). Its scroll
   margin is the app's row above it, so the row lands where a linked
   question's does, 1rem under the top: the rule, 15px, the h3's line box
   (its size times 1.2em * (1 + (1 - 2.2) / 25), which is 1.1424) and 15px. */
.mp-faq .mp-faq-anchor {
  display: block;
  /* An empty box lets the first group heading's margin collapse through it,
     which put the anchor 15px down the branch instead of at its top. A
     pixel of height stops that, and the pixel is handed back below. */
  height: 1px;
  margin-bottom: -1px;
  scroll-margin-top: calc(1px + 15px + var(--mp-faq-app-size) * 1.1424 + 15px + 1rem);
}


/* "Expand all" / "Collapse all", in an app's row beside the plus (faq.js
   adds it, and without script it does not exist). It is outside the
   <summary>, before the <details> in the branch's wrapper, and laid over
   the row: as tall as the row, so the whole height is its target, and
   20px (the plus's own size) left of the plus. It is the Meta role, as a
   group's title is, but full black and underlined like the answers' links,
   since it is a thing to press. Its box is the width of "Collapse all"
   (twelve characters of the monospaced Meta face), with the words set to
   its right, so the right edge stays put when they change; the app's name
   keeps that much clear, so a long name cannot run under it. */
.mp-faq {
  --mp-faq-all-w: calc(var(--mp-faq-meta-size) * 7.2);
}

.mp-faq .mp-faq-branch {
  position: relative;
}

.mp-faq .mp-faq-all {
  position: absolute;
  top: 1px;
  right: 40px;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  width: var(--mp-faq-all-w);
  height: calc(15px + var(--mp-faq-app-size) * 1.1424 + 15px);
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  color: #000;
  font-family: var(--meta-font-font-family);
  font-size: var(--mp-faq-meta-size);
  font-style: var(--meta-font-font-style);
  font-weight: var(--meta-font-font-weight);
  line-height: var(--meta-font-line-height);
  letter-spacing: var(--meta-font-letter-spacing);
  text-transform: var(--meta-font-text-transform);
  white-space: nowrap;
  cursor: pointer;
}

.mp-faq .mp-faq-all-label {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}

.mp-faq .mp-faq-all:hover .mp-faq-all-label {
  text-decoration-thickness: 2px;
}

.mp-faq .mp-faq-all:focus-visible {
  outline: 2px solid #000;
  outline-offset: 2px;
}

.mp-faq--all .mp-faq-app-title {
  margin-right: calc(var(--mp-faq-all-w) + 20px);
}

.mp-faq .mp-faq-group-title {
  margin: 15px 0 12px;
  font-family: var(--meta-font-font-family);
  font-size: var(--mp-faq-meta-size);
  font-style: var(--meta-font-font-style);
  font-weight: var(--meta-font-font-weight);
  line-height: var(--meta-font-line-height);
  letter-spacing: var(--meta-font-letter-spacing);
  text-transform: var(--meta-font-text-transform);
  /* the grey of the form's own "(required)" */
  opacity: 0.7;
}

.mp-faq .mp-faq-group + .mp-faq-group .mp-faq-group-title {
  margin-top: 30px;
}

.mp-faq .mp-faq-item {
  border-top: 1px solid #e4e4e2;
}

.mp-faq .mp-faq-item:last-child {
  border-bottom: 1px solid #e4e4e2;
}

/* The app's last question closes on the app's own black rule, not on a grey
   one with a second rule under it. */
.mp-faq .mp-faq-group:last-child .mp-faq-item:last-child {
  border-bottom: 0;
}

.mp-faq .mp-faq-q {
  align-items: flex-start;
}

.mp-faq .mp-faq-q-title {
  margin: 0;
  font-family: var(--heading-font-font-family);
  font-size: var(--mp-faq-q-size);
  font-style: var(--heading-font-font-style);
  font-weight: var(--heading-font-font-weight);
  line-height: calc(var(--heading-font-line-height) * (1 + (1 - var(--heading-4-size-value)) / 25));
  letter-spacing: var(--heading-font-letter-spacing);
  text-transform: var(--heading-font-text-transform);
}

/* The plus: two 1px strokes. Open, the upright one folds away. */
.mp-faq .mp-faq-icon {
  --mp-faq-icon: 14px;
  position: relative;
  flex: none;
  width: var(--mp-faq-icon);
  height: var(--mp-faq-icon);
}

.mp-faq .mp-faq-app-summary .mp-faq-icon {
  --mp-faq-icon: 20px;
}

/* Centred on a question's first line, however many lines it runs to. The
   line box is the h4's: its size times 1.2em * (1 + (1 - 1.5) / 25). */
.mp-faq .mp-faq-q .mp-faq-icon {
  margin-top: calc((var(--mp-faq-q-size) * 1.176 - var(--mp-faq-icon)) / 2);
}

.mp-faq .mp-faq-icon::before,
.mp-faq .mp-faq-icon::after {
  content: "";
  position: absolute;
  background: currentColor;
}

.mp-faq .mp-faq-icon::before {
  left: 0;
  right: 0;
  top: calc(50% - 0.5px);
  height: 1px;
}

.mp-faq .mp-faq-icon::after {
  top: 0;
  bottom: 0;
  left: calc(50% - 0.5px);
  width: 1px;
  transition: transform 0.15s ease;
}

.mp-faq details[open] > summary > .mp-faq-icon::after {
  transform: scaleY(0);
}

@media (prefers-reduced-motion: reduce) {
  .mp-faq .mp-faq-icon::after {
    transition: none;
  }
}

.mp-faq .mp-faq-a {
  padding: 0 0 30px;
}

.mp-faq .mp-faq-a p {
  margin: 0;
}

.mp-faq .mp-faq-a p + p {
  margin-top: 1rem;
}

/* The site's own content link: a 1px underline 0.2em below. A long URL
   breaks rather than pushing a phone sideways. */
.mp-faq .mp-faq-a a {
  color: inherit;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
  overflow-wrap: anywhere;
}

.mp-faq .mp-faq-a a:focus-visible {
  outline: 2px solid #000;
  outline-offset: 2px;
}

/* The space under the FAQ is the space under the heading above it.
 *
 * The heading "Support" spans two rows of Support's grid and does not fill
 * them, and what it leaves over is part of the distance from the heading to
 * whatever comes next: 54, 43, 37 and 24px at 1440, 1024, 768 and 390. The
 * FAQ sits in a row of its own that grows to fit it, so it leaves nothing
 * over, and the paragraph under it came out 4, 1, 0 and 13px closer than the
 * FAQ is to the heading. So the FAQ's block keeps a margin of exactly what
 * the heading leaves over: two rows and the gap between them, less the
 * heading's line box, never below zero. The rows and the gap are the grid's
 * own (24px and 11px under 768, and from 768 its --container-width times
 * its --row-height-scaling-factor), and the line box is the site's h2: its
 * size times 1.2em * (1 + (1 - 3.5) / 25), which is 1.08. */
@media screen and (max-width: 767px) and (orientation: portrait) {
  .fe-block-mp-faq {
    --mp-h2-line: calc(((var(--heading-2-size-value) - 1) * calc(.012 * min(100vh, 900px)) + 1rem) * 1.08);
  }
}
@media screen and (min-width: 768px), screen and (orientation: landscape) {
  .fe-block-mp-faq {
    --mp-h2-line: calc(min(calc((var(--heading-2-size-value) - 1) * 1.2vw + 1rem), max(calc((var(--heading-2-size-value) - 1) * 0.012 * var(--maxPageWidth) + 1rem), calc(var(--heading-2-size-value) * 1rem))) * 1.08);
  }
}

.fe-block-mp-faq {
  margin-bottom: max(0px, 2 * 24px + 11px - var(--mp-h2-line));
}

@media (min-width: 768px) {
  .fe-block-mp-faq {
    margin-bottom: max(0px, 2 * var(--container-width) * var(--row-height-scaling-factor) + 11px - var(--mp-h2-line));
  }
}

/* ---------------------------------------------------------------------
 * SUPPORT — the footer on white, under a rule
 *
 * Support's last section, which carries the wordmark and the social icons,
 * is on the site's white theme now (in rendered/support.html), the same
 * white as the form above it, so what sets it apart is a 1px rule in the
 * FAQ's light grey: as wide as the wordmark and icons' own columns, the
 * page's margins, not the window. It is a pseudo-element placed in the
 * footer's layout grid, across the same columns the blocks use, so it
 * follows the site's margins (4vw, 6vw under 768) and its 1500px cap
 * without a number of its own. Scoped by the section's id, which only
 * /support has.
 *
 * The space from the Send button to the rule is twice what it was: the
 * form's section ended 3.3vmax under the button (the site's section padding)
 * and now ends 6.6vmax under it, so it scales with the window as before. */
section[data-section-id="65323164587bc764c7106d3a"] .fluid-engine::before {
  content: "";
  grid-area: 1 / 2 / 2 / -2;
  align-self: start;
  border-top: 1px solid #e4e4e2;
}

/* the id outranks the site's rule, whose four :not()s make it heavy */
#siteWrapper section[data-section-id="64b5ae7ce4173639c07c7283"] > .content-wrapper {
  padding-bottom: 6.6vmax;
}

/* ---------------------------------------------------------------------
 * NEWSLETTER — field and button, one line where they fit
 *
 * The sign-up block on / and /about, as newsletter-form.js wires it (the
 * form carries data-newsletter-form, so nothing else is touched).
 *
 * The field and the button together are as wide as the description above
 * them: the body takes the header's width (85% and centred in the
 * homepage's centred block, the whole width in About's left-aligned one,
 * and the whole width below 321px, where the site widens the header too),
 * and the field takes whatever the button leaves. Squarespace had the field
 * a fixed 18rem, well short of the paragraph on a desktop, and stacked the
 * two on the homepage at every width.
 *
 * They sit on one line wherever the field keeps at least 12rem, and go
 * under each other, both the full width, where it would not. That is plain
 * flex wrapping, no breakpoint: the field's basis is 12rem, and the button
 * grows only 1/9999 as eagerly as the field, so on one line it keeps its
 * own width (a hundredth of a pixel more) and on a line of its own it
 * fills it. On the homepage that is one line at 1024 and up; at 768 its
 * block is narrow enough that the paragraph is 260px, so there, as on a
 * phone, they stack.
 *
 * The button's geometry is the design system's and does not change. The
 * field adapts: the site gives both the same padding and line height
 * (1.4rem 2rem, 1.2rem), which on the button makes 4rem, but on the field
 * the input's text box and its 1px border made it 66px to 72px. So the
 * field is 4rem, border included, with its text centred in it, and the
 * two are vertically centred on each other. */
.newsletter-block form[data-newsletter-form] .newsletter-form-body {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 0.5rem;
  width: 85%;
  margin: 1.5rem auto 0;
  padding: 0 0 1.5rem;
}

/* ...and it goes when the thanks takes its place: the site hides it with
   .hidden, which the display above would otherwise outrank */
.newsletter-block form[data-newsletter-form] .newsletter-form-body.hidden {
  display: none;
}

.newsletter-block .newsletter-form-wrapper--alignLeft form[data-newsletter-form] .newsletter-form-body,
.newsletter-block .newsletter-form-wrapper--alignRight form[data-newsletter-form] .newsletter-form-body {
  width: 100%;
}

@media screen and (max-width: 320px) {
  .newsletter-block form[data-newsletter-form] .newsletter-form-body {
    width: 100%;
  }
}

.newsletter-block form[data-newsletter-form] .newsletter-form-fields-wrapper {
  display: block;
  flex: 9999 1 12rem;
  min-width: 12rem;
  margin: 0;
}

/* a phone too narrow for even 12rem still gets the field, at its width */
@media screen and (max-width: 320px) {
  .newsletter-block form[data-newsletter-form] .newsletter-form-fields-wrapper {
    min-width: 0;
  }
}

.newsletter-block form[data-newsletter-form] .newsletter-form-field-wrapper {
  display: block;
  width: 100%;
  min-width: 0;
  max-width: none;
  padding: 0;
}

.newsletter-block form[data-newsletter-form] .newsletter-form-field-element {
  box-sizing: border-box;
  height: calc(1.4rem * 2 + 1.2rem);
  padding-top: 0 !important;
  padding-bottom: 0 !important;
}

.newsletter-block form[data-newsletter-form] .newsletter-form-button-wrapper {
  display: block;
  flex: 1 0 auto;
  margin: 0;
  padding: 0;
}

.newsletter-block form[data-newsletter-form] .newsletter-form-button {
  width: 100%;
}

/* Squarespace's empty captcha slot would otherwise take a line of its own */
.newsletter-block form[data-newsletter-form] .captcha-container:empty {
  display: none;
}

/* The honeypot: out of sight and out of the tab order (it has tabindex -1
   and sits under aria-hidden), but in the form, so a bot filling every
   field fills it. */
.newsletter-block form[data-newsletter-form] .mp-honeypot {
  position: absolute;
  left: -5000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
}

/* The error bar: Support's, a mark then the text on black, in the block's
   description type, the width of the field and button above it. */
.newsletter-block form[data-newsletter-form] .mp-form-status {
  display: flex;
  align-items: flex-start;
  column-gap: 10px;
  box-sizing: border-box;
  width: 85%;
  margin: 0 auto 1rem;
  padding: 6px 10px;
  background: #000;
  color: #fff;
  font-family: var(--newsletter-block-description-text-font-font-family);
  font-size: 0.9rem;
  line-height: 1.5;
  letter-spacing: var(--newsletter-block-description-text-font-letter-spacing);
  text-align: left;
  overflow-wrap: anywhere;
}

.newsletter-block .newsletter-form-wrapper--alignLeft form[data-newsletter-form] .mp-form-status,
.newsletter-block .newsletter-form-wrapper--alignRight form[data-newsletter-form] .mp-form-status {
  width: 100%;
}

@media screen and (max-width: 320px) {
  .newsletter-block form[data-newsletter-form] .mp-form-status {
    width: 100%;
  }
}

.newsletter-block form[data-newsletter-form] .mp-form-status[hidden] {
  display: none;
}

.newsletter-block form[data-newsletter-form] .mp-error-icon {
  flex: none;
  width: 1em;
  height: 1em;
  margin-top: 0.25em;
}

.newsletter-block form[data-newsletter-form] .mp-form-status a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

/* An invalid address keeps its border and takes the light grey fill, as on
   Support. */
.newsletter-block form[data-newsletter-form] .newsletter-form-field-element[aria-invalid="true"] {
  background-color: #f4f4f3;
}

/* Squarespace's own "Thank you!", which the script shows in place of the
   field and the button: the description's type, a little larger. */
.newsletter-block form[data-newsletter-form] .form-submission-text {
  margin: 1.5rem 0 0.5rem;
  font-family: var(--newsletter-block-description-text-font-font-family);
  font-size: 1.25rem;
  letter-spacing: var(--newsletter-block-description-text-font-letter-spacing);
}

.newsletter-block form[data-newsletter-form] .form-submission-text:focus {
  outline: none;
}

/* Until the script has run, Sign Up is disabled, as the markup ships it:
   without script it stays so, and says why in the line under the form. */
.newsletter-block .mp-noscript {
  margin: 0.5rem 0 0;
  font-family: var(--newsletter-block-footnote-text-font-font-family);
  font-size: 0.9rem;
  line-height: 1.5;
}

.newsletter-block .mp-noscript a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.newsletter-block form[data-newsletter-form] .newsletter-form-button[disabled] {
  cursor: default;
}

.newsletter-block form[data-newsletter-form][aria-busy="true"] .newsletter-form-button {
  cursor: progress;
}
