/*
 * The free invoice generator, on top of `landing.css` and `pages.css`.
 *
 * Two columns: the fields on the left, and on the right the document itself,
 * redrawn on every keystroke. The document is not a picture of an invoice.
 * It is the thing that prints, so what somebody sees while typing is exactly
 * what comes out of the print dialogue. That is the app's own rule about the
 * preview being the PDF, kept here because it is the only honest way to show
 * somebody what they are about to send.
 *
 * The PDF comes from the browser. There is no library: `window.print()` and a
 * print stylesheet produce a real A4 PDF through the operating system's own
 * "Save as PDF", which costs nothing to load, works offline once the page is
 * open, and cannot be blocked by this site's `default-src 'none'`.
 */

/* ── layout ───────────────────────────────────────────────────────── */

/*
 * `--paper`, like the first band of every other page on this site and like the
 * app's own page colour. It was `--sand` while this was the only page with a
 * working area on it, and the darker ground read as a different site the
 * moment somebody arrived here from a trade page.
 */
.gen {
  background: var(--paper);
  padding: 56px var(--pad) 96px;
}
.gen-grid {
  display: grid;
  grid-template-columns: 420px minmax(0, 1fr);
  gap: 40px;
  align-items: start;
}

/* ── the fields ───────────────────────────────────────────────────── */

/*
 * The app's card, and the app's rows inside it.
 *
 * The numbers are `src/theme.ts` and the `Field` row in `app/business.tsx`:
 * a white card on paper at 16px radius behind a hairline border and a shadow
 * you only notice by its absence, and inside it a grouped list, a small
 * uppercase caption over a field with no box of its own, rows told apart by
 * hairlines. The form used to be a page of bordered boxes inside a bordered
 * box, which is what an HTML form looks like when nobody has drawn it.
 */
.gen-form {
  position: sticky;
  top: 24px;
  background: #fff;
  border: 1px solid rgba(16, 20, 24, .09);
  border-radius: 16px;
  box-shadow: 0 2px 8px rgba(16, 20, 24, .1);
  padding: 0;
  max-height: calc(100vh - 48px);
  /*
   * `overflow-y: auto` on its own computes `overflow-x` to `auto` as well, so
   * anything a pixel too wide inside the card gives the whole form a sideways
   * scroll. The column is a fixed width and nothing in it is meant to be
   * scrolled across, so the horizontal axis is closed explicitly.
   */
  overflow: hidden auto;
}
@media screen and (max-height: 720px), screen and (max-width: 1080px) {
  .gen-form { position: static; max-height: none; }
}

.gen-form fieldset {
  border: 0;
  border-top: 1px solid rgba(16, 20, 24, .09);
  margin: 0;
  padding: 0;
  min-width: 0;
}
.gen-form fieldset:first-of-type { border-top: 0; }
.gen-form legend {
  display: block;
  width: 100%;
  box-sizing: border-box;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: rgba(16, 20, 24, .42);
  padding: 19px 16px 9px;
}

.field {
  padding: 11px 16px 12px;
  border-top: 1px solid rgba(16, 20, 24, .055);
  /* A grid item's `auto` minimum is its content's, and a native date control
     asks for more than half a narrow card. Let the column win instead. */
  min-width: 0;
}
.field label {
  display: block;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: rgba(16, 20, 24, .42);
  margin-bottom: 1px;
}
.field input,
.field textarea,
.field select {
  display: block;
  width: 100%;
  box-sizing: border-box;
  font-family: var(--sans);
  font-size: 15.5px;
  line-height: 1.45;
  color: var(--ink);
  background: transparent;
  border: 0;
  border-radius: 0;
  padding: 2px 0 0;
  margin: 0;
  min-width: 0;
}
.field input::placeholder,
.field textarea::placeholder { color: rgba(16, 20, 24, .3); }
/* Sized by `grow()` in generator.js, so there is no handle to drag. */
.field textarea { resize: none; overflow: hidden; min-height: 46px; }
.field input[type="date"] { min-height: 24px; }

/*
 * A field with no box needs its focus said some other way. The wash and the
 * red edge are on the row rather than the control, so a caret in a borderless
 * input is not the only thing telling somebody where they are typing.
 */
.field input:focus,
.field textarea:focus,
.field select:focus { outline: none; }
.field:focus-within {
  background: rgba(228, 64, 31, .04);
  box-shadow: inset 2px 0 0 var(--red);
}

