/* Mobile-first: base rules target small screens, media queries add layout for
   larger viewports. Keep specificity flat, avoid framework dependency. */

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  background: #f5f6f8;
  color: #1a1a1a;
  line-height: 1.5;
}

.container {
  width: 100%;
  max-width: 480px;
  margin: 0 auto;
  padding: 16px;
}

header.site-header {
  position: sticky;
  top: 0;
  z-index: 20;
  background: #ffffff;
  border-bottom: 1px solid #e2e4e8;
  padding: 12px 16px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

body.has-bottom-nav {
  padding-bottom: 76px;
}

.bottom-nav {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 20;
  display: flex;
  align-items: flex-end;
  justify-content: space-around;
  background: #ffffff;
  border-top: 1px solid #e2e4e8;
  padding: 8px 16px calc(8px + env(safe-area-inset-bottom));
}

.bottom-nav a {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  color: #888;
  text-decoration: none;
  font-size: 0.75rem;
  min-width: 64px;
}

.bottom-nav a svg {
  width: 22px;
  height: 22px;
  stroke: currentColor;
}

.bottom-nav a.active {
  color: #2450d8;
  font-weight: 600;
}

/* Unread-count badge, WeChat style. .badge-pill is the shared red-circle
   look; .nav-badge positions it on the top-right corner of the Message tab's
   icon (nav-icon-wrap gives it something to anchor to); .badge-inline is the
   same look sitting in normal flow, used on the message thread row
   (messages.html) next to the timestamp. Empty text collapses it away
   entirely rather than showing a bare red dot with no count. */
.nav-icon-wrap {
  position: relative;
  display: inline-flex;
}

.badge-pill {
  background: #e53935;
  color: #fff;
  font-size: 0.65rem;
  font-weight: 700;
  line-height: 1;
  min-width: 16px;
  height: 16px;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 3px;
}

.badge-pill:empty {
  display: none;
}

/* Bare red dot (no count) -- flags a single row as needing this account's
   action, e.g. one row among several on performer-tasks.html's list view.
   Same red as .badge-pill, just without the pill's number-sized chrome. */
.action-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #e53935;
}

.nav-badge {
  position: absolute;
  top: -4px;
  right: -8px;
}

header.site-header .brand {
  font-weight: 700;
  font-size: 1.1rem;
  color: #2450d8;
  text-decoration: none;
}

/* WeChat-style page bar: fixed-minimum-width side slots so the title stays
   visually centered when both sides are icons/empty; a text action (e.g.
   "Save") is allowed to grow past that minimum instead of clipping. */
.header-side {
  min-width: 32px;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
}

.header-side button {
  background: none;
  border: none;
  padding: 0;
  font-size: 1.7rem;
  line-height: 1;
  color: #2450d8;
  cursor: pointer;
}

.header-side button.header-text-action {
  font-size: 0.95rem;
  font-weight: 600;
}

.header-title {
  flex: 1 1 auto;
  min-width: 0;
  text-align: center;
  font-size: 1.05rem;
  font-weight: 600;
  margin: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: 0 4px;
}

/* App-shell pages (anything with the bottom tab bar) go edge-to-edge flat,
   like WeChat's own screens -- no floating shadowed cards, just white
   sections on the gray page background with a little gap between groups.
   No top padding here: the first section sits flush against the header,
   same as WeChat's own screens -- the gap (from .card's margin-bottom
   below) only ever appears *between* sections, never before the first one. */
body.has-bottom-nav .container {
  padding: 0;
}

body.has-bottom-nav .card {
  border-radius: 0;
  box-shadow: none;
  margin: 0 0 10px;
  padding: 16px;
}

/* A card whose only content is a list of self-padded rows (.menu-row /
   .profile-row, each already `padding: 10px 0` with a divider between them)
   should have no vertical padding of its own -- otherwise the card's 16px
   stacks on top of the row's own 10px, giving the first/last row visibly
   more surrounding space (26px) than the ~20px gap between two rows. Real
   WeChat grouped lists start/end flush like this; only add `.card-list` to
   a card that has *nothing else* in it needing its own padding (a plain
   text banner, form controls, etc. still needs the default `.card` padding). */
body.has-bottom-nav .card.card-list {
  padding: 0 16px;
}

/* WeChat-contacts-style small section label sitting directly on the page
   background, in the gap before a card-grouped list -- not inside the
   card itself (that's what makes it read as a section divider rather than
   a heading inside the list).

   Standard rule: a section *without* a title needs no extra top gap of its
   own -- flush against the header (if first) or against the previous
   card's margin-bottom (if not) is already correct, unchanged. A section
   *with* a title always gets a little breathing room on both sides of the
   title text itself. Default padding-top covers the case where this is the
   very first thing in the page (nothing above it but the header, so it
   needs its own gap) -- overridden to 0 right below when a .card actually
   precedes it, since that card's margin-bottom (10px) already provides the
   gap and this would otherwise stack on top of it (10+10=20px, visibly
   more than the normal 10px between two plain cards). */
