/* app.css — all styles for Lesson Ledger. Phone-first, no framework, no build.
   Rules of the house: single column, tap targets >= 44px, readable at 360px,
   16px form controls (so iOS never zooms on focus), and nothing fussy. */

:root {
  color-scheme: light dark;

  --bg: #f4f5f7;
  --surface: #ffffff;
  --surface-2: #eef0f4;
  --ink: #16181d;
  --ink-soft: #5c626e;
  --line: #d9dce3;
  --accent: #1f5fd0;
  --accent-ink: #ffffff;
  --owed: #a8341f;
  --credit: #1c6b45;
  --warn-bg: #fdf3d3;
  --warn-ink: #6b4e00;

  /* Traffic light (DESIGN.md): green starts, red stops, blue creates. */
  --go: #12813c;
  --go-ink: #ffffff;
  --stop: #c22e22;
  --stop-ink: #ffffff;
  --make: var(--accent);
  --make-ink: var(--accent-ink);

  /* The tinted outlines (2026-08-26). A secondary button stays small, light
     and quiet — it just says in colour what it says in words, so a Delete and
     a Cancel are not the same grey pill on a phone, where there is no hover to
     reveal the difference. */
  --go-quiet: #0e6a31;
  --go-quiet-bg: #e8f5ec;
  --danger-quiet: #a8341f;
  --danger-quiet-bg: #fdeeea;
  --make-quiet: #1b4fae;
  --make-quiet-bg: #e9f0fd;

  /* Success: green, and never the warning yellow .alert used to borrow. */
  --done-bg: #e2f3e8;
  --done-ink: #12603a;
  --done-line: #9bd4b3;

  --radius: 12px;
  --tap: 44px;
  --gap: 0.75rem;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #14161a;
    --surface: #1d2026;
    --surface-2: #24282f;
    --ink: #f0f1f4;
    --ink-soft: #a5abb8;
    --line: #333844;
    --accent: #6b9dfa;
    --accent-ink: #0f1115;
    --owed: #ff9c85;
    --credit: #79dba8;
    --warn-bg: #3d3213;
    --warn-ink: #f3e0a6;

    --go: #35c163;
    --go-ink: #06140b;
    --stop: #ff6a5c;
    --stop-ink: #1b0b09;
    --make: var(--accent);
    --make-ink: var(--accent-ink);

    --go-quiet: #79dba8;
    --go-quiet-bg: #17301f;
    --danger-quiet: #ff9c85;
    --danger-quiet-bg: #341d18;
    --make-quiet: #9dbcfb;
    --make-quiet-bg: #1a2333;

    --done-bg: #13301f;
    --done-ink: #8fdcaf;
    --done-line: #2f6a46;
  }
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  padding: 1rem 1rem 3rem;
  background: var(--bg);
  color: var(--ink);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 1rem;
  line-height: 1.5;
  -webkit-text-size-adjust: 100%;
}

#app {
  display: block;
  max-width: 32rem;
  margin: 0 auto;
}

/* --- typography ---------------------------------------------------------- */

h1,
h2 {
  margin: 0;
  line-height: 1.25;
}

.screen-head {
  margin-bottom: var(--gap);
}

.screen-title {
  font-size: 1.5rem;
  overflow-wrap: anywhere;
}

.back {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  color: var(--accent);
  font-weight: 600;
  text-decoration: none;
}

.hint {
  margin: 0.5rem 0 0;
  color: var(--ink-soft);
  font-size: 0.875rem;
}

.badge {
  display: inline-block;
  margin-left: 0.5rem;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--ink-soft);
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  vertical-align: middle;
}

.alert {
  margin: 0 0 var(--gap);
  padding: 0.75rem;
  border-radius: var(--radius);
  background: var(--warn-bg);
  color: var(--warn-ink);
  font-size: 0.9375rem;
}

/* "It worked." Green, bordered and carrying its own tick, so a confirmation
   never reads as the warning yellow .alert is otherwise used for. */