.field-row { display: grid; grid-template-columns: 1fr 1fr; }
.field-row .field + .field { border-left: 1px solid rgba(16, 20, 24, .055); }

/* the logo, whose native control is a browser's own idea of a button */

/*
 * Selector has to out-specify `.field input` above, which would otherwise
 * stretch this to `width: 100%` and push the card's contents 17px sideways.
 */
.field input.file-input {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.file-row { display: flex; align-items: center; gap: 10px; margin-top: 6px; }
.field label.file-btn {
  flex: none;
  border: 1px solid rgba(16, 20, 24, .18);
  border-radius: 9px;
  padding: 6px 12px;
  font-size: 13px;
  font-weight: 600;
  color: rgba(16, 20, 24, .66);
  cursor: pointer;
  /* The label carries the caption styling of every other `.field label`, and
     must not: it is a button. */
  text-transform: none;
  letter-spacing: 0;
  margin: 0;
}
.field label.file-btn:hover { border-color: var(--red); color: var(--red); }
.field input.file-input:focus-visible + .file-row .field label.file-btn,
.field input.file-input:focus-visible + .file-row label.file-btn {
  outline: 2px solid var(--red);
  outline-offset: 2px;
}
.file-name {
  min-width: 0;
  flex: 1;
  font-family: var(--mono);
  font-size: 11px;
  color: rgba(16, 20, 24, .45);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* line items */

.item {
  border: 1px solid rgba(16, 20, 24, .1);
  border-radius: 14px;
  background: rgba(16, 20, 24, .022);
  padding: 0 0 4px;
  margin-bottom: 10px;
  overflow: hidden;
}
.item-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 12px 2px;
}
.item-n {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: rgba(16, 20, 24, .4);
}
.item .field { padding: 8px 12px 9px; }
.item .field:focus-within { background: rgba(228, 64, 31, .05); }
.item-nums { display: grid; grid-template-columns: 1fr 1fr 1.2fr; }
.item-nums .field + .field { border-left: 1px solid rgba(16, 20, 24, .055); }

#f-items { padding: 2px 14px 0; }

.btn-small {
  border: 1px solid rgba(16, 20, 24, .18);
  background: #fff;
  color: rgba(16, 20, 24, .66);
  font-family: var(--sans);
  font-size: 12.5px;
  font-weight: 600;
  border-radius: 8px;
  padding: 5px 10px;
  cursor: pointer;
}
.btn-small:hover { border-color: var(--red); color: var(--red); }

.btn-add {
  width: calc(100% - 28px);
  margin: 4px 14px 16px;
  border: 1px dashed rgba(16, 20, 24, .28);
  background: transparent;
  color: rgba(16, 20, 24, .6);
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 600;
  border-radius: 10px;
  padding: 11px;
  cursor: pointer;
}
.btn-add:hover { border-color: var(--red); color: var(--red); }

/* accents */

.swatches { display: flex; gap: 8px; margin-top: 7px; }
.swatch {
  width: 30px; height: 30px;
  border-radius: 9px;
  border: 2px solid transparent;
  box-shadow: inset 0 0 0 1px rgba(16, 20, 24, .12);
  cursor: pointer;
  padding: 0;
}
.swatch[aria-pressed="true"] { border-color: var(--ink); }

/* actions */

.gen-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 18px 16px 20px;
  border-top: 1px solid rgba(16, 20, 24, .09);
}
.btn-print {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  height: 52px;
  border: 0;
  border-radius: 26px;
  background: var(--red);
  color: #fff;
  font-family: var(--sans);
  font-size: 15.5px;
  font-weight: 600;
  cursor: pointer;
  box-shadow: 0 14px 30px -14px rgba(147, 35, 26, .85);
}
.btn-print:hover { background: var(--red-dark); }
.btn-print .mark { --mark: 18px; }
.gen-note {
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1.6;
  color: rgba(16, 20, 24, .45);
  text-align: center;
}
.btn-reset {
  align-self: center;
  border: 0;
  background: none;
  font-family: var(--sans);
  font-size: 13px;
  color: rgba(16, 20, 24, .5);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
  padding: 4px;
}
.btn-reset:hover { color: var(--red); }

/* ── what is said once the file exists ────────────────────────────── */

/*
 * Revealed on `afterprint`, and not before. It is the app's dark feature card
 * (ink ground, paper text) sitting at the foot of the form, so the offer
 * looks like the product rather than like an advert bolted to a free tool.
 */
