/* m.css — the phone website.
 *
 * SEPARATE FROM styles.css, DELIBERATELY
 *
 *   The desktop is what a firm uses for eight hours in February. It works.
 *   Sharing a stylesheet means every mobile change is a chance to move a
 *   desktop column three pixels, and that is a regression in the thing that
 *   pays for the thing that does not yet.
 *
 *   Nothing here is loaded by any desktop page. The two cannot interfere.
 *
 * THE SAME COLOURS, DELIBERATELY
 *
 *   A firm switching between the two should feel one product. The tokens are
 *   copied rather than imported, so a desktop change does not silently reshape
 *   the phone — and a comment says so, because the next person will otherwise
 *   "fix" the duplication.
 */

:root {
  --ink:        #0f172a;
  --muted:      #475569;
  --line:       #e2e8f0;
  --bg:         #f8fafc;
  --card:       #ffffff;
  --accent:     #1b3a5c;
  --gold:       #c9a227;
  --gold-bg:    #faf6ec;
  --good:       #065f46;
  --good-bg:    #d1fae5;
  --warn:       #92400e;
  --bad:        #991b1b;

  /* A phone is held at the bottom, and the home indicator sits under the nav
     on an iPhone. env() is zero everywhere else, so this is safe. */
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --nav-height:  58px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --ink:      #f1f5f9;
    --muted:    #94a3b8;
    --line:     #1e293b;
    --bg:       #0b0f19;
    --card:     #111827;
    --accent:   #38bdf8;
    --gold:     #fbbf24;
    --gold-bg:  rgba(245, 158, 11, 0.16);
    --good:     #34d399;
    --good-bg:  rgba(16, 185, 129, 0.14);
    --warn:     #fbbf24;
    --bad:      #f87171;
  }
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html {
  /* Chrome on Android inflates text on pages it judges are not built for a
     phone. This one is. 100% rather than none, so somebody who has CHOSEN
     larger text in their settings still gets it. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  background: var(--bg);
  color: var(--ink);
  font-size: 16px;
  line-height: 1.45;
  /* Room for the bottom navigation, plus the phone's own safe area. */
  padding-bottom: calc(var(--nav-height) + var(--safe-bottom) + 8px);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* ── THE HEADER ─────────────────────────────────────────────────────────────
   Two lines when you are inside something: where you came from, then where you
   are. A phone has no surrounding context to remind somebody where they are,
   so the screen has to say it. */
.m-head {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--card);
  border-bottom: 1px solid var(--line);
  padding: 10px 14px;
  padding-top: calc(10px + env(safe-area-inset-top, 0px));
}

.m-back {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--muted);
  font-size: 13.5px;
  text-decoration: none;
  /* 44px of tappable area without 44px of visible chrome.
   *
   * It said this before and measured 32px: 6px of padding either side of a
   * 20px line box is 32, not 44. The intention was right and the arithmetic
   * was never checked, which is TABLED.md 1f exactly - the mobile suite has
   * never asserted that anything can be HIT, so a control could claim 44 in
   * a comment and ship at 32 on every screen. min-height states it instead
   * of implying it. */
  min-height: 44px;
  padding: 6px 8px 6px 0;
  margin: -6px 0 0 -8px;
}

.m-back::before { content: "‹"; font-size: 19px; line-height: 1; }

.m-title {
  font-size: 19px;
  font-weight: 650;
  line-height: 1.25;
  overflow-wrap: anywhere;
}

.m-sub { font-size: 13px; color: var(--muted); margin-top: 1px; }

/* ── THE BOTTOM NAVIGATION ──────────────────────────────────────────────────
   Four items, because a thumb reaches four comfortably and not five.

   At the bottom rather than the top: a phone is held at the bottom, and the
   top of a large screen needs a second hand. */
.m-nav {
  position: fixed;
  bottom: 0; left: 0; right: 0;
  z-index: 30;
  display: flex;
  background: var(--card);
  border-top: 1px solid var(--line);
  padding-bottom: var(--safe-bottom);
}

.m-nav a {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  height: var(--nav-height);
  color: var(--muted);
  text-decoration: none;
  font-size: 11px;
  position: relative;
  /* No grey flash on tap — it reads as a page loading when nothing is. */
  -webkit-tap-highlight-color: transparent;
}

.m-nav a.on { color: var(--accent); font-weight: 600; }
.m-nav .ico { font-size: 19px; line-height: 1; }