.alert-done {
  border: 1px solid var(--done-line);
  background: var(--done-bg);
  color: var(--done-ink);
  font-weight: 600;
}

.alert-done::before {
  content: "\2713\00a0\00a0";
  font-weight: 700;
}

/* --- summary strip ------------------------------------------------------- */

.summary {
  margin-bottom: var(--gap);
  padding: 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}

.summary-label {
  margin: 0;
  color: var(--ink-soft);
  font-size: 0.8125rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.summary-value {
  margin: 0.15rem 0 0;
  font-size: 2rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.summary-meta {
  margin: 0.25rem 0 0;
  color: var(--ink-soft);
  font-size: 0.875rem;
}

/* --- money --------------------------------------------------------------- */

.amount {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  white-space: nowrap;
}

.amount-owed {
  color: var(--owed);
}

.amount-credit {
  color: var(--credit);
}

.amount-settled {
  color: var(--ink-soft);
}

/* --- buttons ------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tap);
  padding: 0.5rem 1rem;
  border: 1px solid transparent;
  border-radius: var(--radius);
  font: inherit;
  font-weight: 600;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
}

/* Primaries: full-width, colour-coded, at most two per screen. */
.btn-green,
.btn-red,
.btn-blue {
  display: flex;
  width: 100%;
  margin-bottom: var(--gap);
  border-color: transparent;
}

.btn-green {
  background: var(--go);
  color: var(--go-ink);
}

.btn-red {
  background: var(--stop);
  color: var(--stop-ink);
}

.btn-blue {
  background: var(--make);
  color: var(--make-ink);
}

/* The big pair — the two taps the whole app is built around. */
.btn-big {
  min-height: 3.5rem;
  font-size: 1.1875rem;
  letter-spacing: 0.01em;
}

/* Secondaries: small, grey, outlined, always below the primaries. */
.btn-small {
  flex: 0 1 auto;
  min-height: var(--tap);
  padding: 0.4rem 0.9rem;
  font-size: 0.9375rem;
  font-weight: 600;
}

.btn-outline {
  border-color: var(--line);
  background: var(--surface);
  color: var(--ink-soft);
}

/* The tinted secondaries (2026-08-26). Same size, same weight, same place as
   .btn-outline — only the hue differs, so the traffic light still belongs to
   the two big buttons and these merely stop being anonymous.

   Destructive stays quiet: red belongs to Finish lesson alone, so a Delete is
   a red-EDGED outline and never a filled red slab. It used to be plain grey
   that turned red on hover — invisible on the phone this app is built for,
   where "Delete lesson" and "Cancel" were the same button to look at. */
.btn-quiet-danger,
.btn-outline-danger {
  border-color: var(--danger-quiet);
  background: var(--danger-quiet-bg);
  color: var(--danger-quiet);
}

.btn-quiet-danger:hover,
.btn-outline-danger:hover {
  border-color: var(--owed);
  color: var(--owed);
}

/* Money in, and putting something back: the quiet end of green. */
.btn-outline-green {
  border-color: var(--go-quiet);
  background: var(--go-quiet-bg);
  color: var(--go-quiet);
}

/* Adds something to the ledger: the quiet end of blue. */
.btn-outline-blue {
  border-color: var(--make-quiet);
  background: var(--make-quiet-bg);
  color: var(--make-quiet);
}

.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

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

.actions-secondary {
  margin-top: 0.25rem;
  margin-bottom: var(--gap);
}

.screen-foot {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 1.25rem;
}

.screen-foot .btn-green,
.screen-foot .btn-red,
.screen-foot .btn-blue {
  margin-bottom: 0;
}

.screen-foot-quiet {
  justify-content: center;
  margin-top: 2rem;
}

/* The save bar for a LONG form — Settings, where the fields ran on for five
   panels and the Save button sat below all of them (client feedback,
   2026-08-26: "there's little feedback… the save button is too far down").
   It sticks to the bottom of the screen while the form is on it, so Save is
   always one tap away and the line that says it worked appears where the eye
   already is. It stops sticking once the form is scrolled past, which is
   right: there is nothing left to save down there. */
.form-foot-sticky {
  position: sticky;
  bottom: 0;
  z-index: 2;
  flex-direction: column;
  align-items: stretch;
  gap: 0;
  margin-top: var(--gap);
  padding: 0.75rem 0;
  border-top: 1px solid var(--line);
  background: var(--bg);
}

.form-foot-sticky .btn-blue {
  flex: 1 1 auto;
  width: auto;
}

/* The confirmation, right beside the button that earned it. */
.form-foot-status {
  margin: 0 0 0.5rem;
  padding: 0.6rem 0.75rem;
}

/* Two boxes that belong together — a licence number and the day it runs out.
   They sit side by side where there is room and stack at phone width, which is
   what "next to" has to mean on a 360px screen. */
.field-pair {
  display: flex;
  flex-wrap: wrap;
  gap: 0 0.75rem;
}

.field-pair > .field {
  flex: 1 1 11rem;
  min-width: 0;
}

.field-pair > .field-narrow {
  flex: 0 1 9.5rem;
}

/* An icon in front of a button's words. Marked aria-hidden in the DOM, so it
   is decoration to a screen reader and a signpost to everyone else. */
.btn-icon {
  margin-right: 0.4rem;
  font-size: 1.1em;
  line-height: 1;
}

.quiet-link {
  min-height: var(--tap);
  display: inline-flex;
  align-items: center;
  color: var(--ink-soft);
  font-size: 0.875rem;
  text-decoration: underline;
}

/* A link that is really a button (the rate line's "change"). */
.link-button {
  min-height: 1.5rem;
  padding: 0;
  border: 0;
  background: none;
  color: var(--accent);
  font: inherit;
  font-size: 0.875rem;
  text-decoration: underline;
  cursor: pointer;
}

/* --- home: hourly-rate setup --------------------------------------------- */

.rate-card {
  border-color: var(--accent);
}

.rate-form .btn {
  width: 100%;
}

.rate-line {
  display: flex;
  gap: 0.5rem;
  align-items: baseline;
  margin: 0 0 var(--gap);
  color: var(--ink-soft);
  font-size: 0.875rem;
}

/* Home's gentle nudge towards Settings while the invoice details are missing.
   Quieter than the rate card: this one does not block anything. */
.setup-card {
  background: var(--surface-2);
}

/* The backup reminder: one quiet line under the two big buttons. No panel, no
   colour of its own, nothing that could be mistaken for a third primary. */
.nudge {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 0.75rem;
  align-items: baseline;
  margin: 0 0 var(--gap);
  color: var(--ink-soft);
  font-size: 0.875rem;
}

.nudge-text {
  flex: 1 1 auto;
}

.nudge-dismiss {
  color: var(--ink-soft);
}

/* The reminder's own answer — "No backup was made this time." — sits directly
   under the line that offered it, closer to it than to anything else. */
.nudge-status {
  margin-top: calc(var(--gap) * -0.5);
}

/* A link-button while it is working: Home's "Back up" disables itself for as
   long as the share sheet is open, and must stop looking tappable. */
.link-button[disabled] {
  color: var(--ink-soft);
  text-decoration: none;
  cursor: default;
}

/* --- undo notice ---------------------------------------------------------- */

.undo-bar {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: var(--gap);
  padding: 0.625rem 0.75rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-2);
}

.undo-text {
  flex: 1 1 auto;
  font-size: 0.9375rem;
  font-weight: 600;
}

/* --- running-lesson banner (home) ---------------------------------------- */

.banner {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-height: var(--tap);
  margin-bottom: var(--gap);
  padding: 0.75rem 1rem;
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  background: var(--warn-bg);
  color: var(--warn-ink);
  text-decoration: none;
}

.banner-body {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
}

.banner-title {
  font-weight: 700;
  overflow-wrap: anywhere;
}

.banner-meta {
  font-size: 0.875rem;
}

/* --- active lesson ------------------------------------------------------- */

.stopwatch {
  margin: 0.15rem 0 0;
  font-size: 2.75rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}

.guard {
  border-color: var(--owed);
}

.preview {
  margin: 0;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.inline-link {
  color: var(--accent);
  font-weight: 600;
}

/* --- panels -------------------------------------------------------------- */

.panel {
  margin-bottom: var(--gap);
  padding: 0.875rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}

.panel-title {
  font-size: 1rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
}

.panel-muted {
  background: var(--surface-2);
}

.panel-summary {
  display: flex;
  align-items: center;
  min-height: var(--tap);
  color: var(--ink-soft);
  font-size: 0.9375rem;
  font-weight: 600;
  cursor: pointer;
}

/* --- customer list ------------------------------------------------------- */

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

.list-item + .list-item {
  border-top: 1px solid var(--line);
}

.row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-height: 3rem;
  padding: 0.5rem 0;
  color: inherit;
  text-decoration: none;
}

.row-name {
  flex: 1 1 auto;
  font-weight: 600;
  overflow-wrap: anywhere;
}

.row-chevron {
  color: var(--ink-soft);
  font-size: 1.25rem;
}

.empty {
  padding: 1rem 0 0.5rem;
  text-align: center;
}

.empty-title {
  margin: 0;
  font-weight: 700;
}

.empty-body {
  margin: 0.25rem 0 0;
  color: var(--ink-soft);
  font-size: 0.9375rem;
}

/* --- ledgers ------------------------------------------------------------- */

.ledger {
  margin: 0.25rem 0 0;
  padding: 0;
  list-style: none;
}

.entry {
  padding: 0.625rem 0;
}

.entry + .entry {
  border-top: 1px solid var(--line);
}

.entry-link {
  display: block;
  min-height: var(--tap);
  padding: 0.125rem 0;
  color: inherit;
  text-decoration: none;
}

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

.entry-top {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
}

.entry-top .row-chevron {
  margin-left: 0.25rem;
}

.entry-date {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  white-space: nowrap;
}

.entry-name {
  flex: 1 1 auto;
  overflow-wrap: anywhere;
}

.entry-top .amount {
  margin-left: auto;
}

.entry-sub {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.75rem;
  color: var(--ink-soft);
  font-size: 0.875rem;
}

.entry-running {
  margin-left: auto;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.entry-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: 0.375rem;
}

/* --- contact details ----------------------------------------------------- */

.contact {
  display: grid;
  grid-template-columns: minmax(4.5rem, auto) 1fr;
  gap: 0.35rem 0.75rem;
  margin: 0.5rem 0 0;
}

.contact dt {
  color: var(--ink-soft);
  font-size: 0.875rem;
}

.contact dd {
  margin: 0;
  overflow-wrap: anywhere;
  white-space: pre-line;
}

.contact a {
  color: var(--accent);
}

/* A learner permit that has run out, or is about to. The same red the app
   already uses for money owed — the one colour on the screen that means
   "deal with this". */
.flag {
  display: inline-block;
  margin-left: 0.4rem;
  padding: 0.05rem 0.45rem;
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.flag-expired {
  background: var(--danger-quiet-bg);
  color: var(--danger-quiet);
}

.flag-soon {
  background: var(--warn-bg);
  color: var(--warn-ink);
}

/* --- invoices ------------------------------------------------------------ */

/* Ticking lessons onto an invoice: the whole row is one tap target. */
.pick-list {
  margin: 0.25rem 0 0;
  padding: 0;
  list-style: none;
}

.pick + .pick {
  border-top: 1px solid var(--line);
}

.pick-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-height: var(--tap);
  padding: 0.5rem 0;
  cursor: pointer;
}

.pick-body {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
}

.pick-top {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
}

.pick-top .amount {
  margin-left: auto;
}

.pick-sub {
  color: var(--ink-soft);
  font-size: 0.875rem;
}

/* The preview: the invoice itself, as the customer will read it. */
.invoice-doc {
  background: var(--surface);
}

.doc-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem;
  margin-bottom: var(--gap);
}

