/*
  Room for the phone's own furniture when this page is read inside the club's
  app, where it draws edge to edge and the bar would otherwise sit under the
  clock. Android publishes --safe-area-inset-*; iOS answers env(). Only one is
  ever set, so max() picks the platform, and both are zero in a browser.
*/
:root {
  --app-inset-top: max(
    var(--safe-area-inset-top, 0px),
    env(safe-area-inset-top, 0px),
    var(--app-min-inset-top, 0px)
  );
  --app-inset-bottom: max(var(--safe-area-inset-bottom, 0px), env(safe-area-inset-bottom, 0px));
}
/*
  The chat is a component that renders in two very different rooms: its own
  document, where this file is the only stylesheet, and the widget on the home
  page, where the whole site bundle is already loaded around it.

  Measured, rather than guessed at. Loading the site bundle beside this one
  changes appearance from auto to button, box-sizing from content-box to
  border-box, and gives every element a solid border style in the site's grey,
  all from the utility framework's reset. None of that is wrong of the site; it
  is simply not this component's idea of itself, and the reactions were wearing
  it.

  So the component states its own starting point. Written with :where(), which
  contributes nothing to specificity, so every rule below this beats it without
  having to be written twice as heavily -- the exact trap that put one emoji on
  each line a few days ago.
*/
:where(.chat), :where(.chat) :where(*, *::before, *::after) {
  box-sizing: border-box;
  /* Stated, because the site bundle states it too and they disagreed. Width
     zero either way, so nothing is drawn; what it buys is that an element
     given only a border colour behaves the same in both rooms. */
  border-width: 0;
  border-style: solid;
  border-color: currentColor;
  tab-size: 4;
}

/* Native control chrome off, and this one has to outrank a bare element
   selector rather than sit at zero, because that is what the site bundle uses
   to turn it back on. Nothing below sets appearance, so nothing is stepped on. */
.chat button,
.chat input,
.chat textarea,
.chat select {
  appearance: none;
  -webkit-appearance: none;
}

:where(.chat) :where(button, input, textarea, select) {
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  letter-spacing: normal;
  text-transform: none;
  appearance: none;
  -webkit-appearance: none;
}

:where(.chat) :where(p, h1, h2, h3, h4, ul, ol, li, figure) {
  margin: 0;
  padding: 0;
  list-style: none;
}

/*
  The chat surface, built to WhatsApp's conventions.
  ---------------------------------------------------------------------------
  Those conventions are not arbitrary: the bubble geometry, the timestamp
  tucked inside the bubble, the run grouping, the day dividers and the sticky
  composer are what make a thread readable at a glance on a small screen, and
  they are what our members already have muscle memory for. Copying the layout
  is the point. What is deliberately ours is the wallpaper, which is drawn here
  in CSS rather than lifted, and the palette, which is variables so a club can
  run its own colours instead of WhatsApp green.

  Written as its own stylesheet rather than utility classes because tails,
  dividers and run grouping are structural rules, not a bag of spacing, and
  because scoping every control here keeps it clear of the theme's global
  button styling.
*/

/* An author `display` beats the browser's own `[hidden] { display: none }`,
   which quietly made hiding the notifications banner do nothing at all. Set
   once here so it holds for anything added later, not just that one element. */
.chat [hidden] { display: none !important; }

.chat {
  --wa-scale: 1;
  --wa-bg: #efeae2;
  --wa-in: #ffffff;
  --wa-out: #d9fdd3;
  --wa-ink: #111b21;
  --wa-meta: rgba(17, 27, 33, 0.45);
  --wa-panel: #f0f2f5;
  --wa-send: #00a884;
  --wa-divider: rgba(255, 255, 255, 0.92);
  --wa-shadow: 0 1px 0.5px rgba(11, 20, 26, 0.13);
  /* The height of one line of composer, and therefore of every control on
     that row. Named once so they cannot drift apart. */
  --wa-row: 44px;
  /* The avatar, and therefore the lane it sits in. Grows with the type like
     everything else: a member who asked for larger text asked because things
     were hard to make out, and a 28px face is one of them. */
  --wa-face: calc(28px * var(--wa-scale));

  position: relative; /* the message menu positions against this */
  display: flex;
  flex-direction: column;
  min-height: 0;
  color: var(--wa-ink);
  font-size: calc(14.2px * var(--wa-scale));
  line-height: calc(19px * var(--wa-scale));
  -webkit-text-size-adjust: 100%;
}

/* The full-screen thread fills the viewport and scrolls only its messages,
   which is what stops the composer sliding away up the page mid-sentence.
   dvh rather than vh because a phone's address bar changes the answer. */