/* A count on Messages, because something waiting is the reason to look. */
.m-nav .count {
  position: absolute;
  top: 6px;
  margin-left: 20px;
  background: var(--bad);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  min-width: 17px;
  height: 17px;
  border-radius: 9px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 4px;
}

/* ── A ROW YOU TAP ──────────────────────────────────────────────────────────
   The whole row, not a link inside it. A small target on a phone is a target
   somebody misses while holding a coffee. */
.m-list { background: var(--card); border-top: 1px solid var(--line); }

.m-row {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 62px;
  padding: 11px 14px;
  border-bottom: 1px solid var(--line);
  color: inherit;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}

.m-row:active { background: var(--bg); }

.m-row .body { flex: 1; min-width: 0; }

.m-row .name {
  font-size: 15.5px;
  font-weight: 600;
  line-height: 1.3;
  overflow-wrap: anywhere;
}

.m-row .meta { font-size: 12.5px; color: var(--muted); margin-top: 2px; }

.m-row .chev { color: var(--muted); font-size: 20px; flex: 0 0 auto; }

/* ── A ROW WITH NOWHERE TO GO ────────────────────────────────────────────
   It must not look tappable — no chevron, no press state. But its TEXT is
   often the main content of the screen: a checklist item is the thing
   somebody opened the engagement to read, and greying it made the most
   important words on the page the faintest.

   So: the row is quiet, the name is not. */
.m-row.flat { cursor: default; }
.m-row.flat:active { background: transparent; }
.m-row.flat .name { font-weight: 500; color: var(--ink); }
.m-row.flat .meta { color: var(--muted); }

/* ── SECTIONS ───────────────────────────────────────────────────────────────*/
.m-section {
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 20px 14px 7px;
}

/* ── STATES ─────────────────────────────────────────────────────────────────*/
.m-empty {
  padding: 40px 24px;
  text-align: center;
  color: var(--muted);
  font-size: 14.5px;
  line-height: 1.55;
}

.m-loading { padding: 30px; text-align: center; color: var(--muted); font-size: 14px; }

/* A failure says what happened and what to do, not a spinner forever. */
.m-error {
  margin: 14px;
  padding: 13px 15px;
  background: #fdf3f3;
  border-left: 3px solid var(--bad);
  border-radius: 6px;
  font-size: 14px;
  line-height: 1.5;
}

/* ── SEARCH ─────────────────────────────────────────────────────────────────*/
.m-search-wrap { padding: 10px 14px; background: var(--card); border-bottom: 1px solid var(--line); }

.m-search {
  width: 100%;
  /* 16px exactly. Below it, iOS zooms in when the field is focused and the
     person is looking at half a page without knowing why. */
  font-size: 16px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--bg);
}

.m-search:focus { outline: none; border-color: var(--accent); background: var(--card); }

/* ── PILLS ──────────────────────────────────────────────────────────────────*/
.pill {
  display: inline-block;
  font-size: 11px;
  font-weight: 600;
  padding: 2px 7px;
  border-radius: 9px;
  vertical-align: middle;
}

