:root {
  /* Light theme. Panels are white and lift off a warm chat background, the way
     WhatsApp Web's light mode reads — borders alone look flat at this scale. */
  --bg:#eae6df; --panel:#ffffff; --panel2:#f4f2ee; --line:#eceae5; --line2:#d8d3c9;
  /* The gold from the Makkah Hotel & Towers mark. --acc-deep is for text, where
     the mid gold is too pale against white to read comfortably. */
  --acc:#a97d28; --acc-deep:#8a6620; --acc-soft:#f6efe0; --acc-ink:#ffffff;
  --txt:#1c1a16; --mut:#7a736a;
  --out:#f6efe0; --in:#ffffff; --err:#c62828;
  --warnbg:#fff8e1; --warnline:#f0c040; --warntxt:#7a5c00;
  --shadow:0 1px 2px rgba(11,20,26,.08); --shadow-lg:0 8px 28px rgba(11,20,26,.18);
}
* { box-sizing:border-box; font-family:system-ui,-apple-system,"Segoe UI",sans-serif; }
/* dvh, so a phone's address bar sliding in and out doesn't cut off the composer
   the way vh does. vh first for anything that doesn't know dvh. */
body { margin:0; background:var(--bg); color:var(--txt); height:100vh; height:100dvh; overflow:hidden; }
.hidden { display:none !important; }

/* --- login --- */
.center { min-height:100vh; display:grid; place-items:center; background:var(--panel2); }
.card { background:var(--panel); padding:32px; border-radius:12px; width:340px; box-shadow:var(--shadow-lg); }
.brand { text-align:center; margin-bottom:20px; }
.brand img { max-width:170px; max-height:130px; width:auto; height:auto; }
/* Stands in for the logo when public/logo.png hasn't been added. */
.wordmark { color:var(--acc-deep); font-size:17px; letter-spacing:1.2px;
            font-variant:small-caps; }
.card h2 { margin:0 0 12px; text-align:center; font-size:17px; color:var(--mut); font-weight:600; }
.card input { width:100%; padding:10px; margin:8px 0; border-radius:8px; border:1px solid var(--line2); background:var(--panel); color:var(--txt); }
.card input:focus { outline:none; border-color:var(--acc); }
.card button { width:100%; padding:11px; background:var(--acc); border:0; border-radius:8px; color:var(--acc-ink); font-weight:600; cursor:pointer; }
.err { color:var(--err); font-size:13px; min-height:18px; margin:8px 0 0; }

/* --- shell --- */
.app { display:grid; grid-template-columns:132px 340px 1fr; height:100vh; height:100dvh; }

/* Only ever shown on a phone, where the list and the thread share the screen. */
.back-btn { display:none; background:transparent; border:0; color:var(--mut); cursor:pointer;
            font-size:30px; line-height:1; padding:0 6px 4px; margin-left:-6px; flex:none; }

/* --- nav rail ---
   These used to share the sidebar header with the title inside 340px, which
   squeezed them until the labels stopped being readable. Plain words, one per
   row, wide enough that none of them wrap. */
.rail { background:var(--panel); border-right:1px solid var(--line2);
        display:flex; flex-direction:column; padding:12px 8px 14px; gap:2px; }
.rail-btn { width:100%; text-align:left; background:transparent; border:0; border-radius:7px;
            padding:9px 10px; font-size:13px; font-family:inherit; cursor:pointer;
            color:var(--mut); white-space:nowrap; }
.rail-btn:hover { background:var(--panel2); color:var(--txt); }
/* Starting a conversation is the one action here worth pulling the eye. */
.rail-btn.primary { color:var(--acc); font-weight:600; }
.rail-btn.primary:hover { background:var(--acc-soft); color:var(--acc); }
#logout:hover { color:var(--err); background:#fdecea; }
.rail-spacer { flex:1; }
.rail-live { padding:8px 10px; }