/* Pinned to the viewport rather than laid out in the document, so nothing the
   page does can push the composer below the fold. The height here is only the
   starting point: chat.js takes it over from visualViewport, which is the only
   measurement that accounts for a browser toolbar overlaying the page and for
   the on-screen keyboard. dvh gets close on Android and is wrong on iOS Safari
   often enough to matter. */
.chat--full {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 100vh;
}

@supports (height: 100dvh) {
  .chat--full { height: 100dvh; }
}

/* ---------- header ---------- */

.chat__bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: calc(8px + var(--app-inset-top)) 12px 8px;
  background: var(--wa-panel);
  border-bottom: 1px solid rgba(11, 20, 26, 0.08);
  flex: none;
}

.chat__back {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  margin-left: -8px;
  border-radius: 50%;
  color: var(--wa-ink);
  text-decoration: none;
  flex: none;
}

.chat__back svg { width: calc(22px * var(--wa-scale)); height: calc(22px * var(--wa-scale)); }

.chat__avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: #6a7175;
  color: #fff;
  font-weight: 600;
  font-size: 15px;
  flex: none;
  overflow: hidden;
}

.chat__who { min-width: 0; flex: 1; }

.chat__name {
  margin: 0;
  font-size: calc(16px * var(--wa-scale));
  font-weight: 600;
  line-height: 21px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.chat__sub {
  margin: 0;
  font-size: 12.5px;
  line-height: 16px;
  color: var(--wa-meta);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---------- the wallpaper ---------- */

.chat__panel {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  /* One finger still scrolls the thread; two fingers are ours, and the browser
     does not also zoom the page underneath. Without this a pinch does both at
     once and the result is neither. */
  touch-action: pan-y;
  padding: 12px 4% 8px;
  background-color: var(--wa-bg);
  /* Our own doodle, not theirs: three faint dot grids offset from each other,
     which reads as texture at arm's length and costs no request. */
  background-image:
    radial-gradient(circle at 12% 22%, rgba(11, 20, 26, 0.045) 1.5px, transparent 1.6px),
    radial-gradient(circle at 63% 71%, rgba(11, 20, 26, 0.035) 1.5px, transparent 1.6px),
    radial-gradient(circle at 87% 34%, rgba(11, 20, 26, 0.03) 1.2px, transparent 1.3px);
  background-size: 78px 78px, 121px 121px, 59px 59px;
}

.chat__panel {
  display: flex;
  flex-direction: column;
}

/* Everything in the thread moves as one block, pushed down so a short
   conversation rests on the composer rather than hanging from the top of an
   empty screen. */
.chat__stack {
  margin-top: auto;
  display: flex;
  flex-direction: column;
}

.chat__list {
  list-style: none;
  margin: 0;
  /* The left gutter is the lane the faces sit in. Indenting here rather than
     narrowing the bubbles, so a message does not rewrap the day somebody adds
     a photo. Tied to the face, so the lane is always exactly wide enough for
     whatever size the reader has asked for. */
  padding: 0 0 0 calc(8px + var(--wa-face));
  display: flex;
  flex-direction: column;
}

/* ---------- day dividers ---------- */

.chat__day {
  align-self: center;
  margin: 12px 0;
  padding: 5px 12px 6px;
  border-radius: 7.5px;
  background: var(--wa-divider);
  box-shadow: var(--wa-shadow);
  font-size: calc(12.5px * var(--wa-scale));
  font-weight: 500;
  text-transform: uppercase;
  color: var(--wa-meta);
  letter-spacing: 0.2px;
}

/* ---------- bubbles ---------- */

.chat__msg {
  position: relative;
  max-width: 85%;
  margin-top: 2px;
  padding: 6px 7px 8px 9px;
  border-radius: 7.5px;
  background: var(--wa-in);
  box-shadow: var(--wa-shadow);
  align-self: flex-start;
  overflow-wrap: anywhere;
}

.chat__msg--mine {
  align-self: flex-end;
  background: var(--wa-out);
}

/* A run of messages from one person reads as one turn, so only the first
   carries the tail, the name and the extra breathing room above it. */
.chat__msg--first { margin-top: 10px; }
.chat__msg--first { border-top-left-radius: 0; }
.chat__msg--mine.chat__msg--first {
  border-top-left-radius: 7.5px;
  border-top-right-radius: 0;
}

.chat__msg--first::before {
  content: "";
  position: absolute;
  top: 0;
  width: 8px;
  height: 13px;
  background: inherit;
  left: -8px;
  clip-path: polygon(100% 0, 100% 100%, 0 0);
}

.chat__msg--mine.chat__msg--first::before {
  left: auto;
  right: -8px;
  clip-path: polygon(0 0, 0 100%, 100% 0);
}

.chat__sender {
  display: block;
  margin-bottom: 1px;
  font-size: calc(12.8px * var(--wa-scale));
  font-weight: 500;
  line-height: calc(17px * var(--wa-scale));
}

.chat__text {
  margin: 0;
  white-space: pre-wrap;
  /* Room for the timestamp, which sits on the last line of the text rather
     than under it. This is the trick that keeps a one-word message small.
     Scaled with the type: the timestamp grows with everything else, and a
     fixed reservation gets overrun the moment somebody pinches out. */
}

/* Room for the timestamp, on the last line only.
   ---------------------------------------------------------------------------
   This was padding-right, which reserves the space on every line rather than
   the one the clock actually sits on. On a phone, where the bubble is most of
   the screen, that is a little waste nobody notices. In the widget on the home
   page, where the column is a third as wide, it took eighty of maybe two
   hundred pixels off every line and squashed the message into a ribbon.

   An empty inline-block at the end of the text is the standard trick and the
   right one: it takes its room from the last line, wraps to a new one when
   that line is full, and costs nothing on the lines above. */
/* A link to a page on this site, inside a message.

   Underlined and coloured rather than made into a button: it sits in the middle
   of a sentence somebody wrote, and a block button mid paragraph breaks the line
   badly on a phone. Large enough to hit, though: the padding gives it a target
   without pushing the line height around, and word-break stops a long path
   forcing the bubble wider than the screen. */
.chat__link {
  color: #0a5ca8;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
  padding: 2px 1px;
  word-break: break-word;
}
.chat__link:active {
  opacity: .6;
}
/* On a photo the bubble goes dark, so the link has to come up with it. */
.chat__msg--onphoto .chat__link {
  color: #cfe6ff;
}

.chat__text::after {
  content: '';
  display: inline-block;
  width: calc(64px * var(--wa-scale));
  height: 1px;
  vertical-align: bottom;
}

/* Your own messages carry ticks after the time, so they need the extra. */
.chat__msg--mine /* A link to a page on this site, inside a message.

   Underlined and coloured rather than made into a button: it sits in the middle
   of a sentence somebody wrote, and a block button mid paragraph breaks the line
   badly on a phone. Large enough to hit, though: the padding gives it a target
   without pushing the line height around, and word-break stops a long path
   forcing the bubble wider than the screen. */
.chat__link {
  color: #0a5ca8;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
  padding: 2px 1px;
  word-break: break-word;
}
.chat__link:active {
  opacity: .6;
}
/* On a photo the bubble goes dark, so the link has to come up with it. */
.chat__msg--onphoto .chat__link {
  color: #cfe6ff;
}

.chat__text::after { width: calc(82px * var(--wa-scale)); }
.chat__msg--edited /* A link to a page on this site, inside a message.

   Underlined and coloured rather than made into a button: it sits in the middle
   of a sentence somebody wrote, and a block button mid paragraph breaks the line
   badly on a phone. Large enough to hit, though: the padding gives it a target
   without pushing the line height around, and word-break stops a long path
   forcing the bubble wider than the screen. */
.chat__link {
  color: #0a5ca8;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
  padding: 2px 1px;
  word-break: break-word;
}
.chat__link:active {
  opacity: .6;
}
/* On a photo the bubble goes dark, so the link has to come up with it. */
.chat__msg--onphoto .chat__link {
  color: #cfe6ff;
}

.chat__text::after { width: calc(96px * var(--wa-scale)); }
.chat__msg--mine.chat__msg--edited /* A link to a page on this site, inside a message.

   Underlined and coloured rather than made into a button: it sits in the middle
   of a sentence somebody wrote, and a block button mid paragraph breaks the line
   badly on a phone. Large enough to hit, though: the padding gives it a target
   without pushing the line height around, and word-break stops a long path
   forcing the bubble wider than the screen. */
.chat__link {
  color: #0a5ca8;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
  padding: 2px 1px;
  word-break: break-word;
}
.chat__link:active {
  opacity: .6;
}
/* On a photo the bubble goes dark, so the link has to come up with it. */
.chat__msg--onphoto .chat__link {
  color: #cfe6ff;
}

.chat__text::after { width: calc(114px * var(--wa-scale)); }



/* Sent, delivered, read. Grey until somebody has read it, then the blue
   everybody already reads as "they have seen it". */
.chat__ticks {
  display: inline-flex;
  align-items: center;
  color: var(--wa-meta);
}

/* Height fixed, width left to follow it: the double tick is a wider drawing
   than the single one and squeezing both into a square is what made the pair
   overlap into a smudge. */
.chat__ticks svg { width: auto; height: calc(16px * var(--wa-scale)); display: block; }
.chat__ticks.is-read { color: #53bdeb; }

.chat__meta {
  position: absolute;
  right: 7px;
  bottom: 4px;
  display: flex;
  align-items: center;
  gap: 3px;
  font-size: calc(11px * var(--wa-scale));
  line-height: calc(15px * var(--wa-scale));
  color: var(--wa-meta);
  white-space: nowrap;
}

.chat__edited { font-style: italic; }

/* ---------- the action menu on your own message ---------- */

.chat__more {
  position: absolute;
  top: 0;
  right: 0;
  width: 34px;
  height: 26px;
  border: 0;
  padding: 0;
  background: linear-gradient(to left, var(--wa-out) 60%, transparent);
  border-radius: 0 7.5px 0 8px;
  color: var(--wa-meta);
  cursor: pointer;
  opacity: 0;
  transition: opacity .12s;
}

.chat__msg--mine:hover .chat__more,
.chat__msg--mine:focus-within .chat__more,
.chat__more:focus-visible { opacity: 1; }

.chat__more svg { width: calc(18px * var(--wa-scale)); height: calc(18px * var(--wa-scale)); }

.chat__menu {
  position: absolute;
  z-index: 30;
  min-width: 148px;
  /* Never wider than the screen it has to fit on. The row of faces is the
     widest thing in here and a phone is the narrowest place it goes. */
  max-width: calc(100vw - 16px);
  padding: 6px 0;
  border-radius: 8px;
  background: #fff;
  box-shadow: 0 2px 8px rgba(11, 20, 26, 0.28);
}

.chat__menu button {
  display: block;
  width: 100%;
  padding: 10px 18px;
  border: 0;
  background: none;
  text-align: left;
  font: inherit;
  font-size: 14.5px;
  color: var(--wa-ink);
  cursor: pointer;
}

.chat__menu button:hover { background: rgba(11, 20, 26, 0.05); }
.chat__menu button.is-danger { color: #c0392b; }

/* ---------- composer ---------- */

.chat__composer {
  flex: none;
  display: flex;
  align-items: flex-end;
  gap: 8px;
  padding: 6px 8px calc(6px + env(safe-area-inset-bottom));
  background: var(--wa-panel);
}

/* The pill. The field's background moves out here so the emoji and the camera
   sit inside it rather than beside it, which is the whole of the difference
   between this composer and the one everybody already uses. */
.chat__pill {
  flex: 1;
  min-width: 0;
  box-sizing: border-box;
  min-height: var(--wa-row);
  display: flex;
  /* Bottom aligned, not centred: once the box has grown to three lines the
     emoji and the camera belong beside the last line, where the cursor is,
     not floating in the middle of the paragraph. */
  align-items: flex-end;
  gap: 2px;
  padding: 0 4px;
  border-radius: 21px;
  background: #fff;
}

.chat__input {
  flex: 1;
  min-width: 0;
  /* Or min-height is the height of the words and the 22px of padding is added
     on top of it, which made a one line box 66px tall against 44px buttons:
     the composer looked two lines deep before anybody had typed anything.
     A textarea does not inherit this from anywhere, and this stylesheet has
     no global reset to inherit it from. */
  box-sizing: border-box;
  /* One line, and the same height as everything beside it.
     11 + 22 + 11 is 44, which is what the two buttons in the pill and the
     round one outside it are, so an empty composer is one flat row rather
     than a 43px box with 40px buttons sitting slightly low against it. It is
     also the smallest thing a thumb reliably hits. */
  min-height: var(--wa-row);
  max-height: 40vh;
  padding: 11px 6px;
  border: 0;
  border-radius: 21px;
  background: transparent;
  font: inherit;
  /* Never below 16px whatever the size setting: under that, iOS zooms the
     whole page the moment the field takes focus. */
  font-size: max(16px, calc(16px * var(--wa-scale)));
  /* Scales with the text, so the row grows when somebody asks for bigger
     type rather than the words growing inside a fixed box. */
  line-height: calc(22px * var(--wa-scale));
  resize: none;
  outline: none;
}

.chat__said {
  flex: none;
  margin: 0;
  padding: 6px 14px;
  background: var(--wa-panel);
  color: #c0392b;
  font-size: 13px;
  font-weight: 600;
}

.chat__empty {
  align-self: center;
  margin: 24px 8px;
  padding: 10px 14px;
  border-radius: 7.5px;
  background: var(--wa-divider);
  box-shadow: var(--wa-shadow);
  font-size: 13.5px;
  color: var(--wa-meta);
  text-align: center;
}

/* The banner offering notifications, styled as WhatsApp styles its own
   in-thread notices rather than as a button bolted to the top. */
/* A suggestion, not a warning. Sits in the thread the way WhatsApp's own
   system notices do, rather than as a coloured bar shouting above it. */
.chat__nudge {
  align-self: center;
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 12px 8px 0;
  padding: 7px 8px 7px 14px;
  border-radius: 7.5px;
  background: var(--wa-divider);
  box-shadow: var(--wa-shadow);
  font-size: 12.5px;
  color: var(--wa-meta);
}

.chat__nudge button {
  flex: none;
  padding: 5px 12px;
  border: 0;
  border-radius: 14px;
  background: var(--wa-send);
  color: #fff;
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
}

/* ---------- the home page widget ---------- */

.chat--widget {
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid rgba(11, 20, 26, 0.12);
}

.chat--widget .chat__panel {
  height: 46vh;
  min-height: 220px;
  max-height: 420px;
}

@media (min-width: 640px) {
  .chat__msg { max-width: 65%; }
  .chat--widget .chat__panel { height: 340px; }
}

/* ---------- the conversation list ---------- */

.inbox {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  background: #fff;
}

.inbox__row {
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 10px 15px;
  text-decoration: none;
  color: inherit;
  border-bottom: 1px solid rgba(11, 20, 26, 0.08);
}

.inbox__row:active { background: rgba(11, 20, 26, 0.05); }

.inbox__body { min-width: 0; flex: 1; }

.inbox__top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}

.inbox__name {
  font-size: 16px;
  font-weight: 500;
  line-height: 22px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.inbox__when {
  flex: none;
  font-size: 12px;
  color: var(--wa-meta);
}

.inbox__last {
  display: block;
  margin-top: 1px;
  font-size: 14px;
  line-height: 20px;
  color: var(--wa-meta);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.inbox__quiet { font-style: italic; }

.inbox__none {
  margin: 0;
  padding: 28px 20px;
  color: var(--wa-meta);
  text-align: center;
  font-size: 14px;
}

/* The text size control, where somebody who cannot read the thread will
   actually find it rather than behind a settings page. */
.chat__size {
  flex: none;
  min-width: 40px;
  height: 40px;
  padding: 0 8px;
  border: 0;
  border-radius: 20px;
  background: transparent;
  color: var(--wa-ink);
  font: inherit;
  font-size: 15px;
  font-weight: 700;
  cursor: pointer;
}

.chat__size:active { background: rgba(11, 20, 26, 0.08); }

/* Passing the squad's link on. The squad module's sheet gives .share-btn a
   dark pill, which is right on a page and wrong on this bar, so the bar says
   otherwise: two classes beat one and the icon button wins here. */
.chat__bar .share-btn {
  flex: none;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 0;
  border-radius: 20px;
  background: transparent;
  color: var(--wa-ink);
  cursor: pointer;
}

.chat__bar .share-btn svg { width: calc(20px * var(--wa-scale)); height: calc(20px * var(--wa-scale)); display: block; }
.chat__bar .share-btn:active { background: rgba(11, 20, 26, 0.08); }

/* ---------- sending, and recording ---------- */

/* The round green button. A microphone until there is something to send and a
   paper plane after it, because two buttons means one of them is always the
   wrong one to press. */
.chat__go {
  flex: none;
  width: var(--wa-row);
  height: var(--wa-row);
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--wa-send);
  color: #fff;
  cursor: pointer;
}

.chat__go svg { width: calc(22px * var(--wa-scale)); height: calc(22px * var(--wa-scale)); display: block; }
.chat__go:active { filter: brightness(0.92); }

/* What the composer becomes while something is being recorded. Over the top of
   it rather than beside it: there is nothing else to do until this is sent or
   thrown away. */
.chat__rec {
  position: absolute;
  inset: auto 0 0;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
  background: var(--wa-panel);
}

.chat__rec-time { font-variant-numeric: tabular-nums; font-weight: 700; font-size: 15px; }
.chat__rec-hint { flex: 1; font-size: 13px; color: var(--wa-meta); }

.chat__rec-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #e0362c;
  animation: chat-rec-pulse 1.4s ease-in-out infinite;
}

@keyframes chat-rec-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }

/* Nothing blinks for anybody who has asked for less of that. */
@media (prefers-reduced-motion: reduce) {
  .chat__rec-dot { animation: none; }
}

.chat__rec-stop,
.chat__rec-send {
  flex: none;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
}

.chat__rec-stop { color: #e0362c; }
.chat__rec-send { background: var(--wa-send); color: #fff; }
.chat__rec-stop svg,
.chat__rec-send svg { width: calc(22px * var(--wa-scale)); height: calc(22px * var(--wa-scale)); display: block; }

/* A voice message in the thread. The browser's own player: it already has a
   scrubber, a clock and a speed control that people know. */
.chat__voice { display: block; width: 100%; max-width: 260px; margin: 2px 0; }

/* ---------- pictures ---------- */

/* Drawn at the width of the bubble and no more, with the shape reserved from
   the message so the thread does not jump while it loads. */
.chat__photo {
  display: block;
  width: 100%;
  max-width: 320px;
  height: auto;
  margin: 2px 0 4px;
  border-radius: 6px;
  background: rgba(11, 20, 26, 0.06);
  cursor: pointer;
}

/* A picture nobody said anything about.
   Every other message ends in a line of text, and the clock takes its room
   from the end of that line. A photograph has no such line, so the clock sits
   on the photograph, where it is white on whatever the picture happens to be
   there: white on a cloudy sky is nothing at all. It gets something to be read
   against, and the picture goes flush to the edges of the bubble, because a
   frame of white around a photo is a frame around nothing. */
.chat__msg--onphoto { padding: 3px; }
.chat__msg--onphoto .chat__photo { margin: 0; border-radius: 5px; }

.chat__msg--onphoto .chat__meta {
  right: 10px;
  bottom: 9px;
  padding: 2px 7px 3px;
  border-radius: 10px;
  background: rgba(11, 20, 26, 0.45);
  color: rgba(255, 255, 255, 0.92);
}

.chat__msg--onphoto .chat__ticks { color: rgba(255, 255, 255, 0.92); }
.chat__msg--onphoto .chat__ticks.is-read { color: #aee4ff; }

.chat__big { text-align: center; }
.chat__big img { max-width: 100%; max-height: 66vh; border-radius: 6px; }
.chat__big-caption { margin: 10px 0 0; font-size: 14px; color: var(--wa-ink); }

/* Take a photo, or choose one. Asked before the picker opens, because capture
   sends a phone straight to its camera and cannot be talked out of it after. */
.chat__choice {
  display: block;
  width: 100%;
  margin: 0 0 8px;
  padding: 14px 16px;
  border: 1px solid rgba(11, 20, 26, 0.12);
  border-radius: 10px;
  background: #fff;
  font: inherit;
  font-size: 16px;
  font-weight: 600;
  text-align: left;
  color: var(--wa-ink);
  cursor: pointer;
}

.chat__choice:active { background: rgba(11, 20, 26, 0.06); }

/* The two buttons inside the pill. Grey, so the green one outside it is the
   only thing on the row that looks like it does something final. */
.chat__emoji,
.chat__attach {
  flex: none;
  width: var(--wa-row);
  height: var(--wa-row);
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: rgba(11, 20, 26, 0.45);
  cursor: pointer;
}

.chat__emoji svg,
.chat__attach svg { width: calc(22px * var(--wa-scale)); height: calc(22px * var(--wa-scale)); display: block; }
.chat__emoji:active,
.chat__attach:active { background: rgba(11, 20, 26, 0.08); color: var(--wa-ink); }

/* ---------- who is talking ---------- */

/* Their face beside the first message of a run, outside the bubble, the way a
   group chat has done it since group chats existed. The lane is indented to
   make room rather than the bubble being made narrower: a message that loses
   width every time somebody has a photo is a message that rewraps. */
.chat__face {
  position: absolute;
  left: calc(-8px - var(--wa-face));
  top: 0;
  width: var(--wa-face);
  height: var(--wa-face);
  border-radius: 50%;
  overflow: hidden;
  display: grid;
  place-items: center;
  color: #fff;
  font-size: calc(13px * var(--wa-scale));
  font-weight: 700;
  line-height: 1;
  user-select: none;
}

/* The photo covers the initial underneath it. If it never loads, the initial
   is what is left, rather than a broken picture. */
.chat__face img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}


/* ---------- reactions ---------- */

/* Hung off the bottom edge of the bubble rather than sitting inside it.
   Inside, it reads as part of what the person said; overlapping the corner, it
   reads as something done to the message, which is what it is. Anchored to the
   left corner for both directions, the way WhatsApp does it, so a reaction is
   always in the same place whoever sent the message. */
.chat__reacts {
  position: absolute;
  left: 8px;
  /* Hung further off the bottom edge, so it reads as something stuck onto the
     message rather than tucked under its corner. */
  bottom: -19px;
  z-index: 2;
  display: flex;
  flex-wrap: nowrap;
  gap: 3px;
}

/* An overlay reserves no space of its own, so the message underneath has to
   be told to move down out of the way. */
.chat__msg--reacted { margin-bottom: 22px; }

.chat__react {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  height: calc(22px * var(--wa-scale));
  padding: 0 calc(6px * var(--wa-scale));
  /* A plain grey edge rather than a tint of the ink. It sits against a white
     bubble, a green one and the page behind both, and a neutral line is the
     only one that looks deliberate against all three. */
  border: 1px solid #e4e7ea;
  border-radius: 11px;
  background: #fff;
  box-shadow: 0 1px 2px rgba(11, 20, 26, 0.12);
  font: inherit;
  font-size: calc(12px * var(--wa-scale));
  line-height: 1;
  color: var(--wa-ink);
  cursor: pointer;
}

/* Yours, so a glance says whether you have already answered. The tint does
   that work; the edge stays the same grey as everybody else's, because a
   green outline on a green bubble is a second thing to look at. */
.chat__react.is-mine {
  border-color: #cfd9d2;
  background: var(--wa-out);
}

.chat__react[disabled] { cursor: default; }
.chat__react-face { font-size: calc(13px * var(--wa-scale)); line-height: 1; }

/* The grey face beside the bubble. Sits outside it, on the side the bubble is
   not, so it never covers a word. Always drawn rather than revealed on hover,
   because a phone has no hover and a control you cannot discover is a control
   that does not exist. */
.chat__react-open {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  right: -30px;
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: rgba(11, 20, 26, 0.38);
  cursor: pointer;
}

.chat__msg--mine .chat__react-open { right: auto; left: -30px; }
.chat__react-open:active { background: rgba(11, 20, 26, 0.08); color: var(--wa-ink); }
.chat__react-n { font-variant-numeric: tabular-nums; font-weight: 600; }

/* The row you pick from, at the top of the message menu. Bigger than the
   counted faces because this one is a target and those are a readout. */
.chat__pick {
  display: flex;
  /* Seven faces at 40px is 280, and a narrow phone has less. Wrapping to a
     second row of faces is fine; one face per row is not, which is what the
     rule above stops. */
  flex-wrap: wrap;
  justify-content: center;
  gap: 2px;
  padding: 6px 6px 8px;
  border-bottom: 1px solid rgba(11, 20, 26, 0.08);
  margin-bottom: 4px;
}

/* Two classes, not one.
   .chat__menu button is a class and an element, which outranks a single class,
   so the menu's own "stack these as full width rows" rule was winning over the
   sizes below and putting one face on each line. The faces are a row; the
   words under them are the rows. */
.chat__pick .chat__pick-one,
.chat__pick .chat__pick-more {
  display: inline-grid;
  place-items: center;
  width: 40px;
  min-width: 40px;
  height: 40px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  text-align: center;
  line-height: 1;
  cursor: pointer;
}

.chat__pick .chat__pick-one { background: transparent; font-size: 22px; }
.chat__pick .chat__pick-one:active { background: rgba(11, 20, 26, 0.08); }
.chat__pick .chat__pick-one.is-mine { background: #e7fce3; }

/* The way to everything else. */
.chat__pick .chat__pick-more { background: rgba(11, 20, 26, 0.06); color: var(--wa-ink); }
.chat__pick .chat__pick-more:active { background: rgba(11, 20, 26, 0.14); }

/* The quick row on its own, off the grey face: no list of words under it, so
   it does not want the menu's column width. */
.chat__menu--pick { min-width: 0; padding: 0; }
.chat__menu--pick .chat__pick { border-bottom: 0; margin-bottom: 0; padding: 6px; }

/* Everything else, in the sheet. A hundred and fifty faces is a wall, so
   there are two ways through it: the drawer it is in, and its name. */
.chat__grid { display: flex; flex-direction: column; min-height: 0; }

.chat__grid-find {
  box-sizing: border-box;
  width: 100%;
  min-height: 44px;
  margin: 0 0 8px;
  padding: 10px 12px;
  border: 1px solid rgba(11, 20, 26, 0.18);
  border-radius: 10px;
  font: inherit;
  /* 16px or iOS zooms the whole sheet the moment it takes focus. */
  font-size: 16px;
  color: var(--wa-ink);
  background: #fff;
}

/* One row, scrolled sideways rather than wrapped to three: the drawers are a
   row you flick along, and a block of them pushes the faces off the screen. */
.chat__grid-tabs {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  padding-bottom: 8px;
  scrollbar-width: none;
}

.chat__grid-tabs::-webkit-scrollbar { display: none; }

.chat__grid-tab {
  flex: none;
  min-height: 36px;
  padding: 7px 13px;
  border: 1px solid rgba(11, 20, 26, 0.14);
  border-radius: 18px;
  background: #fff;
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
  color: var(--wa-ink);
  cursor: pointer;
}

.chat__grid-tab.is-on {
  background: var(--wa-out);
  border-color: rgba(11, 20, 26, 0.24);
}

.chat__grid-body { flex: 1 1 auto; min-height: 0; max-height: 46vh; overflow-y: auto; }
.chat__grid-none { margin: 16px 0; font-size: 14px; color: var(--wa-meta); text-align: center; }
.chat__grid-name {
  margin: 10px 0 4px;
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: rgba(11, 20, 26, 0.5);
}
.chat__grid-name:first-child { margin-top: 0; }
.chat__grid-faces {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(44px, 1fr));
  gap: 2px;
}
.chat__grid-one {
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
}
.chat__grid-one:active { background: rgba(11, 20, 26, 0.08); }

/* ---------- the visitor's panel ---------- */

/* Somebody who has just found the site has no conversations of their own, so
   they get this one instead of a login they cannot use: a panel over the page
   they were reading, reaching whoever runs the club. */
.ask {
  position: fixed;
  z-index: 1200;
  right: 16px;
  bottom: 84px;
  left: 16px;
  max-width: 380px;
  max-height: min(70vh, 560px);
  display: flex;
  flex-direction: column;
  border-radius: 14px;
  overflow: hidden;
  background: var(--wa-bg, #efeae2);
  box-shadow: 0 12px 32px rgba(11, 20, 26, 0.28);
  font-family: inherit;
}

@media (min-width: 480px) {
  .ask { left: auto; width: 380px; }
}

.ask[hidden] { display: none; }

.ask__bar {
  flex: none;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 8px 12px 16px;
  background: var(--wa-panel, #f0f2f5);
}

.ask__title {
  flex: 1;
  min-width: 0;
  font-size: 15px;
  font-weight: 600;
  color: var(--wa-ink, #111b21);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ask__close {
  flex: none;
  width: 36px;
  height: 36px;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--wa-ink, #111b21);
  display: grid;
  place-items: center;
  cursor: pointer;
}

.ask__close svg { width: 20px; height: 20px; }

.ask__intro {
  padding: 16px;
  background: #fff;
}

.ask__hello {
  margin: 0 0 14px;
  font-size: 14px;
  line-height: 20px;
  color: var(--wa-ink, #111b21);
}

.ask__start { display: grid; gap: 6px; }

.ask__label {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--wa-meta, rgba(17, 27, 33, 0.45));
}

.ask__input {
  min-height: 44px;
  padding: 10px 12px;
  border: 1px solid rgba(11, 20, 26, 0.2);
  border-radius: 8px;
  font: inherit;
  font-size: 16px; /* under 16px iOS zooms the page on focus */
}

.ask__go {
  justify-self: start;
  margin-top: 4px;
  min-height: 44px;
  padding: 0 20px;
  border: 0;
  border-radius: 22px;
  background: var(--wa-send, #00a884);
  color: #fff;
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
}

/* The thread inside the panel is the same one the rest of the site draws; it
   just has a ceiling rather than a whole screen. */
.chat--ask {
  flex: 1 1 auto;
  min-height: 0;
}

.chat--ask .chat__panel { padding: 10px 12px 6px; }

/* The report and block sheets.
   Built in chat.js rather than reusing the theme's askReason, because this
   page is its own document and does not load the theme bundle. Sized for a
   thumb: a 48px target on every control, because the membership is mostly
   over 50 and this is the screen somebody uses when they are already upset. */
.chat__sheet {
  position: fixed; inset: 0; z-index: 60;
  display: flex; align-items: flex-end; justify-content: center;
  background: rgba(17, 24, 39, .45);
  padding: 0;
}
@media (min-width: 640px) {
  .chat__sheet { align-items: center; padding: 24px; }
}
.chat__sheet-panel {
  background: #fff; width: 100%; max-width: 460px;
  border-radius: 14px 14px 0 0;
  padding: 20px 20px calc(20px + env(safe-area-inset-bottom, 0px));
  box-shadow: 0 -8px 40px rgba(0, 0, 0, .25);
  max-height: 85vh; overflow-y: auto;
}
@media (min-width: 640px) {
  .chat__sheet-panel { border-radius: 14px; padding-bottom: 20px; }
}
.chat__sheet-title { margin: 0 0 10px; font-size: 18px; font-weight: 700; color: #111827; }
.chat__sheet-note { margin: 0 0 10px; font-size: 14px; line-height: 1.45; color: #4b5563; }
.chat__reasons { display: grid; gap: 2px; margin: 12px 0; }
.chat__reasons label {
  display: flex; align-items: center; gap: 10px;
  min-height: 48px; padding: 0 10px; border-radius: 8px;
  font-size: 15px; color: #111827; cursor: pointer;
}
.chat__reasons label:hover { background: #f3f4f6; }
.chat__reasons input { width: 20px; height: 20px; }
.chat__sheet-input {
  width: 100%; box-sizing: border-box; margin-top: 4px; padding: 10px;
  border: 1px solid #d1d5db; border-radius: 8px;
  font: inherit; font-size: 15px; resize: vertical;
}
.chat__sheet-actions { display: flex; gap: 10px; margin-top: 16px; }
.chat__sheet-actions button {
  flex: 1 1 0; min-height: 48px; border-radius: 8px;
  font-size: 15px; font-weight: 700; font-family: inherit; cursor: pointer;
}
.chat__sheet-cancel { background: #fff; color: #374151; border: 1px solid #9ca3af; }
.chat__sheet-confirm { background: #1f2937; color: #fff; border: none; }
.chat__sheet-confirm.is-danger { background: #b91c1c; }