.gen-done {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 14px;
  margin: 0 12px 14px;
  padding: 20px 20px 18px;
  border-radius: 16px;
  background: var(--ink);
  color: var(--paper);
}
.gen-done[hidden] { display: none; }
.gen-done-eyebrow {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: rgba(200, 220, 228, .58);
}
.gen-done p {
  margin: -4px 0 0;
  font-size: 14.5px;
  line-height: 1.55;
  color: rgba(247, 245, 241, .78);
  text-wrap: pretty;
}
.gen-done .btn-download {
  height: 52px;
  padding: 0 22px;
  font-size: 15.5px;
  box-shadow: 0 14px 30px -16px rgba(0, 0, 0, .9), inset 0 1px 0 rgba(255, 255, 255, .3);
}
.gen-done .btn-reset { align-self: center; color: rgba(200, 220, 228, .55); }
.gen-done .btn-reset:hover { color: var(--paper); }

/* ── the document ─────────────────────────────────────────────────── */

.gen-paper { display: flex; justify-content: center; }

/*
 * A4 at 96 dpi, which is what a browser lays `@page { size: A4 }` out against,
 * so the sheet on screen is the sheet that prints.
 */
.doc {
  --accent: #E4401F;
  width: 794px;
  max-width: 100%;
  min-height: 1123px;
  background: #fff;
  color: #101418;
  border: 1px solid rgba(16, 20, 24, .07);
  border-radius: 4px;
  box-shadow: 0 28px 64px -40px rgba(16, 20, 24, .45);
  padding: 64px 60px 60px;
  font-size: 12px;
  line-height: 1.5;
}

.doc-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 32px;
}
.doc-logo {
  max-width: 190px;
  max-height: 76px;
  object-fit: contain;
  margin-bottom: 12px;
  display: block;
}
.doc-from-name {
  font-family: var(--serif);
  font-size: 24px;
  line-height: 1.15;
  letter-spacing: -.01em;
}
.doc-from-lines { margin-top: 6px; color: rgba(16, 20, 24, .62); white-space: pre-line; }

.doc-title {
  text-align: right;
  flex: none;
}
.doc-title .t {
  font-family: var(--serif);
  font-size: 34px;
  line-height: 1;
  letter-spacing: -.015em;
  color: var(--accent);
}
.doc-facts {
  margin-top: 14px;
  display: grid;
  grid-template-columns: auto auto;
  gap: 4px 16px;
  justify-content: end;
  text-align: right;
}
.doc-facts dt {
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: rgba(16, 20, 24, .42);
  align-self: baseline;
}
.doc-facts dd { margin: 0; font-family: var(--mono); font-size: 12px; }
/*
 * The one optional pair needs a wrapper to be hidden by, and the wrapper must
 * not become a grid cell of its own: it was a `<span>`, so "Terms" and "Net 14
 * days" stacked inside a single cell instead of landing in the label and the
 * value column like every row above them.
 */
.doc-facts .doc-fact { display: contents; }
.doc-facts .doc-fact[hidden] { display: none; }

.doc-rule { height: 1px; background: rgba(16, 20, 24, .14); margin: 30px 0 24px; }

.doc-label {
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: rgba(16, 20, 24, .42);
}
.doc-to-name { font-size: 15px; font-weight: 600; margin-top: 5px; }
.doc-to-lines { color: rgba(16, 20, 24, .62); white-space: pre-line; margin-top: 2px; }

.doc-table { width: 100%; border-collapse: collapse; margin-top: 30px; }
.doc-table th {
  font-family: var(--mono);
  font-size: 9px;
  font-weight: 400;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: rgba(16, 20, 24, .42);
  text-align: left;
  padding: 0 0 8px;
  border-bottom: 1px solid rgba(16, 20, 24, .16);
}
.doc-table th.num, .doc-table td.num { text-align: right; }
.doc-table td { padding: 11px 0; border-bottom: 1px solid rgba(16, 20, 24, .08); vertical-align: top; }
.doc-table td.num { font-family: var(--mono); white-space: nowrap; padding-left: 14px; }
.doc-item-name { font-weight: 500; }
.doc-item-desc { color: rgba(16, 20, 24, .55); margin-top: 2px; }