/* --- sidebar --- */
.sidebar { background:var(--panel); border-right:1px solid var(--line2); display:flex; flex-direction:column; min-height:0; }
.side-head { display:flex; justify-content:space-between; align-items:center; padding:15px 16px; border-bottom:1px solid var(--line); }
.side-head b { font-size:16px; }
.live-dot { width:8px; height:8px; border-radius:50%; flex:none; }
.live-dot.online  { background:var(--acc); box-shadow:0 0 0 3px rgba(169,125,40,.20); }
.live-dot.offline { background:var(--mut); opacity:.45; }
.ghost { background:transparent; border:1px solid var(--line2); color:var(--mut); padding:6px 11px; border-radius:6px; cursor:pointer; font-size:13px; }
.ghost:hover { color:var(--txt); border-color:var(--mut); background:var(--panel2); }
.side-search { padding:10px 12px; }
.side-search input { width:100%; padding:8px 12px; border-radius:8px; border:1px solid var(--line2); background:var(--panel2); color:var(--txt); font-size:14px; }
.side-search input:focus { outline:none; border-color:var(--acc); background:var(--panel); }

.conv-list { list-style:none; margin:0; padding:0; overflow-y:auto; flex:1; min-height:0; }
.conv { display:flex; gap:12px; padding:12px 16px; cursor:pointer; border-bottom:1px solid var(--line); }
.conv:hover { background:var(--panel2); }
.conv.active { background:var(--acc-soft); }
.avatar { width:40px; height:40px; border-radius:50%; background:var(--panel2); color:var(--mut);
          display:grid; place-items:center; font-weight:600; font-size:15px; flex:none; }
