/* HHMS resident portal — mobile-first.
   Self-contained: no external fonts, no CDN, no build step.

   Written for a phone held one-handed on a bus, not for a desk. Everything
   tappable clears 48px, the type never drops below 16px (below that iOS zooms
   the whole page on focus), and the primary navigation sits at the bottom
   inside thumb reach. The desktop layout is the afterthought here, which is
   the reverse of console.css and deliberate. */

:root {
  --bg: #f4f6fa;
  --panel: #ffffff;
  --ink: #16202e;
  --muted: #64748b;
  --line: #dfe5ee;
  --brand: #2563eb;
  --brand-ink: #1d4ed8;
  --on-brand: #ffffff;
  --ok: #15803d;    --ok-bg: #e8f6ec;
  --warn: #b45309;  --warn-bg: #fdf3e2;
  --bad: #b91c1c;   --bad-bg: #fdecec;
  --off: #6b7280;   --off-bg: #eef1f5;
  --radius: 14px;
  --shadow: 0 1px 2px rgba(16, 32, 46, .06), 0 4px 14px rgba(16, 32, 46, .05);
  --tap: 48px;

  /* The parts of a form the browser draws for itself -- a select's wheel, a
     date input's calendar, a file input's Choose File button -- take none of
     the tokens above. They read this one property, and with it undeclared the
     browser assumes a light page and paints them white: on Anne's phone at
     night, five white pills down a dark card.

     `light dark` and not `dark`, because this stylesheet follows the system
     (see the prefers-color-scheme block below) rather than forcing a theme. A
     flat `dark` would fix the phone at night and leave a black select sitting
     on a white card by day. */
  color-scheme: light dark;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0e1420;
    --panel: #161e2c;
    --ink: #e8edf5;
    --muted: #94a3b8;
    --line: #263144;
    --brand: #60a5fa;
    --brand-ink: #93c5fd;
    --on-brand: #0e1420;
    --ok: #6ee7a0;    --ok-bg: #10321f;
    --warn: #fbbf24;  --warn-bg: #35270c;
    --bad: #fca5a5;   --bad-bg: #3a1414;
    --off: #94a3b8;   --off-bg: #1e2735;
    --shadow: 0 1px 2px rgba(0, 0, 0, .4);
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.55 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  /* Room for the fixed tab bar plus the iOS home indicator. */
  padding-bottom: calc(72px + env(safe-area-inset-bottom, 0px));
}

a { color: var(--brand-ink); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ------------------------------------------------------------- brand bar */
.pbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 16px calc(12px + env(safe-area-inset-top, 0px));
  background: var(--panel);
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 10;
}

.pbrand { display: flex; align-items: center; gap: 9px; color: var(--ink); }
.pbrand:hover { text-decoration: none; }
.pbrand strong { display: block; font-size: 1rem; letter-spacing: .2px; }
.pbrand small { display: block; color: var(--muted); font-size: .68rem; }

.psignout button {
  min-height: var(--tap);
  padding: 0 14px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: .9rem;
  cursor: pointer;
}

/* ----------------------------------------------------------------- page */
.ppage { padding: 16px; max-width: 720px; margin: 0 auto; }

.phead { margin: 4px 0 16px; }
.phead h1 { margin: 0; font-size: 1.5rem; letter-spacing: -.01em; }
.phead .pmeta { color: var(--muted); font-size: .9rem; margin-top: 2px; }

/* ---------------------------------------------------------------- cards */
.card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  margin-bottom: 14px;
  overflow: hidden;
}
.card > h2 {
  margin: 0;
  padding: 14px 16px;
  font-size: .82rem;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--muted);
  border-bottom: 1px solid var(--line);
}
.card > .body { padding: 16px; }

/* A big single number — balance, day count, warning position. */
.hero { text-align: center; padding: 24px 16px; }
.hero .value { font-size: 2.6rem; font-weight: 700; letter-spacing: -.02em; line-height: 1.1; }
.hero .label { color: var(--muted); font-size: .95rem; margin-top: 6px; }