.doc-sums { display: flex; justify-content: flex-end; margin-top: 22px; }
.doc-sums-inner { width: 280px; }
.doc-sum {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  padding: 5px 0;
  color: rgba(16, 20, 24, .66);
}
.doc-sum .v { font-family: var(--mono); }
.doc-total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  margin-top: 10px;
  padding-top: 12px;
  border-top: 2px solid var(--accent);
}
.doc-total .l { font-family: var(--serif); font-size: 20px; }
.doc-total .v { font-family: var(--mono); font-size: 21px; font-weight: 500; letter-spacing: -.01em; }

.doc-blocks { margin-top: 40px; display: flex; flex-direction: column; gap: 20px; }
.doc-block-body { margin-top: 5px; white-space: pre-line; color: rgba(16, 20, 24, .7); }
.doc-pay {
  border: 1px solid rgba(16, 20, 24, .14);
  border-left: 3px solid var(--accent);
  border-radius: 3px;
  padding: 14px 16px;
}

.doc-foot {
  margin-top: 44px;
  padding-top: 14px;
  border-top: 1px solid rgba(16, 20, 24, .1);
  font-size: 10px;
  color: rgba(16, 20, 24, .4);
  display: flex;
  justify-content: space-between;
  gap: 20px;
}

/* ── printing ─────────────────────────────────────────────────────── */

/*
 * Everything but the sheet is taken off the page, and the sheet loses the
 * things that only make sense on screen: its shadow, its rounded corner and
 * the width it was constrained to. `@page` supplies the margin, so the
 * document's own padding is dropped to what the design needs inside it.
 */
@media print {
  body { background: #fff; }
  /*
   * Everything that is not the sheet, by exclusion rather than by name. The
   * first version listed the sections to hide and missed the questions band,
   * which printed as a second page, and would have missed the next section
   * anybody adds. Hiding by default is the safe direction: a new section on
   * this page stays off the invoice unless somebody puts it inside the paper.
   */
  body > *:not(.gen) { display: none !important; }
  .gen > .wrap > *:not(.gen-paper) { display: none !important; }
  .gen { background: #fff; padding: 0; }
  .gen-grid { display: block; }
  .gen-paper { display: block; }
  .doc {
    width: auto;
    max-width: none;
    min-height: 0;
    box-shadow: none;
    border: 0;
    border-radius: 0;
    padding: 0;
  }
  @page { size: A4; margin: 16mm 14mm; }
}

/* ── the surrounding page ─────────────────────────────────────────── */

.gen-head { background: var(--paper); padding: 0 var(--pad) 44px; }
.gen-head .wrap { max-width: 820px; margin: 0 auto; }

/* `--sand`, the way `.features` and `.others` sit under a `--paper` band
   elsewhere: the working area took the paper, so this takes the sand rather
   than running into it with no seam. */
.gen-how { background: var(--sand); padding: 96px var(--pad) 104px; }
.gen-how .steps {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 22px;
  margin-top: 44px;
}
.gen-step {
  background: var(--card);
  border: 1px solid rgba(16, 20, 24, .1);
  border-radius: 18px;
  padding: 28px 28px 30px;
}
.gen-step .glyph {
  width: 44px; height: 44px;
  border-radius: 13px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(228, 64, 31, .12);
  color: var(--red);
}
.gen-step h3 { margin: 18px 0 0; font-size: 19px; font-weight: 600; letter-spacing: -.01em; }
.gen-step p { margin: 8px 0 0; font-size: 14.5px; line-height: 1.6; color: rgba(16, 20, 24, .62); text-wrap: pretty; }

@media screen and (max-width: 1280px) {
  .gen-grid { grid-template-columns: 380px minmax(0, 1fr); gap: 28px; }
  .doc { padding: 48px 44px 44px; }
}
@media screen and (max-width: 1080px) {
  .gen-grid { grid-template-columns: minmax(0, 1fr); }
  .gen-how .steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media screen and (max-width: 760px) {
  .gen { padding-top: 32px; padding-bottom: 72px; }
  .gen-form { border-radius: 14px; }
  .item-nums { grid-template-columns: 1fr 1fr; }
  .item-nums .field:nth-child(3) { grid-column: 1 / -1; border-left: 0; border-top: 1px solid rgba(16, 20, 24, .055); }
  .doc { padding: 28px 22px 26px; font-size: 11.5px; min-height: 0; }
  .doc-head { flex-direction: column; gap: 18px; }
  .doc-title { text-align: left; }
  .doc-facts { justify-content: start; text-align: left; }
  .doc-sums-inner { width: 100%; }
  .gen-how { padding-top: 72px; padding-bottom: 80px; }
  .gen-how .steps { grid-template-columns: minmax(0, 1fr); }
}