.doc-heading {
  flex: 1 1 auto;
  font-size: 1.25rem;
}

.doc-number {
  margin-left: auto;
  text-align: right;
}

.doc-party {
  margin-bottom: var(--gap);
}

.doc-label {
  margin: 0 0 0.15rem;
  color: var(--ink-soft);
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.doc-line {
  margin: 0;
  color: var(--ink-soft);
  font-size: 0.875rem;
  overflow-wrap: anywhere;
}

.doc-strong {
  color: var(--ink);
  font-size: 1rem;
  font-weight: 700;
}

/* Wide content scrolls inside its own box — the page never scrolls sideways. */
.table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.invoice-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.8125rem;
  white-space: nowrap;
}

.invoice-table th,
.invoice-table td {
  padding: 0.4rem 0.5rem 0.4rem 0;
  text-align: left;
  vertical-align: top;
}

.invoice-table th {
  border-bottom: 1px solid var(--line);
  color: var(--ink-soft);
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.invoice-table tbody tr + tr td {
  border-top: 1px solid var(--line);
}

.invoice-table .num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  padding-right: 0;
  padding-left: 0.75rem;
}

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

.invoice-balance {
  padding-top: 0.5rem;
  border-top: 1px solid var(--line);
}

.total-row {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  padding: 0.15rem 0;
  color: var(--ink-soft);
  font-size: 0.9375rem;
}