/* Label/value rows. Stacks on the narrowest phones so long values never
   collide with their label. */
.rows { display: grid; gap: 2px; }
.row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  padding: 11px 0;
  border-bottom: 1px solid var(--line);
}
.row:last-child { border-bottom: 0; }
.row .k { color: var(--muted); font-size: .9rem; flex: 0 0 auto; }
.row .v { text-align: right; font-weight: 600; }
@media (max-width: 360px) {
  .row { flex-direction: column; align-items: flex-start; gap: 2px; }
  .row .v { text-align: left; }
}

/* A tappable list item — a warning, an invoice, a checklist run. */
.item {
  display: block;
  min-height: var(--tap);
  padding: 14px 16px;
  border-bottom: 1px solid var(--line);
  color: var(--ink);
}
.item:last-child { border-bottom: 0; }
.item:hover { text-decoration: none; background: var(--off-bg); }
.item .t { font-weight: 600; display: flex; justify-content: space-between; gap: 10px; }
.item .s { color: var(--muted); font-size: .88rem; margin-top: 3px; }

/* --------------------------------------------------------------- pills */
.pill {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: .78rem;
  font-weight: 600;
  white-space: nowrap;
}
.pill.ok   { background: var(--ok-bg);   color: var(--ok); }
.pill.warn { background: var(--warn-bg); color: var(--warn); }
.pill.bad  { background: var(--bad-bg);  color: var(--bad); }
.pill.off  { background: var(--off-bg);  color: var(--off); }

/* ------------------------------------------------------------ progress */
.bar { height: 8px; border-radius: 999px; background: var(--off-bg); overflow: hidden; }
.bar > span { display: block; height: 100%; background: var(--brand); }

/* --------------------------------------------------------- empty states */
/* A new resident has no warnings, no invoices, and no checklist runs. That is
   the good outcome, so it reads as reassurance rather than as a blank page. */
.empty { text-align: center; padding: 28px 20px; color: var(--muted); }
.empty .mark { font-size: 1.8rem; line-height: 1; margin-bottom: 8px; }
.empty p { margin: 0; }

/* ---------------------------------------------------------------- forms */
.field { margin-bottom: 14px; }
.field label { display: block; font-size: .9rem; color: var(--muted); margin-bottom: 6px; }
.field input {
  width: 100%;
  min-height: var(--tap);
  padding: 0 14px;
  font: inherit;              /* 16px — anything smaller triggers iOS zoom */
  color: var(--ink);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 10px;
}
.field input:focus { outline: 2px solid var(--brand); outline-offset: 1px; }
.field .help { color: var(--muted); font-size: .82rem; margin-top: 6px; }
.field .help ul { margin: 4px 0 0; padding-left: 18px; }

/* `.field` above is the sign-in and first-run screens. Everything a resident
   fills in after that -- a pass, a request, a reply -- uses `.fld`, and `.fld`
   had no styling at all: the pass form rendered a 21px white select and two
   23px white date inputs, browser defaults on a dark card, at under half the
   48px this file sets as the floor for anything a thumb has to hit.

   `.pform` marks a form whose fields are laid out this way. The card gives its
   form no padding of its own -- the chat composer wants to sit flush -- so the
   padding belongs to the form that wants it rather than to every card. */
.pform { padding: 16px; }

.fld, .filelabel { display: block; margin-bottom: 14px; }
.fld:last-of-type, .filelabel:last-of-type { margin-bottom: 16px; }
.fld > span, .filelabel > span {
  display: block;
  font-size: .9rem;
  color: var(--muted);
  margin-bottom: 6px;
}

