/*
 * The site uses the application's palette, deliberately.
 *
 * Someone who downloads Buuk after reading this page should recognise it. A
 * marketing site in different colours from the product it sells is a promise
 * the first launch breaks.
 *
 * The tokens are copied rather than imported: this page must be servable as
 * static files with no build step, and one duplicated palette is a smaller
 * cost than a build pipeline for a page of HTML. `docs/DESIGN.md` in the app is
 * the source of truth if they ever drift.
 */

:root {
  color-scheme: light;
  --bg-0: #fcfbf8;
  --bg-1: #f7f5f1;
  --bg-2: #eae7e0;
  --bg-3: #d6cfc4;
  --paper: #fffefb;
  --bd: #c1b8a8;
  --ink-0: #2f2b26;
  --ink-1: #655f57;
  --ink-2: #938c84;
  --accent: #ba3608;
  --accent-soft: #e8430a;
  --measure: 34rem;
}

@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;
    --bg-0: #181c23;
    --bg-1: #222832;
    --bg-2: #2d3542;
    --bg-3: #3a4454;
    --paper: #1e242d;
    --bd: #0f1218;
    --ink-0: #e2e7ee;
    --ink-1: #aeb8c6;
    --ink-2: #828d9c;
    --accent: #cf3c09;
    --accent-soft: #f66634;
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg-0);
  color: var(--ink-0);
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

.wrap { max-width: 1400px; margin: 0 auto; padding: 0 1.5rem; }

/* Header ------------------------------------------------------------------ */

header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.25rem 0;
}

/*
 * The logo, inlined so it can follow the theme.
 *
 * It is `Assets/SVG/Buuk Logo_1.svg` pasted in whole, wordmark and quill in
 * the one viewBox, which is what keeps the quill sitting on the wordmark's
 * baseline: the alignment is the one that was drawn, not one reconstructed
 * here out of two boxes and a guess at where the baseline falls.
 *
 * The source gives the quill a fill and leaves the wordmark without one, so
 * the wordmark would render at the browser default black — which disappears
 * against the dark ground. Inlined, its paths take `.logo-word` and
 * `currentColor` so they follow the ink, and the quill takes `.logo-mark` and
 * the accent. As an <img> neither fill could be reached at all.
 */
.mark { display: inline-flex; align-items: center; color: var(--ink-0); }
.logo { height: 34px; width: auto; display: block; }
.logo .logo-word { fill: currentColor; }
.logo .logo-mark { fill: var(--accent); }

/*
 * The footer carries the "by Codira" lockup rather than the plain mark — the
 * footer is where a page says who made it.
 *
 * 48px, and that is a deliberate reversal of what this rule used to say.
 *
 * The art is the same drawing on a taller canvas: identical width, the quill at
 * identical coordinates, 83.55 units tall instead of 65.64 to fit the second
 * line. Scaling to keep the wordmark at its old size gives 33px — but at 33px
 * "by Codira" is about five pixels of cap height and reads as a smudge rather
 * than as words. Compared at 33 / 40 / 48 / 56 / 64, it clears at 48 and is
 * unambiguous at 64.
 *
 * So the footer mark is deliberately larger than the header's: its wordmark
 * lands at 37px against the header's 25px. The old note here said the footer's
 * was the quieter of the two, and that is no longer true — which is the right
 * trade, because the attribution is the whole reason this lockup is here. An
 * illegible credit is decoration pretending to be a credit.
 */
.logo-footer { height: 64px; margin-bottom: 0.75rem; color: var(--ink-1); }