.total-label {
  flex: 1 1 auto;
}

.total-value {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.total-row-main {
  color: var(--ink);
  font-size: 1.0625rem;
  font-weight: 700;
}

.total-note {
  margin: 0.35rem 0 0;
  color: var(--ink-soft);
  font-size: 0.875rem;
}

.invoice-pay {
  margin-top: var(--gap);
  padding: 0.75rem;
  border-radius: var(--radius);
  background: var(--surface-2);
}

/* --- forms --------------------------------------------------------------- */

.field {
  margin-bottom: 1rem;
}

/* The whole sponsor form, opened inside the "Who pays?" step. It is a second
   form sitting under the pick list, so it is ruled off from it — without the
   line the "Name of the organisation" box reads as one more thing to fill in
   for the customer being added, rather than the start of the organisation. */
.sponsor-add {
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--line);
}

/* Present but deliberately understated — e.g. the per-customer rate box, which
   is prefilled and should only be touched on purpose. */
.field-minor .label {
  color: var(--ink-soft);
  font-size: 0.875rem;
  font-weight: 600;
}

.field-minor .input {
  background: var(--surface-2);
}

.label {
  display: block;
  margin-bottom: 0.25rem;
  font-weight: 600;
}

.req {
  color: var(--owed);
}

.input {
  display: block;
  width: 100%;
  min-height: var(--tap);
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: 1rem; /* 16px: stops iOS zooming on focus */
}

textarea.input {
  min-height: 3.5rem;
  resize: vertical;
}

/* A checkbox and its words as one 44px tap target (the GST toggle). */
.check-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-height: var(--tap);
  cursor: pointer;
}

.check {
  width: 1.375rem;
  height: 1.375rem;
  margin: 0;
  flex: 0 0 auto;
  accent-color: var(--accent);
}

.check-label {
  font-weight: 600;
}

.input:focus-visible,
.check:focus-visible,
.btn:focus-visible,
.row:focus-visible,
.back:focus-visible,
.panel-summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.input[aria-invalid="true"] {
  border-color: var(--owed);
}

.field-error,
.form-error {
  margin: 0.35rem 0 0;
  color: var(--owed);
  font-size: 0.875rem;
  font-weight: 600;
}

.form-error {
  margin: 0 0 var(--gap);
}
