/*
 *  style.css
 *
 *  One stylesheet for the whole site. It is small enough to stay one file and
 *  read top to bottom, and being one file means the marketing page and the
 *  refund policy cannot drift apart — which is a real risk when the fun page
 *  and the dull pages are maintained months apart.
 *
 *  The palette came from the app: paper rather than white, ink rather than
 *  black, and one warm accent. Nothing here is a brand colour chosen to be a
 *  brand colour; they are the colours a page of text wants to be looked at in
 *  for an hour.
 *
 *  What sits on top of that palette is signage. The mark is an afro, the
 *  colours are already earth and rust, and the page they were arranged on was
 *  a quiet centred essay — which said nothing the mark was saying. So: type
 *  set like a flyer, everything ranged left off one hard edge, corners squared
 *  down to almost nothing, section numbers, and a woven strip that carries the
 *  accent across the page. Loud where a poster is loud, and completely
 *  ordinary where somebody is actually reading — which is why the body text
 *  below is still the system font at a comfortable measure. Condensed caps are
 *  for saying a thing once, not for a refund policy.
 */

/* ---- Colour ---------------------------------------------------------------
 *
 *  Both themes are defined here and chosen by the reader's system setting.
 *  Fro is an app people write in at night, and a white page at 1am is a small
 *  cruelty. The dark values are not the light ones inverted: inverting warm
 *  paper gives cold slate, so the dark palette is warm on its own terms.
 *
 *  Not one of these values changed when the site was restyled. The look is
 *  carried entirely by type, spacing and edges, which is the test of whether a
 *  palette was any good to begin with.
 */

:root {
  --paper: #faf8f5;
  --paper-raised: #fffdfa;
  --ink: #2b2724;
  --ink-soft: #4a423b;
  --quiet: #7a726a;
  --rule: #e7e0d6;
  --accent: #b4643c;
  --accent-soft: #f0e4db;
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper: #171512;
    --paper-raised: #211d19;
    --ink: #ede7df;
    --ink-soft: #c4bbb0;
    --quiet: #948a7e;
    --rule: #322c26;
    --accent: #e08a5c;
    --accent-soft: #2e241d;
  }
}

/* ---- Type -----------------------------------------------------------------
 *
 *  Oswald, self-hosted, Latin only, and variable across the three weights this
 *  site asks for — 21 KB for the lot. It is served from /fonts rather than
 *  from anybody's CDN: a font request to a third party is a request that says
 *  who is reading this page and when, and there is no version of that this
 *  site needs.
 *
 *  It is a condensed gothic in the Alternate Gothic line — the lettering of
 *  bills posted on a wall, of destination boards, of a flyer for a night that
 *  has already happened. It has real lowercase, which is why it is here and
 *  Bebas Neue is not: the same face has to set HOW A READING GETS TAKEN and
 *  also get through the terms of sale without shouting.
 *
 *  font-display: swap means the headline is readable in the fallback before
 *  the file lands. The fallbacks are the nearest condensed faces already on a
 *  Mac, so the swap is a small shift rather than a reflow of the whole page.
 */

@font-face {
  font-family: "Oswald";
  src: url("/fonts/oswald-latin-var.woff2") format("woff2");
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
}

:root {
  --display: "Oswald", "DIN Condensed", "Avenir Next Condensed", "Arial Narrow",
    sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Squared, but not to a hard zero. One or two pixels of radius reads as a
   * cut edge; none at all reads as a browser default nobody chose. */
  --radius: 2px;

  /* The strip. Two accent bars and an ink one on a repeating beat, which is
   * the rhythm of woven cloth rather than a rule — and it is a gradient, so it
   * costs no request and re-colours itself in the dark theme without a second
   * file. The var() calls resolve where the strip is painted, not here. */
  --kente: repeating-linear-gradient(
    90deg,
    var(--accent) 0 18px,
    transparent 18px 26px,
    var(--ink) 26px 32px,
    transparent 32px 44px,
    var(--accent) 44px 50px,
    transparent 50px 62px
  );
}