.section-title {
  padding: 10px 16px 6px;
  font-size: 0.8rem;
  color: #888;
}

.card + .section-title {
  padding-top: 0;
}

header.site-header nav {
  display: flex;
  align-items: center;
}

header.site-header nav a {
  color: #333;
  text-decoration: none;
  margin-left: 12px;
  font-size: 0.95rem;
}

.lang-switch {
  display: flex;
  margin-left: 12px;
  border-left: 1px solid #e2e4e8;
  padding-left: 12px;
}

.lang-switch button {
  background: none;
  border: none;
  color: #888;
  font-size: 0.85rem;
  cursor: pointer;
  padding: 4px 6px;
}

.lang-switch button.active {
  color: #2450d8;
  font-weight: 700;
}

.settings-section {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid #eee;
}

.settings-section h2 {
  font-size: 1.1rem;
  margin: 0 0 14px;
}

select {
  width: 100%;
  padding: 12px;
  font-size: 1rem;
  border: 1px solid #cfd3da;
  border-radius: 8px;
  background: #fff;
}

.card {
  background: #ffffff;
  border-radius: 12px;
  padding: 24px;
  margin-top: 24px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}

h1 {
  font-size: 1.5rem;
  margin: 0 0 8px;
}

p.tagline {
  color: #555;
  margin: 0 0 20px;
}

form {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

label {
  font-size: 0.9rem;
  font-weight: 600;
  margin-bottom: 4px;
  display: block;
}

input[type="text"],
input[type="email"],
input[type="password"] {
  width: 100%;
  padding: 12px;
  font-size: 1rem;
  border: 1px solid #cfd3da;
  border-radius: 8px;
}

button.primary {
  width: 100%;
  padding: 14px;
  font-size: 1rem;
  font-weight: 600;
  color: #fff;
  background: #2450d8;
  border: none;
  border-radius: 8px;
  cursor: pointer;
}

button.primary:disabled {
  opacity: 0.6;
  cursor: default;
}

/* Generic fallback so non-.primary action buttons (e.g. admin reject
   buttons, which set their own inline colors) still show a visible busy
   state when disabled via withBusy(). */
button:disabled {
  opacity: 0.6;
  cursor: default;
}

button.secondary {
  width: 100%;
  padding: 14px;
  font-size: 1rem;
  font-weight: 600;
  color: #2450d8;
  background: #fff;
  border: 1px solid #2450d8;
  border-radius: 8px;
  cursor: pointer;
}

button.secondary:disabled {
  opacity: 0.6;
  cursor: default;
}

/* Set by withBusy() (assets/js/api.js) for the duration of an in-flight
   action -- covers plain <a> "buttons" (e.g. logout links), where the
   `disabled` DOM property has no visual/behavioral effect. */
.is-busy {
  opacity: 0.6;
  pointer-events: none;
  cursor: default;
}

.form-footer {
  text-align: center;
  margin-top: 16px;
  font-size: 0.9rem;
}

.error-message {
  background: #fdecea;
  color: #b3261e;
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 0.9rem;
  display: none;
}

.error-message.visible {
  display: block;
}

.success-message {
  background: #e6f4ea;
  color: #1e7e34;
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 0.9rem;
  display: none;
}

.success-message.visible {
  display: block;
}

.profile-row {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid #eee;
  font-size: 0.95rem;
}

.profile-row:last-child {
  border-bottom: none;
}

.profile-row > span:first-child {
  flex-shrink: 0;
}

.profile-row > strong {
  font-weight: 400;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: right;
}

.menu-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid #eee;
  font-size: 0.95rem;
  font-family: inherit;
  color: #1a1a1a;
  text-decoration: none;
  background: none;
  border-left: none;
  border-right: none;
  border-top: none;
  text-align: left;
  cursor: pointer;
}

.menu-row:last-child {
  border-bottom: none;
}

.menu-row > span:first-child {
  flex-shrink: 0;
}

.menu-row .menu-row-chevron {
  flex-shrink: 0;
  color: #bbb;
  font-size: 1.1rem;
}

.menu-row-value {
  display: flex;
  align-items: center;
  gap: 2px;
  min-width: 0;
  color: #888;
}

