/*  Chat, announcements and events.
    ========================================================================
    The chat surface follows the WhatsApp conventions people already know:
    a fixed header naming who you are talking to, a scrolling transcript of
    bubbles with mine on the right and theirs on the left, a day divider, a
    time in the corner of each bubble, and a composer pinned to the bottom.

    Deliberately NOT copied: avatars, reply-quote, forward, star, voice
    notes, read ticks. Read state exists in the data but is private and only
    drives the Home badge -- showing ticks would promise a delivery guarantee
    this has no push channel to keep.

    Colours come from the host app's own tokens, so the same file works in
    BoothWeb amber and SectorWeb green without a per-app copy.               */

/* ── shell ───────────────────────────────────────────────────────────── */

.chat-wrap {
    display: flex;
    flex-direction: column;

    /*  Pinned between the two bars rather than sized in viewport units.
        Three things made the arithmetic version wrong: <main> adds 16px of
        padding that pushed the column down without shortening it, so the
        composer ran 12px under the bottom nav; body is display:block, so
        main's flex:1 does nothing and the column cannot simply inherit a
        height; and 100vh on a phone means the height WITHOUT the browser
        chrome, so the composer hides behind the URL bar.

        top:50px clears the sticky top bar, bottom:56px clears the fixed
        bottom nav, and the box between them is whatever is actually left --
        no viewport units, no assumptions about padding. */
    position: fixed;
    /*  Measured at runtime by commsChat.measureChrome, not hardcoded: these
        were 50px and 56px written by hand, and the top bar later grew to 54px
        when the layout switcher went into it, leaving the chat sitting under
        it. The fallbacks only apply before the first measurement. */
    top: var(--chrome-top, 50px);
    bottom: var(--chrome-bottom, 56px);
    left: 0;
    right: 0;
    margin-inline: auto;
    max-width: 700px;
    z-index: 5;
    background: var(--bg, #0e1014)}

/*  The chat page's only content is that fixed column, so the normal page flow
    is left with nothing but <main>'s padding. Collapse it, or the page keeps a
    stray scrollbar for 76px of empty space. */
.chat-page main.main { padding: 0}

.chat-hd {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 6px 12px;
    background: var(--bg2, #161920);
    border-bottom: 1px solid rgba(255,255,255,0.096)}

.chat-hd .who { font-weight: 700; font-size: 14.5px; line-height: 1.15}
.chat-hd .sub { font-size: 11px; color: var(--muted2, #aeb6c2); line-height: 1.2}

.chat-avatar {
    flex: 0 0 auto;
    width: 30px; height: 30px; border-radius: 50%;
    display: grid; place-items: center;
    background: rgba(180,83,9,.16);
    color: var(--accent, #60a5fa);
    font-weight: 700; font-size: 13px;
    border: 1px solid rgba(180,83,9,.35)}

/* ── transcript ──────────────────────────────────────────────────────── */

.chat-log {
    flex: 1 1 auto;
    overflow-y: auto;
    overflow-x: hidden;
    padding: 8px 12px 16px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    /* The faint texture WhatsApp uses to separate the transcript from the
       bubbles. A gradient, not an image: this runs offline in the field. */
    background:
        radial-gradient(circle at 20% 12%, rgba(15,23,42,.020), transparent 42%),
        radial-gradient(circle at 82% 68%, rgba(15,23,42,.016), transparent 46%),
        var(--bg, #0e1014)}

.chat-day {
    align-self: center;
    margin: 12px 0 8px;
    padding: 3px 12px;
    border-radius: 12px;
    background: rgba(255,255,255,0.084);
    color: var(--muted2, #aeb6c2);
    font-size: 11.5px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase}

.msg { display: flex; max-width: 100%}
.msg.me { justify-content: flex-end}
.msg.them { justify-content: flex-start}

.bubble {
    position: relative;
    max-width: 78%;
    padding: 7px 11px 6px;
    border-radius: 10px;
    font-size: 14.5px;
    line-height: 1.42;
    /* Long EPIC numbers and pasted links must wrap rather than widen the bubble
       past the viewport. */
    overflow-wrap: anywhere;
    box-shadow: 0 1px 1px rgba(0, 0, 0, .3)}

/* Mine: the app's own accent, tinted dark enough to keep white text legible. */
.msg.me .bubble {
    background: var(--accent-dim, rgba(96,165,250,.14));
    border: 1px solid rgba(96,165,250,.30);
    border-bottom-right-radius: 3px}

.msg.them .bubble {
    background: var(--bg2, #161920);
    border: 1px solid rgba(255,255,255,0.108);
    border-bottom-left-radius: 3px}

/* Who sent it. Only on the other side's bubbles -- labelling my own messages
   with my own name is noise, which is why no chat app does it. */
.bubble .from {
    display: block;
    font-size: 11.5px;
    font-weight: 700;
    color: var(--accent, #60a5fa);
    margin-bottom: 2px}

.bubble .txt { white-space: pre-wrap}

.bubble .at {
    float: right;
    margin: 6px 0 0 10px;
    font-size: 10.5px;
    color: var(--muted2, #aeb6c2);
    opacity: .8;
    user-select: none}

.bubble.gone .txt { font-style: italic; color: var(--muted2, #aeb6c2); opacity: .75}

/* Consecutive messages from the same side sit closer, so a burst reads as one
   turn rather than several. */
.msg.run { margin-top: -2px}

/* ── composer ────────────────────────────────────────────────────────── */

.chat-box {
    flex: 0 0 auto;
    display: flex;
    align-items: flex-end;
    gap: 8px;
    padding: 9px 10px;
    background: var(--bg2, #161920);
    border-top: 1px solid rgba(255,255,255,0.096)}

.chat-box textarea {
    flex: 1 1 auto;
    resize: none;
    /*  Height is set from JS as the content grows (commsChat.autoGrow). The
        min/max here are the floor and ceiling it works between. */
    height: 40px;
    min-height: 40px;
    max-height: 120px;
    overflow-y: hidden;
    padding: 10px 13px;
    border-radius: 20px;
    border: 1px solid rgba(255,255,255,0.168);
    background: rgba(255,255,255,0.06);
    color: var(--text, #f5f7fa);
    font-family: inherit;
    font-size: 14.5px;
    line-height: 1.35}

.chat-box textarea::placeholder { color: var(--muted2, #aeb6c2); opacity: .8}
.chat-box textarea:focus { outline: none; border-color: var(--accent, #60a5fa)}

.chat-send {
    flex: 0 0 auto;
    width: 40px; height: 40px;
    border: none; border-radius: 50%;
    background: var(--accent, #60a5fa);
    color: var(--on-accent, #0e1014);
    display: grid; place-items: center;
    cursor: pointer;
    transition: transform .12s, opacity .12s}

.chat-send:disabled { opacity: .4; cursor: default}
.chat-send:not(:disabled):active { transform: scale(.92)}
.chat-send svg { width: 19px; height: 19px}

.chat-empty {
    margin: auto;
    text-align: center;
    color: var(--muted2, #aeb6c2);
    font-size: 14px;
    padding: 28px 20px;
    max-width: 320px}

/* ── assembly inbox ──────────────────────────────────────────────────── */

.inbox-row {
    display: flex; align-items: center; gap: 12px;
    padding: 11px 14px;
    border-bottom: 1px solid rgba(255,255,255,0.084);
    text-decoration: none; color: inherit}

.inbox-row:hover { background: rgba(255,255,255,0.042)}
.inbox-main { flex: 1 1 auto; min-width: 0}
.inbox-top { display: flex; justify-content: space-between; gap: 10px; align-items: baseline}
.inbox-name { font-weight: 700; font-size: 14.5px}
.inbox-at { font-size: 11.5px; color: var(--muted2, #aeb6c2); flex: 0 0 auto}

.inbox-snip {
    font-size: 13px; color: var(--muted2, #aeb6c2);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    margin-top: 2px}

.unread-pill {
    flex: 0 0 auto;
    min-width: 20px; height: 20px; padding: 0 6px;
    border-radius: 10px;
    background: var(--green, #3fd37e);
    color: var(--on-accent, #0e1014);
    font-size: 11.5px; font-weight: 800;
    display: grid; place-items: center}

/* ── home buttons ────────────────────────────────────────────────────── */

.comms-row {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 10px;
    /*  Almost no top margin: this row used to sit at the foot of Home, where it
        needed 22px to clear the dashboard above it. It is now the first thing on
        the Voter tab, so that margin was just a band under the top bar. */
    margin: 0 0 8px}

.comms-btn {
    position: relative;
    display: flex; flex-direction: column; align-items: center; gap: 7px;
    padding: 15px 8px 13px;
    border-radius: 12px;
    background: var(--bg2, #161920);
    border: 1px solid rgba(255,255,255,0.12);
    text-decoration: none;
    color: var(--text, #f5f7fa);
    transition: border-color .15s, transform .12s}

.comms-btn:hover { border-color: var(--accent, #60a5fa)}
.comms-btn:active { transform: translateY(1px)}
.comms-btn svg { width: 24px; height: 24px; stroke: var(--accent, #60a5fa); fill: none}
.comms-btn .lbl { font-size: 12.5px; font-weight: 600; letter-spacing: .02em}

.comms-badge {
    position: absolute; top: 8px; right: 10px;
    min-width: 19px; height: 19px; padding: 0 5px;
    border-radius: 10px;
    background: var(--red, #ff5c77);
    color: var(--on-accent, #0e1014); font-size: 11px; font-weight: 800;
    display: grid; place-items: center}

/* ── announcements & events ──────────────────────────────────────────── */

.feed { max-width: 700px; margin: 0 auto; padding: 4px 0 12px}

.feed-card {
    background: var(--bg2, #161920);
    border: 1px solid rgba(255,255,255,0.108);
    border-left: 3px solid var(--accent, #60a5fa);
    border-radius: 0 10px 10px 0;
    padding: 13px 15px;
    margin: 0 0 11px}

.feed-card.unread { border-left-color: var(--green, #3fd37e)}
.feed-card.past { opacity: .62}
.feed-card.cancelled { border-left-color: var(--red, #ff5c77)}
.feed-card.cancelled .feed-title { text-decoration: line-through}

.feed-top { display: flex; justify-content: space-between; gap: 10px; align-items: baseline; flex-wrap: wrap}
.feed-title { font-size: 15.5px; font-weight: 700; margin: 0 0 3px}
.feed-body { font-size: 14px; line-height: 1.5; white-space: pre-wrap; margin: 6px 0 0}
.feed-meta { font-size: 11.5px; color: var(--muted2, #aeb6c2); margin-top: 8px}

.lvl {
    font-size: 10.5px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase;
    padding: 2px 7px; border-radius: 4px; white-space: nowrap}

.lvl-party { background: rgba(196,181,253,.16); color: var(--purple, #c4b5fd); border: 1px solid rgba(196,181,253,.4)}
.lvl-assembly { background: rgba(96,165,250,.14); color: var(--accent, #60a5fa); border: 1px solid rgba(96,165,250,.38)}

.evt-when { font-size: 13px; font-weight: 600; color: var(--green, #3fd37e); margin-top: 4px}
.evt-where { font-size: 13px; color: var(--muted2, #aeb6c2); margin-top: 2px}

@media (max-width: 400px) {
    .comms-row { gap: 7px}
    .comms-btn { padding: 13px 4px 11px}
    .comms-btn .lbl { font-size: 11.5px}
    .bubble { max-width: 85%}
}

/* ── Compose form (announcements, events) ──
   Self-contained cx-* classes rather than the vr-* ones the voter form uses.
   AssemblyWeb has no .vr-form rule at all -- only BoothWeb, SectorWeb and
   WarRoomWeb define it -- so the compose screens there rendered as native
   white boxes with inline labels on a dark page. Styling them here means the
   same form looks identical in all four apps and does not depend on whichever
   voter-form CSS an app happens to carry. */

.cx-card {
    background: var(--bg2, #161920);
    border: 1px solid rgba(255,255,255,0.12);
    border-left: 3px solid var(--green, #3fd37e);
    border-radius: 0 12px 12px 0;
    padding: 4px 0 0;
    margin: 0 0 16px;
    overflow: hidden}

.cx-card-hd {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    padding: 12px 16px 10px;
    border-bottom: 1px solid rgba(255,255,255,0.084)}

.cx-card-hd h3 {
    margin: 0; font-size: 14px; font-weight: 700;
    letter-spacing: .06em; text-transform: uppercase;
    color: var(--green, #3fd37e)}

.cx-form {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 14px;
    padding: 16px}

.cx-f { display: flex; flex-direction: column; gap: 6px; min-width: 0}
.cx-f.cx-wide { grid-column: 1 / -1}

.cx-f label {
    font-family: var(--mono, ui-monospace, monospace);
    font-size: 10px; font-weight: 600;
    letter-spacing: .12em; text-transform: uppercase;
    color: var(--muted2, #aeb6c2)}

/*  Every control in the form shares one look. width:100% with border-box is
    what stops a datetime-local -- which sizes itself to its own text on
    WebKit -- from running past the column and pushing the layout sideways. */
.cx-f input,
.cx-f textarea,
.cx-f select {
    width: 100%;
    box-sizing: border-box;
    padding: 10px 12px;
    border-radius: 8px;
    border: 1px solid rgba(255,255,255,0.168);
    background: rgba(255,255,255,0.06);
    color: var(--text, #f5f7fa);
    font-family: inherit;
    font-size: 14.5px;
    line-height: 1.35;

    /*  Tells the browser to draw its OWN widgets dark: the calendar picker,
        the clock, the spin buttons and the native dropdown list. Without it a
        date field renders as a white slab with a black glyph, which is exactly
        how the Starts and Ends fields looked. */
    color-scheme: dark}

.cx-f textarea { resize: vertical; min-height: 92px}

.cx-f input::placeholder,
.cx-f textarea::placeholder { color: var(--muted2, #aeb6c2); opacity: .65}

.cx-f input:focus,
.cx-f textarea:focus,
.cx-f select:focus {
    outline: none;
    border-color: var(--green, #3fd37e);
    box-shadow: 0 0 0 3px rgba(21,128,61,.16)}

/*  The calendar button inside a date input is a dark glyph on a dark field, so
    it is lightened rather than left as a smudge. */
.cx-f input[type="date"]::-webkit-calendar-picker-indicator,
.cx-f input[type="datetime-local"]::-webkit-calendar-picker-indicator {
    filter: invert(1) opacity(.65);
    cursor: pointer}
.cx-f input[type="date"]::-webkit-calendar-picker-indicator:hover,
.cx-f input[type="datetime-local"]::-webkit-calendar-picker-indicator:hover {
    filter: invert(1) opacity(1)}

/*  A checkbox is not a full-width control. */
.cx-f.cx-check { flex-direction: row; align-items: center; gap: 9px}
.cx-f.cx-check input { width: 19px; height: 19px; flex: 0 0 auto; padding: 0; accent-color: var(--green, #3fd37e)}
.cx-f.cx-check label { text-transform: none; letter-spacing: 0; font-size: 13.5px; color: var(--text, #f5f7fa); font-family: inherit}

.cx-hint { font-size: 11.5px; color: var(--muted2, #aeb6c2)}

.cx-actions {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    padding: 0 16px 16px}

.cx-btn {
    padding: 10px 22px;
    border: none; border-radius: 8px;
    background: var(--green, #3fd37e);
    color: var(--on-accent, #0e1014);
    font-family: inherit; font-size: 13.5px; font-weight: 700;
    letter-spacing: .04em;
    cursor: pointer;
    transition: filter .15s, transform .1s}
.cx-btn:hover:not(:disabled) { filter: brightness(1.1)}
.cx-btn:active:not(:disabled) { transform: translateY(1px)}
.cx-btn:disabled { opacity: .45; cursor: default}

.cx-btn-ghost {
    background: transparent;
    border: 1px solid rgba(255,255,255,0.216);
    color: var(--text, #f5f7fa)}
.cx-btn-ghost:hover { border-color: var(--green, #3fd37e)}

.cx-msg { font-size: 13px; color: var(--amber, #fbbf24)}

@media (max-width: 560px) {
    .cx-form { grid-template-columns: 1fr; gap: 12px; padding: 14px}
    .cx-actions { padding: 0 14px 14px}
}

/*  Four across when there is a Team button (BoothWeb). At 375px that is ~88px a
    tile, which still holds "Announcements" on two lines without truncating. */
.comms-row-4 { grid-template-columns: repeat(4, 1fr)}

/*  Four labels on one line each.

    "Booth Team" is the longest and was the only one wrapping, which left three
    tiles with a single-line label and one with two -- the row read as ragged
    even though the tiles themselves were equal height. nowrap plus a slightly
    tighter size keeps all four on one line, and the tiles stay the same height
    for the same reason.

    clamp() rather than a breakpoint: the tile width varies continuously with the
    viewport, so the label size should too, instead of stepping at one width and
    wrapping either side of it. */
.comms-row-4 .lbl {
    white-space: nowrap;
    font-size: clamp(9.5px, 2.6vw, 12.5px);
    letter-spacing: .01em}

@media (max-width: 400px) {
    .comms-row-4 { gap: 6px}
    .comms-row-4 .comms-btn { padding: 12px 3px 10px}
}

/*  While the on-screen keyboard is up the bottom nav is dead weight: it sits
    between the composer and the keyboard and eats the height that is left. */
body.kb-open .bottombar { display: none}

/*  Splitter under the button row: separates "reach the team" from "work the
    roll". Now shares the .split treatment defined in app.css rather than
    carrying its own copy -- one divider look across the whole app. */
.comms-split { margin: 16px 0 18px}

/*  Manual refresh in the chat header. Sits at the far right of the bar, away
    from the back arrow so a thumb reaching for one does not hit the other. */
.chat-refresh {
    margin-left: auto;
    flex: 0 0 auto;
    width: 32px; height: 32px;
    display: grid; place-items: center;
    border: 1px solid rgba(255,255,255,0.168);
    border-radius: 50%;
    background: rgba(255,255,255,0.06);
    color: var(--muted2, #aeb6c2);
    cursor: pointer;
    transition: color .15s, border-color .15s}

.chat-refresh svg { width: 16px; height: 16px}
.chat-refresh:hover:not(:disabled) { color: var(--accent); border-color: var(--accent)}
.chat-refresh:disabled { cursor: default; opacity: .8}

/*  Spins only while a fetch is in flight, so the motion means "working" rather
    than being decoration. */
.chat-refresh.spin svg { animation: chat-spin .7s linear infinite}
@keyframes chat-spin { to { transform: rotate(360deg)} }

@media (prefers-reduced-motion: reduce) {
    .chat-refresh.spin svg { animation: none}
    .chat-refresh.spin { color: var(--accent)}
}

/* Keyboard focus. The textarea rule below sets outline:none to drop the browser
   default, which also removes the only visible focus indicator a keyboard user
   gets. :focus-visible puts a real ring back for keyboard navigation without
   showing it on mouse clicks. 3:1 against the surface is the WCAG minimum for a
   non-text indicator; --accent on --bg2 is 5.9:1. */
.chat-box textarea:focus-visible,
.cx-f textarea:focus-visible,
.cx-f input:focus-visible,
.cx-f select:focus-visible,
.comms-btn:focus-visible,
.cx-btn:focus-visible,
.cx-btn-ghost:focus-visible {
    outline: 2px solid var(--accent, #60a5fa);
    outline-offset: 2px}

@media (prefers-reduced-motion: reduce) {
    .chat-box textarea,
    .comms-btn { transition: none}
}