.pill-owed { background: var(--gold-bg); color: var(--warn); }
.pill-done { background: var(--good-bg); color: var(--good); }
.pill-late { background: #fdf3f3; color: var(--bad); }
/* The client has sent it and a person still has to look. Distinct from
   pill-done: this one is waiting on the CPA, not on the client, and reading it
   as "received" is how a document sits unreviewed for a week. */
.pill-sent { background: var(--accent-bg, #e8f0ea); color: var(--accent, #1b4332); }

/* ── BUTTONS ────────────────────────────────────────────────────────────────*/
.m-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  width: 100%;
  min-height: 48px;
  border: none;
  border-radius: 10px;
  background: var(--accent);
  color: #fff;
  font-size: 15.5px;
  font-weight: 600;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.m-btn:active { opacity: 0.85; }
.m-btn[disabled] { opacity: 0.55; }

.m-btn.ghost { background: var(--card); color: var(--accent); border: 1px solid var(--line); }

.m-pad { padding: 14px; }

/* The link out to the desktop version was removed. It read as an apology —
   "this screen is not really finished" — on a phone website that should stand
   on its own. A CPA who wants the full version opens it on a laptop, and does
   not need a link at the bottom of every screen to remind them it exists. */


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

/* .hidden is defined in the desktop stylesheet, which this page does not load.
   A first version used it and the Messages badge rendered as a red dot with no
   number — a class name assumed rather than checked. */
.hidden { display: none !important; }

/* A <label> acting as a button needs to look and behave like one — the input
   it triggers is hidden, so the label IS the control. */
label.m-btn { cursor: pointer; }

/* ── A THREAD ───────────────────────────────────────────────────────────────
 *
 * The reply box is fixed above the bottom navigation and the thread scrolls
 * behind it, because a composer that scrolls away is one you have to hunt for
 * every time you want to answer.
 *
 * The thread's bottom padding clears the composer AND the nav AND the safe
 * area. Without it the newest message - the one somebody opened the screen to
 * read - sits underneath the box they are about to type in.
 */
.m-thread {
  padding: 12px 14px calc(var(--nav-height) + var(--safe-bottom) + 108px);
  min-height: 40vh;
}

.m-msg {
  max-width: 84%;
  margin-bottom: 10px;
  padding: 9px 12px;
  border-radius: 13px;
  font-size: 15px;
  line-height: 1.45;
}

/* Theirs on the left in plain card, ours on the right in the firm's gold.
 * Side AND colour, not colour alone: a thread read in sunlight on a phone is
 * often read at an angle, and position survives what contrast does not. */
.m-msg.theirs {
  background: var(--card);
  border: 1px solid var(--line);
  border-bottom-left-radius: 4px;
  margin-right: auto;
}
.m-msg.mine {
  background: var(--gold-bg);
  border: 1px solid #eee2be;
  border-bottom-right-radius: 4px;
  margin-left: auto;
}

.m-msg-who { font-size: 11.5px; color: var(--muted); margin-bottom: 3px; }

/* pre-wrap keeps the line breaks somebody typed. overflow-wrap breaks a
 * pasted URL or a 40-character reference rather than letting it push the
 * whole thread sideways. */
.m-msg-body { white-space: pre-wrap; overflow-wrap: anywhere; }

.m-closed {
  padding: 10px 14px;
  background: var(--bg);
  border-bottom: 1px solid var(--line);
  font-size: 13px;
  color: var(--muted);
}

/* ── THE COMPOSER ───────────────────────────────────────────────────────────
 *
 * Sits on the safe area so it clears the home indicator on a notched phone,
 * where a button flush to the bottom is one the operating system swallows.
 */
.m-reply {
  position: fixed;
  left: 0; right: 0;
  bottom: calc(var(--nav-height) + var(--safe-bottom));
  background: var(--card);
  border-top: 1px solid var(--line);
  padding: 9px 14px 11px;
  z-index: 30;
}

/* 16px is not a style choice. Below 16px, iOS Safari zooms the whole page in
 * when the field takes focus and does not zoom back out - so the thread is
 * left at 1.3x with the navigation off-screen. */
.m-reply textarea {
  width: 100%;
  box-sizing: border-box;
  font: inherit;
  font-size: 16px;
  line-height: 1.4;
  padding: 9px 11px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--bg);
  resize: none;
  /* One line of 16px text in a 9px-padded box is 42px. Four short of the
   * floor, on the control this screen exists for. */
  min-height: 44px;
  max-height: 140px;
  overflow-y: auto;
}
.m-reply textarea:focus { outline: none; border-color: var(--accent); background: var(--card); }

.m-reply-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 8px;
}
.m-reply-actions .m-btn { margin-left: auto; width: auto; padding: 0 20px; }

/* 44px, the floor Apple asks for and Android exceeds at 48. The clip glyph is
 * 19px; the hit area is what grows around it. TABLED.md 1f: the mobile suite
 * checks that pages fit and that inputs do not zoom, and has never checked
 * that anything can be HIT - which is how a 32px kebab shipped on the control
 * that opens every action on a client. */
.m-attach {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  font-size: 19px;
  cursor: pointer;
  border-radius: 9px;
  flex: 0 0 auto;
}
.m-attach:active { background: var(--bg); }

.m-attach-count { font-size: 12.5px; color: var(--muted); }

/* An attachment is a button rather than a link: it fetches through the
 * download gate and may come back 428 asking the person to confirm who they
 * are, which is not something an <a href> can express. */
.m-clip {
  display: inline-block;
  margin-top: 6px;
  padding: 9px 11px;
  min-height: 44px;
  box-sizing: border-box;
  font: inherit;
  font-size: 13px;
  text-align: left;
  color: var(--accent);
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 9px;
  cursor: pointer;
  overflow-wrap: anywhere;
}
.m-clip:active { background: var(--bg); }

/* A CPA asking for a document from their phone. Small, at the end of the row,
   because the row's job is still to say what is missing. */
/* ── 44px, BECAUSE A THUMB IS NOT A MOUSE POINTER ───────────────────────────
   Both of these were 35px and 34px tall. The phone suite enforces a 44px
   minimum hit area and had never measured this screen -- the note in
   cpa-phone-mobile.spec.js says so outright: "the archive and complete
   buttons, which nothing had ever measured". Run against /m/engagement for the
   first time on 14 September 2026, it found eighteen controls under the line.

   min-height on the HIT AREA, with the padding left alone, so the buttons look
   exactly as they did and are simply easier to hit. inline-flex keeps the label
   centred in the taller box rather than sitting at the top of it. */
.m-ask {
  flex: 0 0 auto; align-self: center;
  border: 1px solid var(--m-border, #ddd); border-radius: 7px;
  background: #fff; font: inherit; font-size: 13px; font-weight: 600;
  padding: 7px 12px; color: var(--m-accent, #1f6f5c); cursor: pointer;
  min-height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
}
.m-ask:disabled { opacity: .65; cursor: default; }

/* ── REVIEWING A DOCUMENT, ON A PHONE ────────────────────────────────────────
   A CPA between meetings looks at one page and says yes or no. That is the
   shortest piece of work in the product and the most worth having here, so it
   gets a real sheet rather than a row that merely reports there is work. */
.m-review {
  flex: 0 0 auto;
  border: 1px solid var(--accent, #1b4332);
  background: var(--accent, #1b4332);
  color: #fff;
  border-radius: 8px;
  padding: 7px 13px;
  font-size: 13px;
  font-weight: 600;
  /* Was 34px tall. See the note on .m-ask above. */
  min-height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
}
.m-sheet-backdrop {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(16, 22, 19, .45);
  display: flex; align-items: flex-end; justify-content: center;
}
.m-sheet {
  width: 100%; max-width: 560px;
  background: var(--bg, #fff);
  border-radius: 14px 14px 0 0;
  padding: 16px 16px calc(16px + var(--safe-bottom, 0px));
  /* Tall enough for a long label and a reason box, never taller than the
     screen -- a sheet you cannot reach the buttons of is not a sheet. */
  max-height: 88vh; overflow-y: auto;
  box-shadow: 0 -6px 24px rgba(0, 0, 0, .22);
}
.m-sheet-title { font-weight: 700; font-size: 16px; margin-bottom: 12px; }
.m-sheet-body { display: grid; gap: 10px; }
.m-sheet-actions { display: grid; gap: 8px; margin-top: 14px; }
.m-btn.good { background: var(--good, #1e6b3a); border-color: var(--good, #1e6b3a); color: #fff; }
.m-btn.bad  { background: #fff; border-color: var(--bad, #a02020); color: var(--bad, #a02020); }
.m-label { display: block; font-size: 13px; font-weight: 600; margin-bottom: 4px; }
.m-input {
  width: 100%; box-sizing: border-box;
  font: inherit; padding: 10px;
  border: 1px solid var(--line, #dcdcd4); border-radius: 8px;
  resize: vertical;
}

/* ── A GROUP BADGE, AND A NOTE ─────────────────────────────────────────────
   Added 1 October 2026 for the books page on the phone. Hari asked that two
   properties in one group "give them same label or something that shows both
   belong to the same group" -- so the badge is a real class rather than an
   inline style, because the desktop shows the same label and the two should not
   drift apart.
   Colours come from the existing variables, so dark mode needs nothing. */
.m-badge {
  display: inline-block;
  font-size: 11px; font-weight: 700; letter-spacing: 0.04em;
  padding: 1px 6px; margin-right: 6px;
  border: 1px solid var(--line, #dcdcd4); border-radius: 999px;
  background: var(--bg); color: var(--muted);
  vertical-align: 1px;
}
.m-note { margin: 0; font-size: 13px; color: var(--muted); }

/* ── A ROW THAT IS A BUTTON ────────────────────────────────────────────────
   Added 1 October 2026. Every m-row in the product is an <a>; the books page
   needs a <button>, because tapping it opens the camera rather than navigating,
   and a link that does not navigate lies to anybody using a screen reader.

   Without this the browser's own button styling wins: content-width instead of
   full width, its own border and background, centred text. The row rendered as a
   small grey box and Hari reported "from mobile, user can't select any of his
   belongings" - it was there and did not look like anything tappable. */
button.m-row {
  width: 100%;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--line);
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

/* ── A FILE INPUT A PHONE WILL ACTUALLY OPEN ──────────────────────────────────
 *
 * Hari, 2 October 2026, reporting it for the SECOND time: *"Still in the mobile
 * link - I am not able to select the individual belonging of the person"*.
 *
 * The first version hid the input with the `hidden` attribute, which is
 * `display:none`, and then called `.click()` on it from a tap handler. On a
 * desktop that works, which is why a desktop test passed. **iOS Safari will not
 * open the picker for an input that is `display:none`** -- the tap does nothing
 * at all, silently, which is his sentence exactly.
 *
 * So the input stays in the layout and is moved off-screen instead, and each row
 * is a <label for>, whose activation is native and needs no script. Not
 * `visibility:hidden` and not `width:0;height:0` on its own either: both have the
 * same problem in some versions. Off-screen with a real size is the shape that
 * works everywhere.
 *
 * The test that would have caught it is a REAL mobile browser, not a narrow
 * viewport -- the phone site is a separate site, and this is the second rule on
 * that page earning its place.
 */
.m-offscreen {
  position: absolute;
  left: -10000px;
  /* ── 44px, NOT 1px, AND THE REASON IS A REAL TEST ─────────────────────────
   *
   * This was 1x1 and cpa-phone-mobile.spec.js refused the screen:
   *
   *     Every control must be at least 44px in its smallest dimension — the HIT
   *     AREA, not the icon: ["input#m-shot.m-offscreen 1x1"]
   *
   * The spec is right to count it. It deliberately does NOT use display:none —
   * that is the whole reason this class exists, because iOS will not open the
   * picker for a display:none input — so the element genuinely IS in the layout,
   * and a rule about every control in the layout applies to it.
   *
   * 44px costs nothing here: the element sits 10,000px to the left of the
   * viewport and is fully transparent, so nobody can see or reach it either way.
   * Making it the minimum tap size satisfies the rule honestly rather than
   * carving an exception into the spec for it.
   */
  width: 44px;
  height: 44px;
  opacity: 0;
  overflow: hidden;
  /* NO pointer-events: none. It was here for a moment as "belt and braces" and it
   * is removed deliberately: label activation is an activation behaviour rather
   * than a pointer event, so it SHOULD be unaffected -- but "should" is doing the
   * work in that sentence, and the one path it would break is the real iOS picker,
   * which nothing here can test. The element sits 10,000px off-screen at zero
   * opacity, so there is nothing to protect against. */
}

/* A label behaves as a row, so the picker opens from the browser's own handling
 * of a label rather than from script. Mirrors button.m-row above it. */
label.m-row {
  width: 100%;
  display: flex;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--line);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

/* ── A GROUP OF KINDS INSIDE ONE COMPANY ──────────────────────────────────────
 *
 * The catalogue's own groups — "Buildings and land", "Vehicles, equipment and
 * belongings", "What is owed — not held". .m-section already separates COMPANIES;
 * this separates kinds within one of them, so it is quieter.
 *
 * NOT .m-sub, which already exists at line 105 with a different job. Caught
 * before shipping this time: a second meaning for one class name is the same
 * fault as the duplicate `group-pick` id, and the collision would only have shown
 * up on whichever page loaded first.
 */
.m-kindgroup {
  padding: 8px 14px 4px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--muted);
  background: var(--bg);
  border-bottom: 1px solid var(--line);
}

/* ── A CATEGORY ON THE PHONE, CLOSED UNTIL ASKED FOR ─────────────────────────
 *
 * Hari, 3 October 2026: "categorize by their belongings (17) - user should be able
 * to expand after he clicks the category". His own client drew 31 rows across 29
 * company sections before this — correct and unusable.
 */
.m-cat {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 48px;
  padding: 10px 14px;
  border: 0;
  border-bottom: 1px solid var(--line);
  background: var(--card);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.m-cat:active { background: var(--bg); }
.m-cat .cn { flex: 1; min-width: 0; font-weight: 600; overflow-wrap: anywhere; }
/* The count answers "which category is my receipt in" without opening each one. */
.m-cat .cc {
  flex: 0 0 auto;
  min-width: 1.7em;
  text-align: center;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--bg);
  color: var(--muted);
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
}
.m-cat .cx { flex: 0 0 auto; width: 1.1em; text-align: center; color: var(--muted); }
.m-cat.open { font-weight: 700; }

/* C-084: Accessible screen-reader-only label and WCAG AA 4.5:1+ footer stamp contrast (#475569 on #f8fafc = 7.18:1) */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.m-stamp {
  color: var(--muted, #475569);
}