.conv-main { flex:1; min-width:0; }
.conv-top { display:flex; justify-content:space-between; gap:8px; align-items:baseline; }
.conv-name { font-weight:600; font-size:14.5px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.conv-time { color:var(--mut); font-size:11.5px; flex:none; }
.conv-preview { color:var(--mut); font-size:13px; margin-top:2px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.conv-bottom { display:flex; justify-content:space-between; gap:8px; align-items:center; }
/* without min-width:0 the preview refuses to shrink and shoves the badge out of the row */
.conv-bottom .conv-preview { flex:1; min-width:0; }
.conv.unread .conv-name, .conv.unread .conv-preview { color:var(--txt); font-weight:600; }
.badge { background:var(--acc); color:var(--acc-ink); font-size:11px; font-weight:700; line-height:1;
         min-width:19px; height:19px; padding:0 6px; border-radius:10px; display:grid; place-items:center; flex:none; }
/* Someone else already has this thread open — the collision cue in the list. */
.seat { color:var(--warntxt); font-size:11.5px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; flex:none; max-width:60%; }
.empty-note { color:var(--mut); font-size:13px; padding:24px 16px; text-align:center; }

/* On a narrower window the conversation list gives up width first — it tolerates
   it better than the rail, which becomes unreadable, or the thread itself. */
@media (max-width:1000px) { .app { grid-template-columns:132px 264px 1fr; } }

/* --- thread --- */
.thread-pane { display:flex; flex-direction:column; min-height:0; min-width:0; background:var(--bg); }
.placeholder { flex:1; display:grid; place-items:center; color:var(--mut); font-size:14px; }
.thread-head { display:flex; align-items:center; gap:12px; padding:12px 20px; background:var(--panel); border-bottom:1px solid var(--line2); }
.who { display:flex; flex-direction:column; min-width:0; }
.who b { font-size:15px; }
.who span { color:var(--mut); font-size:12.5px; }
.presence { margin-left:auto; color:var(--warntxt); font-size:12.5px; background:var(--warnbg);
            border:1px solid var(--warnline); padding:5px 11px; border-radius:14px; }
/* Pushed right on its own; sits beside the presence chip when that is showing,
   rather than splitting the free space with it. */
.thread-head .btn-sm { margin-left:auto; flex:none; }
.thread-head .presence:not(.hidden) + .btn-sm { margin-left:12px; }

.messages { flex:1; overflow-y:auto; padding:20px 24px; display:flex; flex-direction:column; gap:6px; min-height:0; }
.msg { max-width:min(68%,560px); padding:7px 11px 5px; border-radius:9px; font-size:14.5px;
       line-height:1.4; word-wrap:break-word; box-shadow:var(--shadow); }
.msg.in  { background:var(--in);  align-self:flex-start; border-top-left-radius:2px; }
.msg.out { background:var(--out); align-self:flex-end;  border-top-right-radius:2px; }
.msg-body { white-space:pre-wrap; }
/* A named message kind ("Sticker", "Voice message") rather than the guest's own
   words — set apart so it doesn't read as something they typed. */
.msg-body.muted { color:var(--mut); font-style:italic; font-size:13.5px; }
.meta { display:flex; gap:5px; justify-content:flex-end; align-items:center; margin-top:3px; font-size:11px; color:var(--mut); }
.tick.read { color:#53bdeb; }
.tick.failed { color:var(--err); font-weight:600; }
.day { align-self:center; background:var(--panel); color:var(--mut); font-size:11.5px; box-shadow:var(--shadow);
       padding:4px 12px; border-radius:12px; margin:10px 0 4px; }

/* A removed message leaves a marker rather than closing the gap, so the thread
   still reads as a record of what happened. */
.msg.gone { background:var(--panel2); box-shadow:none; border:1px dashed var(--line2); }
.msg-gone { color:var(--mut); font-size:13.5px; font-style:italic; }

/* Kept out of the way until the pointer is on the message it belongs to. */
.msg-del { background:none; border:0; padding:0 0 0 4px; cursor:pointer; color:var(--mut);
           font-size:11px; font-family:inherit; opacity:0; transition:opacity .12s; }
.msg:hover .msg-del { opacity:1; }
.msg-del:hover { color:var(--err); text-decoration:underline; }

/* --- media in the thread --- */
.msg-media { display:block; margin:-2px 0 4px; border-radius:6px; overflow:hidden; background:var(--panel2); }
.msg-media img, .msg-media video { display:block; width:100%; max-width:340px; max-height:400px;
                                   object-fit:cover; border-radius:6px; cursor:pointer; }
.msg-media video { object-fit:contain; background:#000; cursor:default; }
/* Anything we can't show inline (documents, audio) still has to be reachable. */
.msg-file { display:inline-flex; align-items:center; gap:8px; padding:8px 12px; margin:2px 0 4px;
            background:var(--panel2); border-radius:8px; color:var(--txt); text-decoration:none; font-size:13.5px; }
.msg-file:hover { background:var(--line); }
.media-failed { padding:14px; color:var(--mut); font-size:12.5px; text-align:center; }

/* Full-size viewer for an image clicked in the thread. */
.lightbox { position:fixed; inset:0; background:rgba(11,20,26,.9); display:grid; place-items:center; z-index:20; padding:32px; }
.lightbox img { max-width:100%; max-height:100%; border-radius:6px; }

/* --- 24h window notice --- */
.warn { background:var(--warnbg); border-top:1px solid var(--warnline); color:var(--warntxt);
        padding:10px 20px; font-size:13px; line-height:1.45; display:flex; align-items:center; gap:12px; }
.warn span { flex:1; }
.warn button { flex:none; background:var(--warntxt); color:#fff; border:0; padding:6px 12px;
               border-radius:6px; font-size:12.5px; cursor:pointer; font-weight:600; }

/* --- modals --- */
.modal { position:fixed; inset:0; background:rgba(11,20,26,.45); display:grid; place-items:center; z-index:10; padding:20px; }
.modal-card { background:var(--panel); border-radius:12px; box-shadow:var(--shadow-lg);
              padding:24px; width:420px; max-width:100%; max-height:90vh; overflow-y:auto; }
.modal-card.wide { width:600px; }
/* Opens on top of whichever screen asked the question. */
#confirmModal { z-index:15; }
.modal-card h3 { margin:0 0 14px; }
.modal-card label { display:block; font-size:12.5px; color:var(--mut); margin:12px 0 5px; }
.modal-card input, .modal-card select, .modal-card textarea {
  width:100%; padding:9px 11px; border-radius:8px; border:1px solid var(--line2);
  background:var(--panel); color:var(--txt); font-size:14px; font-family:inherit; }
.modal-card input:focus, .modal-card select:focus, .modal-card textarea:focus { outline:none; border-color:var(--acc); }
.modal-card textarea { resize:vertical; }
#newTemplateManual { display:grid; grid-template-columns:2fr 1fr; gap:8px; }
.hint { color:var(--mut); font-size:12px; line-height:1.5; margin:6px 0 0; }
.modal-actions { display:flex; gap:10px; justify-content:flex-end; margin-top:18px; }
.modal-actions button { width:auto; padding:9px 20px; background:var(--acc); border:0;
                        border-radius:8px; color:var(--acc-ink); font-weight:600; cursor:pointer; }
.modal-actions .ghost { background:transparent; border:1px solid var(--line2); color:var(--mut); font-weight:400; }
.modal-actions button:disabled { opacity:.5; cursor:not-allowed; }

/* Text vs template, so neither one is buried behind the other. */
.tabs { display:flex; gap:4px; background:var(--panel2); padding:4px; border-radius:8px; margin:14px 0 4px; }
.tab { flex:1; padding:7px 10px; border:0; background:transparent; color:var(--mut);
       border-radius:6px; font-size:13.5px; cursor:pointer; font-family:inherit; }
.tab.on { background:var(--panel); color:var(--txt); font-weight:600; box-shadow:var(--shadow); }

/* --- user management --- */
.user-row { display:flex; align-items:center; gap:10px; padding:11px 0; border-bottom:1px solid var(--line); }
.user-main { flex:1; min-width:0; }
.user-email { font-size:14px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.user-sub { color:var(--mut); font-size:12px; margin-top:2px; }
.pill { font-size:11px; font-weight:700; padding:2px 8px; border-radius:10px; text-transform:uppercase; letter-spacing:.3px; }
.pill.admin { background:var(--acc-soft); color:var(--acc-deep); }
.pill.agent { background:var(--panel2); color:var(--mut); }
.pill.off   { background:#fdecea; color:var(--err); }
.row-actions { display:flex; gap:6px; flex:none; }
.btn-sm { background:transparent; border:1px solid var(--line2); color:var(--mut); font-size:12px;
          padding:4px 9px; border-radius:6px; cursor:pointer; font-family:inherit; }
.btn-sm:hover { color:var(--txt); border-color:var(--mut); background:var(--panel2); }
.btn-sm.danger:hover { color:var(--err); border-color:var(--err); background:#fdecea; }
.section-head { display:flex; justify-content:space-between; align-items:baseline; margin:22px 0 2px; }
.section-head h4 { margin:0; font-size:13px; text-transform:uppercase; letter-spacing:.4px; color:var(--mut); }
.new-user-grid { display:grid; grid-template-columns:1fr 1fr; gap:8px; }
.ok { color:#00674f; font-size:13px; min-height:18px; margin:8px 0 0; }

/* The SMTP conversation, shown after a test so the failing step is visible
   without going to the server log. */
.smtp-trace { background:#0b141a; color:#c9d6dc; border-radius:8px; padding:10px 12px; margin-top:10px;
              font-family:ui-monospace,Menlo,Consolas,monospace; font-size:11.5px; line-height:1.6;
              max-height:200px; overflow:auto; white-space:pre-wrap; word-break:break-all; }

/* --- two-step verification --- */
.qr-wrap { display:grid; place-items:center; padding:14px; background:#fff;
           border:1px solid var(--line2); border-radius:10px; margin:10px 0; }
.qr-wrap img { width:190px; height:190px; }
/* Selectable, because typing it by hand is the fallback when scanning fails. */
.secret { display:inline-block; margin-top:4px; padding:5px 9px; background:var(--panel2);
          border-radius:6px; font-family:ui-monospace,Menlo,Consolas,monospace;
          font-size:13px; letter-spacing:1.5px; user-select:all; }

/* --- ready-made picker --- */
#cannedList { margin-top:10px; max-height:46vh; overflow-y:auto; }
/* Shorter than the composer's copy — this list shares the dialog with a number
   field, the tabs and the send buttons. */
#newCannedList { margin-top:10px; max-height:30vh; overflow-y:auto; }
.canned { border:1px solid var(--line); border-radius:9px; padding:11px 13px; margin-bottom:8px; cursor:pointer; }
.canned:hover { border-color:var(--mut); background:var(--panel2); }
.canned.on { border-color:var(--acc); background:var(--acc-soft); }
.canned-top { display:flex; justify-content:space-between; gap:10px; align-items:baseline; }
.canned-name { font-weight:600; font-size:13.5px; }
.canned-kind { color:var(--mut); font-size:11px; flex:none; }
.canned-body { color:var(--mut); font-size:12.5px; margin-top:4px; white-space:pre-wrap;
               display:-webkit-box; -webkit-line-clamp:3; -webkit-box-orient:vertical; overflow:hidden; }
.canned-opts { display:flex; flex-wrap:wrap; gap:5px; margin-top:7px; }
.canned-opt { font-size:11px; border:1px solid var(--line2); background:var(--panel);
              color:var(--mut); border-radius:11px; padding:2px 9px; }

/* --- quick-reply buttons --- */
.bi-row { display:grid; grid-template-columns:1fr 1fr auto; gap:8px; align-items:center; margin-bottom:8px; }
.bi-row .btn-sm { padding:8px 10px; }
/* Lists carry a description as well, so they get their own column layout. */
.li-row { display:grid; grid-template-columns:1.1fr 1fr 1.4fr auto; gap:8px; align-items:center; margin-bottom:8px; }
.li-row .btn-sm { padding:8px 10px; }
/* The menu row as the guest sees it: one tappable line that opens the options. */
.msg-list { margin-top:6px; border-top:1px solid rgba(11,20,26,.09); padding-top:6px;
            text-align:center; font-size:13px; color:var(--acc-deep); }
.msg-list-rows { margin-top:4px; text-align:left; color:var(--mut); font-size:12px; }
.msg-list-rows div { padding:1px 0; }
/* Buttons as the guest will see them, under the message they hang off. */
.msg-buttons { display:flex; flex-direction:column; gap:3px; margin-top:6px;
               border-top:1px solid rgba(11,20,26,.09); padding-top:6px; }
.msg-buttons span { text-align:center; font-size:13px; color:var(--acc-deep); padding:4px; }

/* --- template preview --- */
.tpl-preview { background:var(--out); border-radius:9px; padding:10px 12px; margin-top:10px;
               font-size:13.5px; line-height:1.45; white-space:pre-wrap; box-shadow:var(--shadow); }
.tpl-preview .tpl-meta { color:var(--mut); font-size:11.5px; margin-top:6px; white-space:normal; }
.tpl-buttons { display:flex; flex-wrap:wrap; gap:6px; margin-top:8px; }
.tpl-btn { font-size:11.5px; border:1px solid var(--line2); background:var(--panel);
           color:var(--mut); border-radius:12px; padding:2px 10px; }
.tpl-warn { color:var(--warntxt); background:var(--warnbg); border:1px solid var(--warnline);
            border-radius:7px; padding:7px 10px; font-size:12px; margin-top:8px; }
.tpl-var { margin-top:8px; }
.tpl-var label { display:block; font-size:12px; color:var(--mut); margin-bottom:4px; }

/* --- import report --- */
.import-report { background:var(--panel2); border-radius:8px; padding:12px 14px; margin-top:10px; font-size:12.5px; }
.import-report h5 { margin:0 0 6px; font-size:12px; text-transform:uppercase; letter-spacing:.4px; color:var(--mut); }
.import-report ul { margin:0 0 10px; padding-left:18px; }
.import-report li { padding:1px 0; line-height:1.45; }
.import-report .bad  { color:var(--err); }
.import-report .warn-line { color:var(--warntxt); }
.import-report .sum { font-weight:600; margin-bottom:8px; }

/* --- inline rule editor --- */
.rule-edit { background:var(--panel2); border-radius:8px; padding:14px 16px; margin:8px 0; }
.rule-edit label { display:block; font-size:12px; color:var(--mut); margin:10px 0 4px; }
.rule-edit label:first-child { margin-top:0; }
.rule-edit input, .rule-edit select, .rule-edit textarea {
  width:100%; padding:8px 10px; border-radius:7px; border:1px solid var(--line2);
  background:var(--panel); color:var(--txt); font-size:13.5px; font-family:inherit; }
.rule-edit input:focus, .rule-edit select:focus, .rule-edit textarea:focus { outline:none; border-color:var(--acc); }
.rule-edit textarea { resize:vertical; }
.rule-edit-actions { display:flex; gap:8px; justify-content:flex-end; margin-top:12px; }
.rule-edit-actions button { width:auto; padding:7px 16px; background:var(--acc); border:0;
                            border-radius:7px; color:var(--acc-ink); font-size:13px; font-weight:600;
                            cursor:pointer; font-family:inherit; }
.rule-edit-actions .ghost { background:transparent; border:1px solid var(--line2); color:var(--mut); font-weight:400; }

/* --- auto-reply rules --- */
.rule-row { display:flex; gap:12px; align-items:flex-start; padding:11px 0; border-bottom:1px solid var(--line); }
.rule-main { flex:1; min-width:0; }
.rule-when { font-size:13px; font-weight:600; }
.rule-when code { background:var(--panel2); padding:1px 6px; border-radius:4px; font-size:12px; font-weight:400; }
.rule-reply { color:var(--mut); font-size:12.5px; margin-top:3px; white-space:pre-wrap;
              display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; }
.rule-meta { color:var(--mut); font-size:11px; margin-top:3px; }
.rule-row.off .rule-when, .rule-row.off .rule-reply { opacity:.5; }

/* A tapped button is not the same thing as a guest typing those words, and an
   agent reading back through a thread needs to be able to tell them apart. */
.msg-tap { display:inline-block; font-size:11px; color:var(--mut); border:1px solid var(--line2);
           border-radius:10px; padding:1px 8px; margin-bottom:4px; }
/* What the tap was answering, so a bare "Yes" can be read in context. */
.msg-quote { border-left:3px solid var(--line2); padding:2px 0 2px 8px; margin-bottom:4px;
             color:var(--mut); font-size:12.5px; max-height:34px; overflow:hidden; }
.auto-tag { color:var(--mut); font-size:10.5px; border:1px solid var(--line2); border-radius:8px; padding:0 5px; }
/* The colleague who sent it. Sits before the time and stays quieter than the
   message — it is for the team, and reads as a signature rather than content. */
.sent-by { color:var(--acc-deep); font-size:10.5px; font-weight:600; margin-right:1px; }

/* --- business number --- */
#phoneStatus { background:var(--panel2); border-radius:8px; padding:14px 16px; margin-top:10px; }
.ph-line { display:flex; justify-content:space-between; gap:12px; padding:4px 0; font-size:13px; }
.ph-line span:first-child { color:var(--mut); }
.ph-line b { font-weight:600; text-align:right; word-break:break-word; }
.ph-num { font-size:17px; font-weight:600; margin-bottom:6px; }
.ph-others { margin-top:10px; padding-top:10px; border-top:1px solid var(--line2); }

/* --- activity log --- */
#auditList { margin-top:6px; max-height:46vh; overflow-y:auto; }
.audit-row { display:flex; gap:12px; padding:9px 0; border-bottom:1px solid var(--line); font-size:13px; align-items:baseline; }
.audit-when { color:var(--mut); font-size:11.5px; flex:none; width:112px; }
.audit-what { flex:1; min-width:0; }
.audit-what b { font-weight:600; }
.audit-actor { color:var(--mut); }
.audit-detail { color:var(--mut); font-size:11.5px; margin-top:2px; word-break:break-word; }
.audit-ip { color:var(--mut); font-size:11px; flex:none; }
/* Failures are the rows worth spotting in a wall of routine activity. */
.audit-row.bad b { color:var(--err); }

/* --- composer --- */
.composer { display:flex; gap:10px; align-items:flex-end; padding:12px 20px; background:var(--panel); border-top:1px solid var(--line2); }
.composer textarea { flex:1; resize:none; max-height:140px; padding:10px 12px; border-radius:8px;
                     border:1px solid var(--line2); background:var(--panel); color:var(--txt);
                     font-size:14.5px; line-height:1.4; font-family:inherit; }
.composer textarea:focus { outline:none; border-color:var(--acc); }
.composer button { padding:10px 22px; background:var(--acc); border:0; border-radius:8px;
                   color:var(--acc-ink); font-weight:600; cursor:pointer; flex:none; }
.composer button:disabled { opacity:.5; cursor:not-allowed; }
.attach { flex:none; padding:10px 14px; background:transparent; border:1px solid var(--line2);
          border-radius:8px; color:var(--mut); font-size:13.5px; font-family:inherit; cursor:pointer; }
.attach:hover { color:var(--txt); border-color:var(--mut); background:var(--panel2); }

/* Picked file sits above the composer until it's sent or cleared. */
.attach-bar { display:flex; align-items:center; gap:12px; padding:10px 20px; background:var(--panel2); border-top:1px solid var(--line); }
.attach-bar img, .attach-bar video { width:44px; height:44px; object-fit:cover; border-radius:6px; flex:none; background:#000; }
.attach-info { flex:1; min-width:0; font-size:13px; }
.attach-info b { display:block; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; font-weight:600; }
.attach-info span { color:var(--mut); font-size:12px; }
.attach-bar .btn-sm { flex:none; }

/* ============================================================
   Phones and small tablets.

   A three-column shell cannot work here, so the list and the thread take turns
   over the full width — the way every messaging app does it — with the rail
   flattened into a strip along the top. Which one is showing is driven by
   .thread-open on <body>, set when a conversation is opened.
   ============================================================ */
@media (max-width: 768px) {
  .app { display:flex; flex-direction:column; }

  /* The rail lies down and scrolls sideways rather than stealing a third of a
     narrow screen. */
  .rail { flex-direction:row; align-items:center; width:100%; flex:none;
          border-right:0; border-bottom:1px solid var(--line2);
          overflow-x:auto; -webkit-overflow-scrolling:touch;
          padding:8px 10px; gap:6px; }
  .rail-btn { width:auto; flex:none; padding:8px 12px; border:1px solid var(--line2); }
  .rail-spacer { display:none; }
  .rail-live { padding:0 6px; display:flex; align-items:center; flex:none; }

  .sidebar { width:auto; flex:1; min-height:0; border-right:0; }
  .thread-pane { display:none; }

  /* One at a time. */
  body.thread-open .sidebar { display:none; }
  body.thread-open .thread-pane { display:flex; flex:1; min-height:0; }

  .back-btn { display:block; }

  .thread-head { flex-wrap:wrap; padding:10px 12px; gap:10px; }
  .thread-head .btn-sm { font-size:11.5px; padding:4px 8px; }
  .presence { margin-left:auto; font-size:11.5px; padding:4px 8px; }

  .messages { padding:14px 12px; }
  .msg { max-width:86%; }

  /* Text on its own line above the buttons — three controls and a field do not
     fit across a phone. */
  .composer { flex-wrap:wrap; padding:8px 10px; gap:6px; }
  .composer textarea { order:-1; flex:1 1 100%; }
  .composer button, .attach { flex:none; }
  .composer button[type="submit"] { margin-left:auto; }

  /* 16px stops iOS zooming the page in the moment a field is focused, which
     leaves the layout scrolled sideways with no way back. */
  input, select, textarea,
  .modal-card input, .modal-card select, .modal-card textarea,
  .composer textarea, .side-search input { font-size:16px; }

  /* Dialogs take the whole screen; a centred card with margins wastes most of
     a phone and puts the buttons off the bottom. */
  .modal { padding:0; place-items:stretch; }
  .modal-card, .modal-card.wide { width:100%; max-width:100%;
                                  height:100vh; height:100dvh;
                                  max-height:100vh; max-height:100dvh; border-radius:0; }
  .modal-actions { position:sticky; bottom:0; background:var(--panel);
                   padding:12px 0 4px; margin-top:14px; }

  /* Side-by-side pairs stack. */
  .new-user-grid, #newTemplateManual, .bi-row, .li-row { grid-template-columns:1fr; }
  .user-row, .rule-row, .audit-row { flex-wrap:wrap; }
  .row-actions { width:100%; flex-wrap:wrap; }
  .audit-when { width:auto; }

  .qr-wrap img { width:170px; height:170px; }
  #cannedList, #auditList, #userList { max-height:none; }
}

/* Very narrow: the rail labels are what give way, not the buttons. */
@media (max-width: 400px) {
  .rail-btn { padding:8px 9px; font-size:12px; }
  .msg { max-width:92%; }
}