/*
 * The quill turns on its own vertical axis, once every fifteen seconds.
 *
 * rotateY, not rotate. A plain `rotate()` is rotation about Z — the axis
 * pointing out of the screen — which cartwheels the quill onto its side. The
 * mark should stay upright and turn the way an object on a turntable does, so
 * the axis has to be the vertical one.
 *
 * One revolution in 7.5 seconds, then eight seconds still, repeating: a
 * 15.5-second cycle that is turning for a little under half of it. The turn
 * itself is linear — a turntable holds its speed — so the keyframes carry the
 * rest rather than the easing, holding at 360 degrees from 48.3871% (7.5s of
 * 15.5s) to the end. Rest written into the timeline repeats; an
 * `animation-delay` would only quieten the first cycle.
 *
 * `transform-box: fill-box` makes the origin the quill's OWN bounding box
 * rather than the whole SVG's viewport. Without it the mark swings around the
 * wordmark instead of turning in place, because it sits at the right-hand end
 * of a 175-unit canvas it shares with the letters.
 *
 * The turn is orthographic. `perspective` on the <svg> does not reach a path
 * inside it — an SVG element does not propagate a 3D rendering context to its
 * SVG children, so the transform is flattened and rotateY degrades to a
 * horizontal squeeze. Real depth would mean lifting the quill out into its own
 * <svg> positioned over the wordmark, in all four lockups, at both sizes — and
 * that is exactly the split that loses the drawn baseline. Not worth it for a
 * trapezoid under a pixel deep on an 18px mark.
 *
 * The backface is left visible. Halfway through the turn you are looking at
 * the back of the quill, which is what a turntable shows you.
 */
@keyframes quill-turn {
  0%                { transform: rotateY(0deg); }
  48.3871%, 100%    { transform: rotateY(360deg); }
}

.logo .logo-mark {
  transform-box: fill-box;
  transform-origin: center;
  animation: quill-turn 15.5s linear infinite;
}

/* Someone who has asked their system for less motion gets a still mark. */
@media (prefers-reduced-motion: reduce) {
  .logo .logo-mark { animation: none; }
}

nav { display: flex; gap: 1.5rem; align-items: center; }
nav a { color: var(--ink-1); text-decoration: none; font-size: 0.875rem; }
nav a:hover { color: var(--ink-0); }

.button {
  display: inline-block;
  background: var(--accent);
  /* Light labels on accent fills, always — the house rule from the app. */
  color: #fff;
  text-decoration: none;
  font-size: 0.875rem;
  font-weight: 600;
  padding: 0.55rem 1.1rem;
  border-radius: 5px;
}
.button:hover { opacity: 0.9; }
.button.quiet { background: var(--bg-2); color: var(--ink-0); }

/* Hero -------------------------------------------------------------------- */

.hero { padding: 5rem 0 4rem; }

/*
 * The hero art, and the closer's.
 *
 * The hero was already built to a measure — `.hero p` caps at `--measure` —
 * so on a wide screen its right-hand half was empty. The illustration goes
 * there rather than above or below the words. That is the only reason the copy
 * is wrapped in `.hero-copy`: a grid needs one element per column, and the
 * paragraphs were loose children.
 *
 * Same 3fr/2fr as `.showcase`, so the hero's art and the section art below it
 * come out the same size. Sized off the column rather than a `min()` of rem
 * and vw: at the 1400px wrap a fixed rem cap left the hero art visibly
 * smaller than every illustration under it.
 *
 * `.arc` stays a direct child and spans both columns. It is the strip along
 * the bottom of the hero, not the last line of the left column.
 *
 * Wrapping the copy does not disturb the specificity trap noted below. `.hero
 * p` is a descendant selector, so it still reaches the paragraphs a level
 * deeper, and still at (0,1,1).
 *
 * Both images are ornament: the page says everything they say in words a line
 * or two away. So they take `alt=""` and a screen reader steps over them
 * rather than narrating a decoration. Both carry intrinsic width and height so
 * the space is reserved before they arrive and nothing jumps.
 */
.hero {
  display: grid;
  grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
  gap: 0 3.5rem;
  align-items: center;
}
.hero-copy { min-width: 0; }
.hero .arc { grid-column: 1 / -1; }
.hero-art { width: 100%; height: auto; justify-self: end; }

/*
 * A section split between a piece of art and its copy.
 *
 * Not `.split` — that name was already the fiction/nonfiction panel pair
 * further down, and reusing it silently handed these sections that layout.
 *
 * 3fr/2fr rather than half and half: the art is one object and reads at a
 * smaller size than a column of text needs to stay comfortable.
 *
 * The art always comes second in the DOM, whichever side it lands on, so the
 * stacked layout leads with the words rather than making someone on a phone
 * scroll past a picture to reach the heading. `.art-left` moves it with
 * `order` and flips the ratio; the wide column stays the copy's either way.
 *
 * The copy keeps a cap of its own — 40rem rather than `--measure`, because the
 * column beside a picture can take a longer line than a full-width block of
 * prose. Without any cap it runs to 95 characters at the 1400px wrap.
 */