/* ---- Foundations --------------------------------------------------------- */

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

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 16px/1.6 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  -webkit-font-smoothing: antialiased;
}

/* Every page opens on the weave, edge to edge. It is the one piece of the
 * design that is pure decoration, and it earns its place by being the thing
 * that says whose site this is before a word has been read. */
body::before {
  display: block;
  height: 0.55rem;
  background: var(--kente);
  content: "";
}

/* The measure. 34em is what the legal pages already used, and it is about
 * 70 characters — long enough not to feel clipped, short enough that the eye
 * finds the next line without hunting for it. */
main {
  max-width: 34em;
  margin: 0 auto;
  padding: 0 32px;
}

/* The one exception: sections that want the full width to breathe, like the
 * screenshot and the feature grid — and the home page's <main>, which holds
 * nothing but the hero and so has no measure to keep. */
.wide {
  max-width: 60em;
}

/* Headings are the signage. Condensed, caps, tracked open just enough that the
 * counters do not close up, and set tight against each other — a poster sets
 * its lines touching, not one and a half apart. */
h1,
h2,
h3 {
  font-family: var(--display);
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  text-wrap: balance;
}

h1 {
  margin: 0 0 0.4em;
  font-size: 2em;
}

h2 {
  margin: 2em 0 0.5em;
  font-size: 1.4em;
}

h3 {
  margin: 1.6em 0 0.4em;
  font-size: 1.1em;
  color: var(--ink-soft);
}

/* Paragraphs are not signage. Nothing above applies to them: same system font,
 * same size, same generous line height the site has always had. */
p,
li {
  margin: 0 0 1em;
  text-wrap: pretty;
}

ul {
  margin: 0 0 1em;
  padding-left: 1.2em;
}

li {
  margin: 0 0 0.4em;
}

dl {
  margin: 0 0 1em;
}

dt {
  margin-top: 1.2em;
  font-family: var(--display);
  font-size: 1.05em;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

dd {
  margin: 0;
}

a {
  color: var(--accent);
  text-underline-offset: 0.18em;
}

a:hover {
  text-decoration: none;
}

strong {
  font-weight: 600;
}

code {
  padding: 0.15em 0.4em;
  border-radius: var(--radius);
  background: var(--accent-soft);
  font: 0.9em/1 var(--mono);
}

/* Anything focused by keyboard gets a visible ring. The default one is
 * invisible against warm paper. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: var(--radius);
}

.quiet {
  color: var(--quiet);
}

.lede {
  font-size: 1.05em;
}

.dateline {
  margin: -0.6em 0 2.4em;
  color: var(--quiet);
  font: 0.72rem/1.6 var(--mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* ---- Section labels -------------------------------------------------------
 *
 *  The small line above a heading — 01 / FEATURES — with a hairline running
 *  off to the right margin. It is a wayfinding device borrowed from signage:
 *  it tells you where in the page you are before you have read the heading,
 *  and the rule gives the ranged-left column an edge to sit against.
 *
 *  The numbers are counted by CSS rather than typed into the markup, so
 *  reordering the sections cannot leave two 02s behind.
 */

body {
  counter-reset: section;
}

.eyebrow {
  display: flex;
  gap: 1em;
  align-items: center;
  margin: 0 0 1.4em;
  color: var(--quiet);
  font: 600 0.72rem/1 var(--mono);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  counter-increment: section;
}

.eyebrow::before {
  color: var(--accent);
  content: counter(section, decimal-leading-zero) " /";
}

.eyebrow::after {
  flex: 1;
  height: 1px;
  background: var(--rule);
  content: "";
}

/* ---- Masthead ------------------------------------------------------------ */

/* Wraps rather than overflows. The nav is set in tracked monospaced caps,
 * which is wide, and on a 320px phone it will not sit beside the wordmark —
 * so it drops to its own line instead of pushing the page sideways. */
.masthead {
  display: flex;
  flex-wrap: wrap;
  gap: 0.8em 1.5em;
  align-items: center;
  justify-content: space-between;
  max-width: 60em;
  margin: 0 auto;
  padding: 1.8em 32px 2.6em;
}

/* The icon and the name are one link, so they are one flex box rather than two
 * things that happen to sit next to each other. */
.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  color: var(--ink);
  font-family: var(--display);
  font-size: 1.5em;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-decoration: none;
  text-transform: uppercase;
}