.fld input, .fld select, .fld textarea, .filelabel input[type="file"] {
  width: 100%;
  color: var(--ink);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 10px;
  /* Spelled out rather than `font: inherit`: on .filelabel that would inherit
     the label's smaller size and drop the control under the 16px floor, which
     is what makes iOS zoom the page on focus. */
  font-family: inherit;
  font-size: 16px;
  line-height: 1.5;
}
.fld input, .fld select { min-height: var(--tap); padding: 0 12px; }
.fld textarea { padding: 11px 12px; resize: vertical; }
/* Beats `.card textarea`, which self-pads for the chat composer. Inside a
   .fld the padding is the form's job and the two together indent it twice. */
.card .fld textarea { width: 100%; margin: 0; }
.filelabel input[type="file"] { padding: 11px 12px; }
/* The Choose Files button is the browser's, and inherits nothing. */
.filelabel input[type="file"]::file-selector-button {
  margin-right: 10px;
  padding: 7px 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--panel);
  color: var(--ink);
  font-family: inherit;
  font-size: .9rem;
  cursor: pointer;
}
.fld input:focus-visible,
.fld select:focus-visible,
.fld textarea:focus-visible,
.filelabel input:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }

/* Send, on all three forms, is a bare <button type="submit">: no class, so no
   styling, so a 24px #f0f0f0 native pill directly under fields that now look
   like ours. Same box as .btn, which it would have used had it been given the
   class. */
.pform button[type="submit"] {
  display: block;
  width: 100%;
  min-height: var(--tap);
  padding: 0 18px;
  border: 0;
  border-radius: 10px;
  background: var(--brand);
  color: var(--on-brand);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

.btn {
  display: block;
  width: 100%;
  min-height: var(--tap);
  padding: 0 18px;
  border: 0;
  border-radius: 10px;
  background: var(--brand);
  color: var(--on-brand);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

.alert {
  padding: 12px 14px;
  border-radius: 10px;
  background: var(--bad-bg);
  color: var(--bad);
  font-size: .92rem;
  margin-bottom: 14px;
}
.alert.info { background: var(--warn-bg); color: var(--warn); }

/* ------------------------------------------------------------- tab bar */
.tabs {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 20;
  display: flex;
  background: var(--panel);
  border-top: 1px solid var(--line);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.tabs a {
  flex: 1;
  min-height: var(--tap);
  padding: 8px 2px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  color: var(--muted);
  font-size: .68rem;
  text-align: center;
}
.tabs a:hover { text-decoration: none; }
.tabs a.on { color: var(--brand-ink); font-weight: 600; }
.tabs .ic { font-size: 1.15rem; line-height: 1; }

.foot { text-align: center; color: var(--muted); font-size: .8rem; padding: 4px 16px 20px; }

/* Wider screens: the tab bar becomes a normal row above the content rather
   than a floating bar, which on a laptop reads as a phone emulator. */
@media (min-width: 720px) {
  body { padding-bottom: 0; }
  .tabs {
    position: static;
    max-width: 720px;
    margin: 16px auto -4px;
    border: 1px solid var(--line);
    border-radius: var(--radius);
  }
}

/* ----------------------------------------------------------------- chat */
/* Bubbles rather than rows: a conversation on a phone is read by shape
   before it is read by name, and the sender's own messages have to be
   findable at a glance while scrolling with a thumb. */
.msg { margin: 0 16px 12px; display: flex; flex-direction: column; align-items: flex-start; }
.msg.mine { align-items: flex-end; }
.msg .who { color: var(--muted); font-size: .78rem; margin-bottom: 3px; }
.msg .who small { opacity: .8; }
.bubble {
  background: var(--off-bg);
  color: var(--ink);
  padding: 10px 13px;
  border-radius: 16px;
  max-width: 82%;
  /* A pasted URL or a long unbroken word must not widen the page. */
  overflow-wrap: anywhere;
}
.msg.mine .bubble { background: var(--brand); color: var(--on-brand); }
/* A removed message stays on screen as a gap that explains itself. Hiding
   the row entirely leaves a conversation that no longer makes sense. */
.bubble.gone { background: transparent; border: 1px dashed var(--line); color: var(--muted); font-style: italic; }

#stream { padding: 14px 0 4px; }
#stream .muted { padding: 0 16px 12px; }

.card textarea {
  width: calc(100% - 32px);
  margin: 14px 16px 0;
  padding: 11px 12px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--bg);
  color: var(--ink);
  /* 16px minimum: anything smaller and iOS zooms the page on focus. Named
     rather than `inherit` -- `font: 16px/1.5 inherit` is invalid shorthand and
     the browser drops the whole declaration, leaving a monospace composer. */
  font-family: inherit;
  font-size: 16px;
  line-height: 1.5;
  resize: vertical;
}
.card textarea:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
.card button.primary {
  margin: 10px 16px 16px;
  min-height: var(--tap);
  padding: 0 20px;
  border: 0;
  border-radius: 10px;
  background: var(--brand);
  color: var(--on-brand);
  font: inherit;
  font-weight: 600;
}
/* A whole list row that submits a form: same box as .item, no button chrome. */
button.item.wide {
  width: 100%;
  text-align: left;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--line);
  font: inherit;
  color: inherit;
  cursor: pointer;
}
/* The unread badge is emptied rather than removed by the poller, so an
   already-read row would otherwise keep a grey dot where a count used to be. */
.pill:empty { display: none; }
.muted { color: var(--muted); }
.card > .muted, .card > p.warn { padding: 0 16px 14px; margin: 12px 0 0; }
p.warn { color: var(--warn); }

/* ----------------------------------------------------------- community feed */
/* A board, not a conversation: full-width cards read top-down, so no bubbles
   and no left/right split. */
.post { padding: 14px 16px; }
.posthead { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin-bottom: 6px; }
.posthead .who { font-weight: 600; font-size: .9rem; }
.posthead .when { color: var(--muted); font-size: .78rem; }
.posttitle { font-weight: 700; font-size: 1.05rem; line-height: 1.3; }
.posttitle.gone { color: var(--muted); font-style: italic; font-weight: 500; }
.postbody { margin-top: 6px; overflow-wrap: anywhere; }

/* Thumbnails in a grid that reflows to one column on a narrow phone. Every
   src is a /files/... view URL that redirects to a short-lived presigned
   link — a storage URL is never rendered. */
.shots { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 8px; margin-top: 10px; }
.shots img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 10px;
  background: var(--off-bg);
  display: block;
}