.showcase { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: 3.5rem; align-items: center; }
.showcase-art { width: 100%; height: auto; }
.showcase-copy > :first-child { margin-top: 0; }
.showcase-copy p { max-width: 40rem; }

/*
 * Art on the left is the variant, not the default. The art is always second in
 * the DOM; `order` moves it, and the column ratio flips with it so the wide
 * column stays the copy's either way.
 */
.showcase.art-left { grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); }
.showcase.art-left .showcase-art { order: -1; }

@media (max-width: 52rem) {
  .showcase, .showcase.art-left { grid-template-columns: 1fr; gap: 2rem; }
  .showcase.art-left .showcase-art { order: 0; }
  .showcase-art { width: min(20rem, 70%); margin: 0 auto; }
}


/*
 * Two columns need room the width of the measure plus the art plus the gap.
 * Below that the art drops under the copy and comes in off its own cap rather
 * than a share of the viewport, so it does not shrink to a thumbnail on a
 * phone.
 */
@media (max-width: 52rem) {
  .hero { grid-template-columns: 1fr; }
  .hero-art { justify-self: center; width: min(17rem, 62%); margin-top: 2.5rem; }
}

/*
 * Headings break their own lines.
 *
 * Two things control this and they are easy to confuse. `max-width` decides
 * how many lines a heading gets; `text-wrap: balance` only decides where the
 * breaks fall once that number is fixed. Balance cannot rescue a cap that is
 * too tight — at 22ch the longest headline here got three lines and broke as
 * "AI Should Assist / the Author, Not / Replace the Author", and balance had
 * evened those out as well as it could. 34ch gives it two.
 *
 * So the rule is: if a headline breaks badly, widen the cap first and let
 * balance tidy what is left. Checking only for a stranded last word will miss
 * this entirely, because three cramped lines can be perfectly balanced.
 *
 * It is a hint, not a layout rule: browsers that do not have it ignore it and
 * wrap greedily, exactly as before, and those that do give up past about six
 * lines. Both are fine — it is only ever tidying a heading.
 */
h1 {
  font-family: 'Source Serif 4', 'Iowan Old Style', Georgia, serif;
  font-size: clamp(2.5rem, 6vw, 4rem);
  line-height: 1.08;
  font-weight: 400;
  margin: 0 0 1.25rem;
  max-width: 18ch;
  text-wrap: balance;
}

.lede {
  font-size: 1.2rem;
  color: var(--ink-1);
  max-width: var(--measure);
  margin: 0 0 2rem;
}

.arc {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 0.9rem;
  margin: 3.5rem 0 0;
  font-size: 0.8rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.arc span::after { content: ' →'; color: var(--accent-soft); }
.arc span:last-child::after { content: ''; }

/* Sections ---------------------------------------------------------------- */

section { padding: 4rem 0; border-top: 1px solid var(--bd); }

h2 {
  font-family: 'Source Serif 4', 'Iowan Old Style', Georgia, serif;
  font-size: clamp(1.6rem, 3.5vw, 2.2rem);
  font-weight: 400;
  line-height: 1.2;
  margin: 0 0 1rem;
  max-width: 34ch;
  text-wrap: balance;
}

section p { max-width: var(--measure); color: var(--ink-1); margin: 0 0 1rem; }
section p strong { color: var(--ink-0); font-weight: 600; }

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1.5rem;
  margin-top: 2.5rem;
}

.card { background: var(--bg-1); border-radius: 6px; padding: 1.25rem; }
.card h3 { font-size: 0.95rem; margin: 0 0 0.4rem; }
.card p { font-size: 0.875rem; margin: 0; color: var(--ink-2); }

/* A quoted example of what the software actually says. */
.said {
  background: var(--paper);
  border-left: 2px solid var(--accent-soft);
  border-radius: 0 4px 4px 0;
  padding: 0.9rem 1.1rem;
  margin: 1.5rem 0;
  max-width: var(--measure);
  font-size: 0.9rem;
  color: var(--ink-1);
}
.said code { font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 0.85em; }