/* img/icon.png is the app's own 1024 icon with the macOS margin and drop shadow
 * cropped away — 826 square out of 1024, which is the tile the icon grid draws
 * on. Left whole it would arrive here as a small mark adrift in a lot of empty
 * space, since a page has no Dock to space icons apart from each other.
 *
 * The file is 512 square; these two lines are what actually decides how big it
 * is drawn, and em rather than px so it tracks the wordmark's own size. */
.wordmark img {
  width: 1.3em;
  height: 1.3em;
}

.masthead nav {
  display: flex;
  gap: 1.6em;
  font: 600 0.72rem/1 var(--mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.masthead nav a {
  padding-bottom: 0.3em;
  border-bottom: 2px solid transparent;
  color: var(--quiet);
  text-decoration: none;
}

.masthead nav a:hover,
.masthead nav a[aria-current="page"] {
  border-bottom-color: var(--accent);
  color: var(--ink);
}

/* ---- Hero -----------------------------------------------------------------
 *
 *  Ranged left, not centred. A centred hero is a poster pinned in the middle
 *  of a wall; this one is pasted against the edge, which is where bills
 *  actually go, and it gives the headline, the sentence and the buttons one
 *  shared left margin to line up on.
 */

.hero {
  padding: 2vh 0 0;
}

.hero h1 {
  margin: 0 0 0.35em;
  font-size: clamp(2.6rem, 1.6rem + 3vw, 4rem);
  line-height: 0.9;
  letter-spacing: 0.012em;
}

/* Only the home page gets the poster size. On the download and support pages
 * the hero sits inside the reading column, where 5.6rem of condensed caps
 * would run "DOWNLOAD FRO" straight off the measure. */
main.wide > .hero h1 {
  font-size: clamp(3rem, 1.4rem + 6.4vw, 5.6rem);
  line-height: 0.88;
}

/* One phrase of the headline gets the accent behind it rather than in it. The
 * text goes to paper on both themes, which is correct in each: rust on cream,
 * and a lighter rust on near-black. */
/* inline-block, not inline. An inline box is painted the full height of the
 * font's own line box, which for a condensed face at line-height 0.88 is
 * considerably taller than the capitals in it — so the block would run up over
 * the line above and read as a printing fault. As an inline-block it carries
 * its own line-height, and the slab is the size of the word inside it. */
.slab {
  display: inline-block;
  padding: 0.1em 0.18em 0.08em;
  background: var(--accent);
  color: var(--paper);
  line-height: 0.78;
}

.hero .tagline {
  max-width: 32em;
  margin: 0 0 2em;
  color: var(--ink-soft);
  font-size: clamp(1.05rem, 0.98rem + 0.4vw, 1.25rem);
  line-height: 1.5;
}

/* ---- Buttons --------------------------------------------------------------
 *
 *  Squared, ruled, and lettered in monospaced caps — a stamped ticket rather
 *  than a soft pill. The border is on both variants and the same width on
 *  both, so the pair sit at exactly the same height and the secondary does not
 *  read as a button that failed to finish loading.
 */

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7em;
  align-items: center;
}

.button {
  display: inline-block;
  padding: 0.85em 1.7em;
  border: 1.5px solid var(--accent);
  border-radius: var(--radius);
  background: var(--accent);
  color: var(--paper);
  font: 600 0.78rem/1 var(--mono);
  letter-spacing: 0.16em;
  text-decoration: none;
  text-transform: uppercase;
  transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}

.button:hover {
  border-color: var(--ink);
  background: var(--ink);
  color: var(--paper);
}

.button.secondary {
  border-color: var(--rule);
  background: transparent;
  color: var(--ink);
}

.button.secondary:hover {
  border-color: var(--accent);
  background: transparent;
  color: var(--accent);
}

/* The line of specification under a set of buttons, and the one above the
 * price. Same voice in both places: small, monospaced, tracked, and stating
 * facts rather than making a case for anything. */
.under-actions,
.price .spec {
  color: var(--quiet);
  font: 0.72rem/1.6 var(--mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.under-actions {
  margin: 1.2em 0 0;
}

.price .spec {
  margin: 0 0 1.1rem;
}

/* ---- Screenshot -----------------------------------------------------------
 *
 *  The soft drop shadow that used to float this off the page is gone. A poster
 *  is flat, and the picture of the app is now a plate ruled onto the sheet —
 *  which also stops the one warm shadow on the page from being the thing that
 *  dates it in two years.
 */

.shot {
  margin: 3.4em auto 0;
  padding: 0 32px;
}

.shot img {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}

.shot figcaption {
  max-width: 42em;
  margin: 1.1em 0 0;
  color: var(--quiet);
  font-size: 0.88em;
}

/* ---- Feature grid --------------------------------------------------------
 *
 *  A claim and the picture of that claim, in one box. The heading and the
 *  sentence are read first and the evidence is directly beneath them, which is
 *  the whole point of the arrangement: a feature list is a promise, and a
 *  feature list with the screenshot attached is a promise you can check.
 *
 *  Each card is numbered, and the numbers are counted rather than typed, so a
 *  card moved or dropped renumbers the rest of them by itself.
 */

.feature-intro {
  margin: 6em auto 0;
  padding: 0 32px;
}

.feature-intro h2 {
  margin: 0 0 0.4em;
  font-size: clamp(2rem, 1.4rem + 2.4vw, 3.2rem);
  line-height: 0.95;
}

.feature-intro p {
  max-width: 38em;
  margin: 0;
  color: var(--ink-soft);
  font-size: 1.05em;
}

.features {
  display: grid;
  gap: 1.2em;
  /* min() rather than a bare 19em: on a narrow phone the track floor would
   * otherwise be wider than the screen and the whole grid would hang off the
   * right edge. Capped at 100%, a single column simply fits. */
  grid-template-columns: repeat(auto-fit, minmax(min(19em, 100%), 1fr));
  margin: 2.6em auto 0;
  padding: 0 32px;
  counter-reset: card;
}

/* The image is flush with the card's bottom edge and clipped by its corner
 * radius, so a shot looks like it carries on past the card rather than sitting
 * in it — which is what stops nine boxes in a row from reading as nine slides.
 *
 * Every card image is 1520x800 and every card has the same padding, so the one
 * thing that can make a card taller than its neighbour is the length of the
 * paragraph. Letting the paragraph grow into the spare height keeps the images
 * on a line with each other. */
.card {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding: 1.6em 1.6em 0;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--paper-raised);
  counter-increment: card;
}

.card h3 {
  margin: 0 0 0.5em;
  color: var(--ink);
  font-size: 1.25em;
  line-height: 1;
}

/* The number belongs to the label, not to the sentence: monospaced, accent,
 * and on its own line above the heading rather than running into it. */
.card h3::before {
  display: block;
  margin-bottom: 0.5em;
  color: var(--accent);
  font: 600 0.7rem/1 var(--mono);
  letter-spacing: 0.16em;
  content: counter(card, decimal-leading-zero);
}

.card p {
  flex: 1;
  margin: 0;
  color: var(--ink-soft);
  font-size: 0.94em;
}

.card img {
  display: block;
  width: 100%;
  height: auto;
  margin: 1.6em 0 0;
  border: 1px solid var(--rule);
  border-bottom: 0;
  border-radius: var(--radius) var(--radius) 0 0;
}

/* The two claims no screenshot can make. Without an image to weigh them down
 * they would sit at the top of a tall box with a lot of nothing under them, so
 * they get their padding back and centre what little they have. */
.card.plain {
  justify-content: center;
  padding-bottom: 1.6em;
}

/* A card with a picture wants its paragraph to grow into the spare height so
 * the pictures line up. A card without one wants the opposite: let the
 * paragraph stay its natural size, and the two lines then sit in the middle of
 * a box that is as tall as its neighbour rather than clinging to the top of it. */
.card.plain p {
  flex: 0 1 auto;
}

/* Nine cards into two columns leaves the ninth on its own with an empty half
 * beside it, which reads as a card that failed to load. The last one runs the
 * full width instead, and because it is the "you can leave whenever you like"
 * card, ending on it deliberately is no loss. In one column the rule does
 * nothing, which is the right amount. */
.features .card:last-child {
  grid-column: 1 / -1;
}

/* Being twice as wide does not mean the sentence should be twice as long. The
 * paragraph keeps roughly the measure it has in a narrow card. */
.features .card:last-child p {
  max-width: 42em;
}

/* ---- Price ----------------------------------------------------------------
 *
 *  The band is closed top and bottom by the weave rather than by a hairline.
 *  It is the one place on the page asking for money, and the strip is what
 *  marks it off as its own thing without a box around it or a colour the
 *  palette does not have.
 */

.price {
  margin: 5em auto 0;
  padding: 2.8em 32px 3em;
  background-image: var(--kente), var(--kente);
  background-position: top left, bottom left;
  background-repeat: repeat-x, repeat-x;
  background-size: 100% 0.55rem;
}

.price .amount {
  margin: 0 0 0.7rem;
  font-family: var(--display);
  font-size: clamp(3.4rem, 2rem + 5vw, 5.4rem);
  font-weight: 600;
  line-height: 0.9;
  letter-spacing: 0.01em;
}

/* The price it is not, beside the price it is. Struck, smaller, and in the
 * quiet colour, so the eye lands on the figure that will actually be charged
 * and only then works out why it is lower. */
.price .amount .was {
  margin-right: 0.34em;
  color: var(--quiet);
  font-size: 0.42em;
  font-weight: 400;
  text-decoration: line-through;
  text-decoration-thickness: 0.05em;
}

/* The band is 60em wide because the grid above it is. That is a width for
 * pictures, not for sentences, so everything in here that is read keeps a
 * column of its own. In rem, not em: these elements set their own font-size,
 * and an em measure would silently shrink with it. */
.price p:not(.amount):not(.eyebrow) {
  max-width: 34rem;
}

.price ul {
  max-width: 32rem;
  margin: 1.6em 0 2em;
  padding: 0;
  color: var(--ink-soft);
  font-size: 0.94em;
  list-style: none;
}

/* A ruled tick rather than a bullet: the same accent mark the cards number
 * themselves with, so the page has one vocabulary of small marks. */
.price li {
  margin: 0 0 0.55em;
  padding-left: 1.4em;
  text-indent: -1.4em;
}

.price li::before {
  display: inline-block;
  width: 1.4em;
  color: var(--accent);
  font-family: var(--mono);
  text-indent: 0;
  content: "—";
}

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

footer {
  max-width: 60rem;
  margin: 5em auto 0;
  padding: 1.6em 32px 4em;
  border-top: 1px solid var(--rule);
  color: var(--quiet);
  font: 0.72rem/2.2 var(--mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

footer a {
  color: var(--quiet);
  text-decoration: none;
}

footer a:hover {
  color: var(--accent);
  text-decoration: underline;
}

footer span {
  color: var(--ink);
}

/* Legal pages set their own top padding; the marketing page starts with a
 * masthead instead. */
.doc {
  padding-top: 2vh;
  padding-bottom: 2em;
}

/* A page of terms is read, not looked at. It keeps the site's headings and the
 * site's marks, and gives back everything else: the h1 comes down to somewhere
 * near a document title, and nothing on it is set in condensed caps for longer
 * than a line. */
.doc h1 {
  font-size: 2.4em;
}

.doc h2 {
  font-size: 1.2em;
}

/* Support's questions all hang off one "Frequently asked questions" heading,
 * so by the outline they are h3. They are still the lines a reader scans the
 * page for, though, so they take back the size and the full-strength ink an h2
 * has everywhere else; only the heading above them is allowed to be larger. */
.faq h2 {
  font-size: 1.7em;
}

.faq h3 {
  margin: 2em 0 0.5em;
  font-size: 1.4em;
  color: var(--ink);
}

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