.menu-row-select {
  appearance: none;
  -webkit-appearance: none;
  border: none;
  background: none;
  font: inherit;
  color: inherit;
  text-align: right;
  cursor: pointer;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.menu-row-select:focus {
  outline: none;
}

/* A single choice within a settings sub-page (e.g. pick a language) --
   tapping just stages the selection (aria-checked), the page's header Save
   button is what actually commits it. */
.option-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  padding: 14px 0;
  border-bottom: 1px solid #eee;
  font-size: 0.95rem;
  font-family: inherit;
  color: #1a1a1a;
  background: none;
  border-left: none;
  border-right: none;
  border-top: none;
  text-align: left;
  cursor: pointer;
}

.option-row:last-child {
  border-bottom: none;
}

.option-row .option-check {
  color: #2450d8;
  font-weight: 700;
  visibility: hidden;
}

.option-row[aria-checked="true"] .option-check {
  visibility: visible;
}

.menu-row-danger {
  color: #b3261e;
}

/* Two-way chat window (message-detail.html) -- WeChat style: the current
   user's own messages are right-aligned/green bubbles, everyone else
   (admin, another author, or a system notification with no sender) is
   left-aligned/white. This page replaces the standard bottom-nav shell
   entirely -- a fixed input bar takes its place (see UI_STYLE_GUIDE.md
   "Chat window pages"). */
body.chat-page {
  padding-bottom: 64px;
}

.chat-messages {
  padding: 12px 12px 4px;
}

.chat-bubble-row {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  margin: 4px 0;
}

.chat-bubble-row.mine {
  justify-content: flex-end;
}

.chat-bubble-row.theirs {
  justify-content: flex-start;
}

/* DOM order is always avatar-then-bubble (see message-detail.html); `order`
   flips the avatar after the bubble for "mine" so it lands on the right.
   Note: flex-direction: row-reverse would NOT do this correctly -- it also
   flips what "flex-end" means (main-axis end becomes the left), which
   silently pushes justify-content: flex-end content to the wrong side. */
.chat-bubble-row.mine .chat-avatar {
  order: 2;
}

.chat-bubble-row.mine .chat-bubble {
  order: 1;
}

/* Smaller than the 44px contact-list avatar (messages.html) -- same square-
   rounded look, scoped to chat bubbles so the list avatar size elsewhere is
   unaffected. */
.chat-bubble-row .chat-avatar {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  font-size: 0.85rem;
  margin-bottom: 2px;
}

.chat-bubble {
  max-width: 75%;
  padding: 10px 14px;
  border-radius: 16px;
  font-size: 0.95rem;
  line-height: 1.45;
  word-break: break-word;
  white-space: pre-wrap;
}

.chat-bubble-row.mine .chat-bubble {
  background: #95ec69;
  color: #1a1a1a;
  border-bottom-right-radius: 4px;
}

.chat-bubble-row.theirs .chat-bubble {
  background: #ffffff;
  color: #1a1a1a;
  border: 1px solid #eee;
  border-bottom-left-radius: 4px;
}

.chat-bubble-title {
  display: block;
  font-weight: 600;
  margin-bottom: 2px;
}

.chat-timestamp {
  text-align: center;
  font-size: 0.72rem;
  color: #999;
  margin: 14px 0 6px;
}

.chat-input-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 8px;
  background: #ffffff;
  border-top: 1px solid #e2e4e8;
  padding: 8px 10px calc(8px + env(safe-area-inset-bottom));
}

.chat-input-bar input[type="text"] {
  flex: 1;
  padding: 10px 14px;
  border: 1px solid #cfd3da;
  border-radius: 18px;
  font: inherit;
}

.chat-input-bar button {
  width: auto;
  padding: 10px 16px;
  border-radius: 18px;
  flex-shrink: 0;
}

/* WeChat-style contact list rows (messages.html, admin's multi-thread
   inbox) -- small square-rounded avatar with the counterparty's initial,
   next to name + last-message preview + time + unread badge. Deliberately
   no chevron, same exception as any other chat-list row (see "The '>'
   rule"). */
.chat-avatar {
  width: 44px;
  height: 44px;
  border-radius: 10px;
  background: #2450d8;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.1rem;
  font-weight: 700;
  flex-shrink: 0;
}

/* Tablet / desktop: give the card breathing room instead of edge-to-edge. */
@media (min-width: 600px) {
  .container {
    padding: 40px 16px;
  }

  .card {
    padding: 32px;
  }

  header.site-header,
  .bottom-nav,
  .chat-input-bar {
    max-width: 480px;
    margin-left: auto;
    margin-right: auto;
    border-left: 1px solid #e2e4e8;
    border-right: 1px solid #e2e4e8;
  }
}
