/* T030: mobile-first. The moment of use is one-handed, in a shop. */
:root {
  --bg: #fbfbfa; --fg: #1a1a18; --muted: #6b6b66; --line: #e3e3df;
  --accent: #2f6f4f; --danger: #a33; --card: #fff;
}
@media (prefers-color-scheme: dark) {
  :root { --bg:#16181a; --fg:#e9e9e6; --muted:#9a9a94; --line:#2c2f33;
          --accent:#6fbf95; --danger:#e08585; --card:#1e2124; }
}
* { box-sizing: border-box; }
body {
  margin: 0; padding: 1rem; background: var(--bg); color: var(--fg);
  font: 17px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif;
}
main { max-width: 34rem; margin: 0 auto; }
.topbar { display: flex; justify-content: space-between; align-items: center; gap: 1rem; }
.topbar-user { color: var(--muted); font-size: .9rem; margin-right: auto; }
h1 { font-size: 1.4rem; margin: .2rem 0 1rem; }
h2 { font-size: 1rem; color: var(--muted); margin: 1.6rem 0 .5rem; font-weight: 600; }
.add-form { display: flex; gap: .5rem; margin-bottom: 1rem; }
input[type=text], input:not([type]), input[type=password] {
  flex: 1; padding: .8rem; font-size: 1rem; border: 1px solid var(--line);
  border-radius: .5rem; background: var(--card); color: var(--fg); min-width: 0;
}
button {
  font: inherit; cursor: pointer; border-radius: .5rem; border: 1px solid transparent;
  padding: .8rem 1rem; background: var(--accent); color: #fff;
}
button.link { background: none; color: var(--muted); border: none; padding: .3rem;
  text-decoration: underline; font-size: .9rem; }
.items { list-style: none; margin: 0; padding: 0; }
.items li {
  display: flex; align-items: center; gap: .6rem; padding: .1rem 0;
  border-bottom: 1px solid var(--line);
}
.items .name { flex: 1; padding: .7rem 0; word-break: break-word; }
.items .name.done { text-decoration: line-through; color: var(--muted); }
/* The name is a link so it works without JavaScript, but it is not link-shaped: it is the
   item, and a blue underlined shopping list would be unreadable. */
.items a.name { color: inherit; text-decoration: none; cursor: text; }
/* The field must occupy the same box as the name it replaced, or the row jumps as soon as
   it is tapped — on a phone, out from under the thumb. */
.items .name-edit { flex: 1; padding: .7rem 0; font: inherit; color: inherit;
  background: none; border: none; border-bottom: 2px solid var(--line); min-width: 0; }
.meta { font-size: .75rem; color: var(--muted); }
/* Generous tap targets: this is used while holding a basket. */
.tick, .del { background: none; color: var(--muted); font-size: 1.3rem;
  padding: .5rem .7rem; min-width: 2.75rem; min-height: 2.75rem; }
.tick.done { color: var(--accent); }
.del { color: var(--danger); }
.inline { display: inline; margin: 0; }
.empty { color: var(--muted); font-style: italic; padding: 1rem 0; }
.error { color: var(--danger); }

/* Spec 016: offline indicator. A banner, not inline text, so it reads as a persistent state
   rather than a one-off message like .error. */
.offline-indicator {
  background: var(--danger);
  color: #fff;
  margin: 0 0 1rem;
  padding: .6rem .9rem;
  border-radius: .5rem;
  font-size: .9rem;
  text-align: center;
}
/* Spec 021: the offer to switch the icon count on. Deliberately quieter than
   .offline-indicator — that one reports a problem with the list, this one is an invitation
   that most members will never see. */
.badge-offer {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: .5rem;
  margin: 0 0 1rem;
  padding: .7rem .9rem;
  font-size: .9rem;
}
.badge-offer p { margin: 0 0 .5rem; }
/* Spec 023: the device report's footnote — an aside about the page itself, not shopping. */
.muted-note { color: var(--muted); font-size: .85rem; }
#badge-report { font-size: .9rem; }
#badge-report ul { margin: .3rem 0; padding-left: 1.2rem; }
.badge-offer-actions { display: flex; gap: .5rem; margin: 0; }

.card { background: var(--card); border: 1px solid var(--line); border-radius: .75rem;
  padding: 1.5rem; margin-top: 3rem; }
.card form { display: flex; flex-direction: column; gap: .4rem; }
.card label { font-size: .85rem; color: var(--muted); margin-top: .6rem; }
.card button { margin-top: 1.2rem; }

/* Build identity. Operational detail, not something a shopper reads — muted, and
   constrained so it can never push list content sideways on a narrow screen. */
footer.version {
  margin: 2rem 0 .5rem;
  font-size: .7rem;
  color: var(--muted);
  text-align: center;
  opacity: .7;
  overflow-wrap: anywhere;
  max-width: 100%;
}

/* Admin surface. Mobile-first: the account list is a stack of cards, not a table —
   a table with five columns cannot fit 375px without horizontal scrolling. */
.admin-form { display: flex; flex-direction: column; gap: .3rem; margin-bottom: 1.5rem; }
.admin-form label { font-size: .85rem; color: var(--muted); margin-top: .6rem; }
.admin-form button { margin-top: 1rem; align-self: flex-start; }
.admin-form .checkbox { display: flex; align-items: center; gap: .5rem; margin-top: .8rem;
  font-size: .95rem; color: var(--fg); }
.admin-form .checkbox input { width: auto; min-height: 1.2rem; }
.admin-list { list-style: none; margin: 0; padding: 0; }
.admin-list li { padding: .8rem 0; border-bottom: 1px solid var(--line);
  display: flex; flex-direction: column; gap: .5rem; }
.admin-list .who { display: flex; flex-wrap: wrap; align-items: baseline; gap: .5rem; }
.admin-list .actions { display: flex; flex-wrap: wrap; gap: .8rem; }
.tag { font-size: .7rem; padding: .1rem .45rem; border-radius: .6rem;
  background: var(--line); color: var(--muted); }
.tag.admin { background: var(--accent); color: #fff; }
.tag.locked { background: var(--danger); color: #fff; }

/* Help page. Prose, not interface: a comfortable measure and generous spacing, because
   this is the only page in the application anybody actually reads. */
.help { max-width: 34rem; }
.help h2 { font-size: 1.05rem; color: var(--fg); margin: 1.8rem 0 .4rem; font-weight: 600; }
.help p { margin: .5rem 0; line-height: 1.6; overflow-wrap: anywhere; }
.help em { font-style: normal; color: var(--accent); }
.help-footer { margin-top: 2.5rem; padding-top: 1rem; border-top: 1px solid var(--line); }

/* Navigation styled as buttons (issue #10).

   These stay <a href> elements. A <button> that navigates loses opening in a new tab,
   copying the address, and bookmarking; it needs JavaScript or a form to go anywhere, which
   the no-JavaScript requirement rules out; and a screen reader announces "button" for
   something that leaves the page. The look is identical either way, so there is nothing to
   gain by changing the element. */
.btn {
  display: inline-block;
  font: inherit;
  padding: .55rem .9rem;
  min-height: 2.75rem;          /* thumb-sized, like the list controls */
  line-height: 1.6rem;
  border-radius: .5rem;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--fg);
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
}
.btn:hover { border-color: var(--accent); color: var(--accent); }

/* The header now carries up to three of these. Wrapping is not decoration: at 375px an
   administrator sees Help, Accounts, and Sign out together, and without this the page
   would scroll sideways. */
.topbar { flex-wrap: wrap; row-gap: .5rem; }
.topbar .btn { padding: .45rem .7rem; min-height: 2.4rem; font-size: .9rem; }

/* Quiet by design: a cancel sitting next to "Yes, revoke" as an equal-weight button invites
   the wrong click on an action that removes somebody's access. */
.btn-quiet {
  background: none;
  border-color: transparent;
  color: var(--muted);
  text-decoration: underline;
}
.btn-quiet:hover { color: var(--fg); }

/* The one truly irreversible action in the app (spec 017 follow-up) — every other
   confirm button here uses the same accent green as "add an item". */
button.btn-danger { background: var(--danger); }

/* The bought-section toggle is the section heading itself, so it does not get a button box —
   a framed heading reads as a control that opens something else. It gets an affordance
   instead: a caret that follows aria-expanded, so the state is visible without JavaScript
   reading the DOM. */
#toggle-bought { font: inherit; color: var(--muted); text-decoration: none; padding: .4rem 0; }
#toggle-bought::after { content: " ▾"; font-size: .8em; }
#toggle-bought[aria-expanded="false"]::after { content: " ▸"; }
#toggle-bought:hover { color: var(--fg); }

/* Header on a narrow screen: fit on one line (issue: buttons wrapping).

   Tightening the gaps alone was not enough — the sign-out label carried the display name,
   which made it the widest element and would have grown with a longer name. The name is
   gone: it told the user something they already knew. `flex-wrap` stays as a safety net, so
   a future translation wraps the header rather than scrolling the page sideways, which is
   the worse failure. */
.topbar { gap: .35rem; }
.topbar h1 { font-size: 1.15rem; margin: .2rem .4rem .6rem 0; }
.topbar .btn { padding: .4rem .5rem; font-size: .82rem; min-height: 2.2rem; }

@media (max-width: 430px) {
  .topbar h1 { font-size: 1.05rem; }
}

/* A hard break between "To buy" and "Bought".

   The two lists look alike — same rows, same controls — and on a phone the boundary between
   "still needed" and "already in the basket" was carried by a heading alone. In a shop that
   is the one distinction that matters, so it gets a line rather than only whitespace. */
.section-divider {
  border: none;
  border-top: 2px solid var(--line);
  margin: 2rem 0 0;
}

/* Activity log. A stack of lines rather than a table: five columns cannot fit 375px, and
   the subject is the part most likely to be long. */
.activity-filter { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center;
  margin-bottom: 1.2rem; }
.activity-filter label { font-size: .8rem; color: var(--muted); }
.activity-filter select { padding: .4rem; border: 1px solid var(--line); border-radius: .4rem;
  background: var(--card); color: var(--fg); font: inherit; font-size: .85rem; max-width: 9rem; }
.activity { list-style: none; margin: 0; padding: 0; }
.activity li { padding: .6rem 0; border-bottom: 1px solid var(--line);
  display: flex; flex-wrap: wrap; gap: .4rem; align-items: baseline; font-size: .9rem; }
.activity .when { color: var(--muted); font-size: .78rem; white-space: nowrap; }
.activity .who { font-weight: 600; }
.activity .what { color: var(--muted); }
.activity .subject { overflow-wrap: anywhere; min-width: 0; }
.paging { display: flex; gap: .6rem; margin-top: 1.5rem; }

/* Paging controls. Wrap on a narrow screen rather than pushing the page sideways — five
   controls plus a counter does not fit 375px in one row. */
.paging { flex-wrap: wrap; align-items: center; }
.paging .page-of { font-size: .8rem; color: var(--muted); white-space: nowrap; }

/* The family bar (spec 006). Named on every signed-in page, so it has to survive a
   fifty-character family name on a 375px screen without pushing the page sideways. */
.family-bar {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-wrap: wrap;
  margin: 0 0 0.75rem;
  font-size: 0.95rem;
}

.family-label {
  color: var(--muted, #666);
}

.family-name,
.family-bar select {
  /* User-supplied text: allowed to be long, not allowed to widen the page. */
  max-width: 100%;
  min-width: 0;
  overflow-wrap: anywhere;
}

.family-switch {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-wrap: wrap;
  min-width: 0;
}

.family-switch select {
  max-width: 14rem;
  flex: 1 1 auto;
}

.no-family {
  max-width: 34rem;
  line-height: 1.5;
}

/* Labels that a screen reader needs and the layout does not. The families table repeats a
   name field per row, and an unlabelled input is unusable without sight. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* The families list: several controls per row, on a 375px screen. */
.admin-list.families .actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  align-items: center;
}

/* Each control is its own form, and `.inline` sets `display: inline` — which means the
   form is not a flex container, its input cannot shrink, and a fifty-character family name
   pushes the page sideways. Overridden here rather than globally: `.inline` is right
   everywhere else, where a form holds one button. */
.admin-list.families .actions > form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  min-width: 0;
  flex: 1 1 100%;
}

.admin-list.families .actions input {
  min-width: 0;
  flex: 1 1 6rem;
  max-width: 100%;
}

/* A family name is user-supplied and may be fifty characters with no spaces in it. */
.admin-list.families .who strong {
  overflow-wrap: anywhere;
  min-width: 0;
}

@media (min-width: 40rem) {
  /* Room for two controls per row once the screen allows it. */
  .admin-list.families .actions > form {
    flex: 0 1 auto;
  }
  .admin-list.families .actions input {
    max-width: 12rem;
  }
}