/* ------------------------------------------------- header bell (2026-08-25) */
.baractions { display: flex; align-items: center; gap: 6px; }
.bell {
  position: relative; display: flex; align-items: center; justify-content: center;
  width: var(--tap); height: var(--tap); border-radius: 10px;
  font-size: 1.25rem; color: var(--muted); text-decoration: none;
}
.bell:hover { text-decoration: none; }
.bell .badge {
  position: absolute; top: 6px; right: 5px;
  min-width: 19px; height: 19px; padding: 0 5px;
  border-radius: 999px; background: var(--bad); color: #fff;
  font-size: .68rem; font-weight: 700; line-height: 19px; text-align: center;
  border: 2px solid var(--panel);
}

/* Badge on a bottom-bar tab (Messages, More). */
.tabs a { position: relative; }
.tabs .dot {
  position: absolute; top: 5px; right: 50%; margin-right: -20px;
  min-width: 17px; height: 17px; padding: 0 4px; border-radius: 999px;
  background: var(--bad); color: #fff; font-size: .64rem; font-weight: 700;
  line-height: 17px; text-align: center;
}

/* iOS Safari auto-zooms any control under 16px on focus, which then leaves the
   page scrolled sideways. 16px is the floor, not a preference. */
input, select, textarea, button { font-size: 16px; }

/* Nothing overflows sideways at 390px: long unbroken strings wrap, and any
   table that must stay wide scrolls inside its own box rather than stretching
   the page. */
body { overflow-x: hidden; }
.card, .item, .row { min-width: 0; }
.item .muted, .item .t { overflow-wrap: anywhere; }
table { display: block; overflow-x: auto; max-width: 100%; }