/*
 * A 64-character SHA-256 is one unbreakable token, and min-content width made
 * the whole column as wide as it — 177px of horizontal scroll on a phone, on
 * the download page. Let it break anywhere; a hash has no words to keep whole.
 */
code { overflow-wrap: anywhere; }

/* Pricing ----------------------------------------------------------------- */

.plans { display: grid; grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); gap: 1rem; margin-top: 2rem; }
.plan { background: var(--bg-1); border-radius: 6px; padding: 1.25rem; }
.plan.featured { outline: 1px solid var(--accent-soft); }
.plan h3 { margin: 0 0 0.2rem; font-size: 1rem; }
.plan .price { font-size: 1.6rem; font-family: 'Source Serif 4', Georgia, serif; }
.plan .price small { font-size: 0.8rem; color: var(--ink-2); font-family: inherit; }
.plan ul { list-style: none; padding: 0; margin: 1rem 0 0; font-size: 0.85rem; color: var(--ink-2); }
.plan li { padding: 0.25rem 0; }

footer {
  border-top: 1px solid var(--bd);
  padding: 2.5rem 0 4rem;
  color: var(--ink-2);
  font-size: 0.85rem;
}
footer a { color: var(--ink-1); }

/*
 * The copyright sits below the links and quieter than them — it identifies the
 * company, it is not navigation. The year is written into the file: there is no
 * build step here to substitute one, and a script for a four-digit number is
 * not worth the only <script> tag on the site. It needs an edit each January.
 */
.legal { color: var(--ink-2); margin-top: 1.25rem; }

.note { font-size: 0.85rem; color: var(--ink-2); max-width: var(--measure); }

/* Beats ------------------------------------------------------------------- */

/*
 * The copy leans on short declarative lines set one per row — "Every change is
 * a proposal. / Accept it. / Reject it." Those are one thought with hard line
 * breaks in it, not a list, so they are <br> inside a paragraph rather than a
 * <ul> with the markers hidden.
 *
 * They sit a step darker and a step larger than body copy: the surrounding
 * paragraph explains, and the beat is the line meant to land.
 */
p.beats {
  font-size: 1.05rem;
  line-height: 1.7;
  color: var(--ink-0);
  max-width: var(--measure);
  margin: 1.5rem 0;
}

/* Enumerations ------------------------------------------------------------ */

/*
 * Genuine lists — the thirteen typesetting details, the eight measured voice
 * characteristics. Set in columns because thirteen single-word rows down the
 * left edge reads as a very long page rather than a short list.
 */
.ticks {
  list-style: none;
  padding: 0;
  margin: 1.5rem 0;
  max-width: 46rem;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11.5rem, 1fr));
  gap: 0.1rem 1.5rem;
  font-size: 0.9rem;
  color: var(--ink-1);
}
.ticks li { padding: 0.15rem 0 0.15rem 0.9rem; position: relative; }
.ticks li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.75em;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--accent-soft);
}

/* Fiction and nonfiction, side by side ------------------------------------ */

.split {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
  gap: 1.5rem;
  margin-top: 2.5rem;
}
.panel { background: var(--bg-1); border-radius: 6px; padding: 1.5rem; }
.panel h3 {
  font-family: 'Source Serif 4', 'Iowan Old Style', Georgia, serif;
  font-size: 1.3rem;
  font-weight: 400;
  margin: 0 0 0.75rem;
}
.panel p { max-width: none; }
.panel p.beats { font-size: 0.95rem; margin: 1rem 0 0; }

/* Button rows ------------------------------------------------------------- */

.actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 2rem 0 0; }

/* Hero body copy ---------------------------------------------------------- */

/*
 * The hero sits outside <section>, so it does not inherit `section p`. These
 * come after `.lede` in the file and are re-asserted at matching specificity
 * below so the lede keeps its size.
 */
.hero p { max-width: var(--measure); color: var(--ink-1); margin: 0 0 1rem; }
.hero p.lede { font-size: 1.2rem; margin: 0 0 1.5rem; }
.hero p.beats { color: var(--ink-0); margin: 1.5rem 0 0; }

/* Plans ------------------------------------------------------------------- */

/*
 * Column layout so the price sits under the name, the features stretch, and
 * every call to action lands on the same baseline no matter how many features
 * a plan lists.
 */
.plan { display: flex; flex-direction: column; }
.plan .who { font-size: 0.85rem; color: var(--ink-2); margin: 0.5rem 0 0; max-width: none; }
.plan .plus { font-size: 0.85rem; color: var(--ink-1); margin: 0.9rem 0 0; max-width: none; }
/*
 * The feature list is prose now rather than a <ul>, so `.includes` takes over
 * both jobs the list had: the quieter type, and the `flex: 1 1 auto` that
 * absorbs the height difference between plans so all three CTAs sit on the
 * same line no matter how much each card says.
 */
.plan .includes {
  font-size: 0.85rem;
  color: var(--ink-2);
  margin: 1rem 0 0;
  max-width: none;
  flex: 1 1 auto;
}
.plan ul { flex: 1 1 auto; }
.plan .cta {
  display: block;
  text-align: center;
  margin-top: 1.25rem;
  font-size: 0.8rem;
  padding: 0.6rem 0.5rem;
}

.badge {
  align-self: flex-start;
  background: var(--accent);
  color: #fff;
  font-size: 0.65rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 0.2rem 0.5rem;
  border-radius: 3px;
  margin-bottom: 0.6rem;
}

/* The close --------------------------------------------------------------- */

.closer { text-align: center; }
.closer h2, .closer p { margin-left: auto; margin-right: auto; }
.closer h2 { max-width: 30ch; }
.closer .actions { justify-content: center; }

.finale {
  font-family: 'Source Serif 4', 'Iowan Old Style', Georgia, serif;
  font-size: clamp(1.8rem, 4vw, 2.6rem);
  line-height: 1.15;
  color: var(--ink-0);
  max-width: none;
  margin: 2.5rem 0 0;
}

/* Five across rather than four and a stranded fifth. */
.grid.five { grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); }

/*
 * Button rows, re-asserted last.
 *
 * `.hero p` and `section p` both score (0,1,1) and would otherwise zero the
 * row's top margin. Longhand rather than the shorthand, so `.closer p`'s auto
 * side margins survive and the closing button stays centred.
 */
p.actions { margin-top: 2rem; margin-bottom: 0; }

/* Narrow screens ---------------------------------------------------------- */

/*
 * The header is a single flex row that cannot fit a phone: the nav's natural
 * width is 375px and the logo is another 110px, against 327px of usable width
 * inside the padding. Rather than shrink the mark back down — it is meant to
 * be the size it is — both rows are allowed to wrap, so the nav drops beneath
 * the logo instead of pushing the page sideways.
 */
@media (max-width: 40rem) {
  header { flex-wrap: wrap; gap: 0.75rem 1rem; }
  nav { flex-wrap: wrap; gap: 0.75rem 1rem; }
}

/* Sign-up ----------------------------------------------------------------- */

.signup-hero { padding-bottom: 3rem; }

.signup {
  display: flex;
  flex-direction: column;
  max-width: 22rem;
  margin: 2.5rem 0 0;
}
.signup label {
  font-size: 0.8rem;
  color: var(--ink-1);
  margin-bottom: 0.35rem;
}
.signup input {
  font: inherit;
  font-size: 0.95rem;
  color: var(--ink-0);
  background: var(--paper);
  border: 1px solid var(--bd);
  border-radius: 5px;
  padding: 0.6rem 0.7rem;
  margin-bottom: 1.1rem;
}
.signup input:focus {
  outline: 2px solid var(--accent-soft);
  outline-offset: 1px;
  border-color: transparent;
}
.signup .hint {
  font-size: 0.78rem;
  color: var(--ink-2);
  margin: -0.75rem 0 1.25rem;
  max-width: none;
}
.signup .button { border: 0; cursor: pointer; font-family: inherit; }
.signup .button:disabled { opacity: 0.55; cursor: default; }

/*
 * The status line is empty until something happens, so it must not reserve
 * space or the button appears to float above a gap.
 */
.status { font-size: 0.85rem; margin: 0.9rem 0 0; max-width: none; }
.status:empty { display: none; }
.status.good { color: var(--ink-0); }
.status.bad { color: #b3261e; }

@media (prefers-color-scheme: dark) {
  .status.bad { color: #ff9a90; }
}

.signup-note { margin-top: 2.5rem; }
