/* kalm-web
 *
 * Reference: an operator's switchboard console. Deep slate panel,
 * silkscreened labels, amber signal lamps. Numbers are set in tabular
 * monospace because on this page a phone number is data, not prose.
 */

:root {
    --panel-deep:   #0e1319;
    --panel:        #151c25;
    --panel-raised: #1c2530;
    --line:         #27313e;
    --line-bright:  #35424f;

    --ink:          #d3dae3;
    --ink-dim:      #8b97a6;
    --ink-faint:    #5d6976;

    --lamp:         #e8a33d;
    --lamp-glow:    rgba(232, 163, 61, 0.28);
    --lamp-dead:    #2b3441;

    --ok:           #64ac86;
    --warn:         #d4874f;
    --bad:          #c9604f;

    --radius: 3px;
    /* Chat bubbles only. 3px reads wrong on a message bubble - the
       iMessage idiom is what makes a thread scan as a conversation - so
       geometry is section-specific while the palette stays shared. */
    --radius-bubble: 16px;
    --radius-bubble-tail: 5px;
    --panel-font: ui-sans-serif, -apple-system, "Segoe UI", Roboto,
                  "Helvetica Neue", Arial, sans-serif;
    --data-font: ui-monospace, "SF Mono", "Cascadia Mono", Menlo,
                 "DejaVu Sans Mono", monospace;
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    /* iOS standalone: status bar overlays the page under
       black-translucent, and the home indicator eats the bottom. */
    padding: env(safe-area-inset-top) env(safe-area-inset-right)
             env(safe-area-inset-bottom) env(safe-area-inset-left);
    background:
        radial-gradient(ellipse 120% 60% at 50% 0%,
                        #18212c 0%, var(--panel-deep) 62%) no-repeat;
    background-color: var(--panel-deep);
    min-height: 100vh;
    color: var(--ink);
    font-family: var(--panel-font);
    font-size: 15px;
    line-height: 1.55;
}

a { color: var(--lamp); text-decoration: none; }
a:hover { text-decoration: underline; }

:focus-visible {
    outline: 2px solid var(--lamp);
    outline-offset: 2px;
}

/* --- Silkscreen labels ------------------------------------------------- */

.label {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.17em;
    text-transform: uppercase;
    color: var(--ink-faint);
}

.num {
    font-family: var(--data-font);
    font-variant-numeric: tabular-nums;
    font-size: 0.94em;
    letter-spacing: -0.01em;
}

/* --- Frame -------------------------------------------------------------- */

.shell {
    max-width: 1060px;
    margin: 0 auto;
    padding: 0 20px 72px;
}

header.masthead {
    display: flex;
    position: sticky;
    top: 0;
    z-index: 5;
    /* The background has to reach past .shell's 20px side padding, or it
       stops short of the viewport edge and content scrolls visibly
       through the gap. Negative margin widens it, matching padding pulls
       the contents back into line with the panels below. */
    background: var(--panel-deep);
    margin: 0 -20px 28px;
    padding: 26px 20px 20px;
    align-items: baseline;
    gap: 18px;
    flex-wrap: wrap;
    border-bottom: 1px solid var(--line);
}

.wordmark {
    font-size: 19px;
    font-weight: 640;
    letter-spacing: -0.015em;
    color: var(--ink);
}

.wordmark span {
    color: var(--lamp);
    font-family: var(--data-font);
    font-size: 15px;
    font-weight: 500;
    margin-left: 2px;
}

nav.tabs {
    display: flex;
    gap: 22px;
    margin-left: auto;
    align-items: baseline;
}

nav.tabs a {
    color: var(--ink-dim);
    font-size: 13px;
    font-weight: 520;
    letter-spacing: 0.02em;
    padding-bottom: 3px;
    border-bottom: 2px solid transparent;
}

nav.tabs a:hover { color: var(--ink); text-decoration: none; }

nav.tabs a.on {
    color: var(--ink);
    border-bottom-color: var(--lamp);
}

nav.tabs form { display: inline; }

.linkbtn {
    background: none;
    border: 0;
    padding: 0;
    color: var(--ink-faint);
    font: inherit;
    font-size: 13px;
    cursor: pointer;
}
.linkbtn:hover { color: var(--ink); }

/* --- Panels ------------------------------------------------------------- */

.panel {
    background: var(--panel);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    margin-bottom: 22px;
}

.panel > h2 {
    margin: 0;
    padding: 13px 18px;
    font-size: 11px;
    font-weight: 640;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--ink-dim);
    border-bottom: 1px solid var(--line);
    display: flex;
    align-items: center;
    gap: 12px;
}

.panel > h2 .aside {
    margin-left: auto;
    letter-spacing: 0.02em;
    text-transform: none;
    font-weight: 460;
    font-size: 12px;
    color: var(--ink-faint);
}

.panel-body { padding: 18px; }

/* --- Lamp field: the DID forwarding selector ---------------------------- */

.field {
    border-bottom: 1px solid var(--line);
    padding: 20px 18px;
}
.field:last-child { border-bottom: 0; }

.field-head {
    display: flex;
    align-items: baseline;
    gap: 14px;
    flex-wrap: wrap;
    margin-bottom: 16px;
}

.field-did {
    font-family: var(--data-font);
    font-size: 17px;
    font-weight: 500;
    color: var(--ink);
    letter-spacing: -0.02em;
}

.field-ext {
    font-size: 12px;
    color: var(--ink-faint);
}

.lamps {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 8px;
    margin-bottom: 16px;
}

.lamp {
    position: relative;
    display: block;
    cursor: pointer;
}

.lamp input {
    position: absolute;
    opacity: 0;
    width: 1px;
    height: 1px;
}

.lamp-face {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    background: var(--panel-raised);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    transition: border-color 120ms ease, background 120ms ease;
}

.lamp-face .bulb {
    flex: none;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--lamp-dead);
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.45);
    transition: background 140ms ease, box-shadow 140ms ease;
}

.lamp-face .text {
    font-size: 13px;
    line-height: 1.3;
    color: var(--ink-dim);
}

.lamp:hover .lamp-face { border-color: var(--line-bright); }

.lamp input:checked + .lamp-face {
    border-color: rgba(232, 163, 61, 0.5);
    background: #1f2733;
}

.lamp input:checked + .lamp-face .bulb {
    background: var(--lamp);
    box-shadow: 0 0 9px 2px var(--lamp-glow),
                inset 0 0 0 1px rgba(255, 255, 255, 0.25);
}

.lamp input:checked + .lamp-face .text { color: var(--ink); }

.lamp input:focus-visible + .lamp-face {
    outline: 2px solid var(--lamp);
    outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
    .lamp-face, .lamp-face .bulb { transition: none; }
}

/* --- Timers row --------------------------------------------------------- */

.timers {
    display: flex;
    gap: 22px;
    align-items: flex-end;
    flex-wrap: wrap;
}

.timer label { display: block; margin-bottom: 5px; }

.timer input {
    width: 74px;
    padding: 7px 9px;
    background: var(--panel-deep);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    color: var(--ink);
    font-family: var(--data-font);
    font-size: 14px;
}

.timer .hint {
    font-size: 11px;
    color: var(--ink-faint);
    margin-top: 5px;
    max-width: 30ch;
    line-height: 1.4;
}

.timer .hint.alert { color: var(--warn); }

/* --- Buttons ------------------------------------------------------------ */

.btn {
    padding: 8px 16px;
    background: var(--panel-raised);
    border: 1px solid var(--line-bright);
    border-radius: var(--radius);
    color: var(--ink);
    font: inherit;
    font-size: 13px;
    font-weight: 540;
    cursor: pointer;
}
.btn:hover { border-color: var(--lamp); color: #fff; }

.btn-primary {
    background: rgba(232, 163, 61, 0.13);
    border-color: rgba(232, 163, 61, 0.45);
    color: var(--lamp);
}
.btn-primary:hover { background: rgba(232, 163, 61, 0.2); color: var(--lamp); }

.btn-tiny {
    padding: 3px 9px;
    font-size: 11px;
    letter-spacing: 0.03em;
}

.btn-danger { color: var(--bad); border-color: rgba(201, 96, 79, 0.4); }
.btn-danger:hover { border-color: var(--bad); color: var(--bad); }

/* --- Tables ------------------------------------------------------------- */

table {
    width: 100%;
    border-collapse: collapse;
    font-size: 14px;
}

thead th {
    text-align: left;
    padding: 9px 18px;
    font-size: 10px;
    font-weight: 640;
    letter-spacing: 0.15em;
    text-transform: uppercase;
    color: var(--ink-faint);
    border-bottom: 1px solid var(--line);
    white-space: nowrap;
}

tbody td {
    padding: 11px 18px;
    border-bottom: 1px solid rgba(39, 49, 62, 0.55);
    vertical-align: middle;
}

tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover { background: rgba(28, 37, 48, 0.6); }

td.right, th.right { text-align: right; }
td.shrink { width: 1%; white-space: nowrap; }

.rowact { opacity: 0; transition: opacity 110ms ease; }
tr:hover .rowact, .rowact:focus-within { opacity: 1; }
@media (hover: none) { .rowact { opacity: 1; } }

/* --- Direction and status marks ----------------------------------------- */

.dir {
    font-family: var(--data-font);
    font-size: 12px;
    color: var(--ink-faint);
    letter-spacing: 0.04em;
}
.dir.in  { color: var(--ok); }
.dir.out { color: var(--ink-dim); }

/* Outcome, not raw disposition: a voicemail is ANSWERED to Asterisk but
   is not a call you took, so it gets its own colour rather than the green
   that would imply you spoke to someone. */
.disp { font-size: 12px; color: var(--ink-dim); }
/* A voicemail result links through to the message. Styled as the label
   already was, so the row reads the same until you hover it. */
a.disp { text-decoration: none; }
a.disp:hover { text-decoration: underline; }
.disp.answered  { color: var(--ok); }
.disp.voicemail { color: var(--lamp); }
.disp.mailbox   { color: var(--ink-dim); }
.disp.blocked   { color: var(--ink-faint); text-decoration: line-through; }
.disp.no-answer { color: var(--ink-faint); }
.disp.busy, .disp.failed { color: var(--bad); }
.disp.other     { color: var(--ink-dim); }

/* A voicemail result links through to the message. Styled exactly like
   the plain label so the column does not turn into a row of blue links;
   the underline on hover is the only tell. */
a.disp { text-decoration: none; cursor: pointer; }
a.disp:hover { text-decoration: underline; }

/* Ends of the pager stay in place when unavailable, so the control does
   not shift under the cursor as you page through. */
.pager-off { color: var(--line-bright); }
.pager-at { color: var(--ink-faint); }

/* Landing target for a deep link from the call history. */
.vm:target {
    border-color: var(--lamp);
    box-shadow: 0 0 0 1px rgba(232, 163, 61, 0.28);
}

.cidname {
    display: block;
    font-size: 12px;
    color: var(--ink-faint);
    margin-top: 1px;
}

/* --- Filters ------------------------------------------------------------ */

.filters {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
    align-items: center;
    padding: 14px 18px;
    border-bottom: 1px solid var(--line);
}

.filters input[type="search"] {
    flex: 1 1 220px;
    min-width: 0;
    padding: 8px 11px;
    background: var(--panel-deep);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    color: var(--ink);
    font: inherit;
    font-size: 14px;
}

.filters input[type="search"]::placeholder { color: var(--ink-faint); }

.filters select {
    padding: 8px 10px;
    background: var(--panel-deep);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    color: var(--ink);
    font: inherit;
    font-size: 13px;
}

/* --- Add form ----------------------------------------------------------- */

.addrow {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
    align-items: center;
}

.addrow input {
    padding: 8px 11px;
    background: var(--panel-deep);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    color: var(--ink);
    font: inherit;
    font-size: 14px;
}

.addrow input[name="number"] {
    width: 160px;
    font-family: var(--data-font);
}
.addrow input[name="note"] { flex: 1 1 220px; min-width: 0; }

/* --- Messages and empty states ------------------------------------------ */

.flash {
    padding: 11px 16px;
    border-radius: var(--radius);
    border: 1px solid var(--line);
    border-left-width: 3px;
    background: var(--panel);
    margin-bottom: 18px;
    font-size: 14px;
}
.flash.ok    { border-left-color: var(--ok); }
.flash.error { border-left-color: var(--bad); }

.empty {
    padding: 40px 18px;
    text-align: center;
    color: var(--ink-faint);
    font-size: 14px;
}
.empty strong { display: block; color: var(--ink-dim); margin-bottom: 5px; }

.pager {
    display: flex;
    gap: 16px;
    align-items: center;
    justify-content: center;
    padding: 16px;
    font-size: 13px;
    color: var(--ink-faint);
    border-top: 1px solid var(--line);
}

/* --- Login -------------------------------------------------------------- */

.gate {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
}

.gate .panel { width: 100%; max-width: 340px; margin: 0; }

.gate .panel-body { padding: 22px 20px 24px; }

.gate label { display: block; margin-bottom: 14px; }

.gate input {
    width: 100%;
    margin-top: 5px;
    padding: 9px 11px;
    background: var(--panel-deep);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    color: var(--ink);
    font: inherit;
}

.gate .btn { width: 100%; margin-top: 4px; }

/* --- Small screens ------------------------------------------------------ */

@media (max-width: 620px) {
    .shell { padding: 0 14px 56px; }
    header.masthead { margin: 0 -14px 22px; padding: 18px 14px 16px; }
    nav.tabs { width: 100%; margin-left: 0; gap: 16px; }
    .lamps { grid-template-columns: 1fr; }
    thead { display: none; }
    tbody td { display: block; padding: 4px 16px; border: 0; }
    tbody td:first-child { padding-top: 13px; }
    tbody td:last-child { padding-bottom: 13px; }
    tbody tr { display: block; border-bottom: 1px solid var(--line); }
    td.right { text-align: left; }
}


/* --- Home screen app ----------------------------------------------------
 *
 * Safari zooms any input whose font-size is under 16px when it gets
 * focus, and in standalone mode there is no pinch-out to undo it. Every
 * focusable field is therefore set at 16px on touch devices, whatever it
 * looks like on the desktop.
 */

@media (pointer: coarse) {
    .filters input[type="search"],
    .filters select,
    .addrow input,
    .timer input,
    .gate input {
        font-size: 16px;
    }

    /* Comfortable thumb targets. */
    .btn { padding: 11px 18px; }
    .btn-tiny { padding: 7px 12px; }
    .lamp-face { padding: 14px 15px; }
    nav.tabs a { padding-bottom: 6px; }
    tbody tr:hover { background: none; }
}

/* Standalone has no browser chrome, so the app supplies its own bottom
   breathing room above the home indicator. */
@media (display-mode: standalone) {
    .shell { padding-bottom: 40px; }
}

/* --- Voicemail ----------------------------------------------------------
 *
 * Each message is its own raised card with a coloured left edge keyed to
 * its verdict, separated by real gaps and grouped under day headings.
 * The earlier version stacked them inside one panel with hairline
 * dividers and it read as a wall of text: at a glance you could not tell
 * where one message ended and the next began.
 */

.daymark {
    margin: 26px 2px 10px;
    font-size: 10px;
    font-weight: 640;
    letter-spacing: 0.17em;
    text-transform: uppercase;
    color: var(--ink-faint);
}
.daymark:first-of-type { margin-top: 6px; }

.vm {
    background: var(--panel);
    border: 1px solid var(--line);
    border-left: 3px solid var(--line-bright);
    border-radius: var(--radius);
    padding: 15px 17px;
    margin-bottom: 10px;
}

/* Left edge carries the verdict, so the shape of the list is readable
   before any of it is read. */
.vm.v-important { border-left-color: var(--lamp); }
.vm.v-worth     { border-left-color: var(--ok); }
.vm.v-spam,
.vm.v-ai        { border-left-color: var(--bad); }
.vm.v-unsure,
.vm.v-probably,
.vm.v-none      { border-left-color: var(--line-bright); }

.vm-head {
    display: flex;
    align-items: center;
    gap: 9px;
    flex-wrap: wrap;
    margin-bottom: 9px;
}

.vm-cid {
    font-size: 16px;
    color: var(--ink);
    letter-spacing: -0.01em;
}

.vm-when {
    margin-left: auto;
    font-size: 12px;
    color: var(--ink-faint);
    white-space: nowrap;
}

.badge {
    font-size: 10px;
    font-weight: 640;
    letter-spacing: 0.11em;
    text-transform: uppercase;
    padding: 3px 8px;
    border-radius: 2px;
    border: 1px solid currentColor;
    white-space: nowrap;
    line-height: 1.4;
}

/* Amber is the signal lamp, so it marks what deserves attention rather
   than what is wrong. Junk is greyed down instead of shouted at. */
.badge.v-important { color: var(--lamp); background: rgba(232, 163, 61, 0.12); }
.badge.v-worth     { color: var(--ok); }
.badge.v-unsure    { color: var(--ink-dim); }
.badge.v-probably  { color: var(--ink-faint); }
.badge.v-spam      { color: var(--bad); }
.badge.v-ai        { color: var(--bad); }
.badge.v-none      { color: var(--ink-faint); }
.badge.v-job       { color: var(--lamp); background: rgba(232, 163, 61, 0.12); }

.vm-reason {
    margin: 0 0 11px;
    font-size: 14px;
    color: var(--ink-dim);
    line-height: 1.5;
}

.vm-extract {
    display: flex;
    flex-wrap: wrap;
    gap: 10px 30px;
    margin: 0 0 12px;
    padding: 11px 14px;
    background: var(--panel-deep);
    border-radius: var(--radius);
    border-left: 2px solid var(--lamp);
}
.vm-extract > div { min-width: 0; }
.vm-extract .label { display: block; margin-bottom: 2px; }
.vm-extract b { font-size: 14px; font-weight: 500; color: var(--ink); }

.vm-audio {
    width: 100%;
    height: 34px;
    margin-bottom: 11px;
    color-scheme: dark;
}

.vm-transcript { margin-bottom: 12px; }

/* list-item keeps the disclosure triangle, which display:flex removes —
   without it there is no affordance that the excerpt expands. */
.vm-transcript summary {
    cursor: pointer;
    display: list-item;
    list-style-position: inside;
    font-size: 13px;
    line-height: 1.55;
    color: var(--ink-dim);
    padding: 9px 12px;
    background: var(--panel-deep);
    border: 1px solid var(--line);
    border-radius: var(--radius);
}
.vm-transcript summary:hover { border-color: var(--line-bright); color: var(--ink); }
.vm-transcript summary::marker { color: var(--ink-faint); font-size: 11px; }
.vm-transcript[open] summary {
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
    color: var(--ink-faint);
}

.vm-transcript p {
    margin: 0;
    padding: 13px;
    font-size: 14px;
    line-height: 1.65;
    color: var(--ink);
    background: var(--panel-deep);
    border: 1px solid var(--line);
    border-top: 0;
    border-radius: 0 0 var(--radius) var(--radius);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.vm-aged { margin-bottom: 11px !important; }

.vm-note {
    margin: 0;
    font-size: 12px;
    color: var(--ink-faint);
    font-style: italic;
}

.vm-actions {
    display: flex;
    gap: 8px;
    align-items: center;
    flex-wrap: wrap;
}
.vm-actions form { display: inline; }
.vm-actions .spacer { flex: 1; }

.filters .toggle {
    display: flex;
    align-items: center;
    gap: 7px;
    font-size: 13px;
    color: var(--ink-dim);
    cursor: pointer;
    white-space: nowrap;
}
.filters .toggle input { accent-color: var(--lamp); width: 15px; height: 15px; }

@media (max-width: 620px) {
    .vm { padding: 13px 15px; }
    .vm-when { margin-left: 0; width: 100%; }
    .vm-extract { gap: 8px 20px; }
}


/* --- Messages -------------------------------------------------------------
 *
 * The SMS portal's own stylesheet is gone. It lived inline in its base.html
 * with a blue accent, a 10px radius scale, and a parallel class vocabulary
 * (.wrap/.card/.topbar against .shell/.panel/.masthead). Four of its class
 * names - .btn, .btn-primary, .flash, .empty - collided with these by name
 * while looking different, so namespacing would have meant specificity
 * fights on top of a rename that was most of the work anyway.
 *
 * What survives from it: the bubble geometry, which is genuinely
 * section-specific, and nothing else. Colours all resolve to the tokens above.
 */

.panel-body.flush { padding: 0; }

.count {
    font: 500 12px/1 var(--data-font);
    color: var(--ink-faint);
    margin-left: 6px;
}

.dim   { color: var(--ink-dim); }
.grow  { flex: 1; min-width: 180px; }
.narrow { flex: 0 0 150px; }
.note  { color: var(--ink-faint); margin-left: 8px; font-size: 13px; }

/* Conversation list */

.thread-row {
    display: block;
    padding: 13px 16px;
    color: inherit;
    text-decoration: none;
    border-bottom: 1px solid var(--line);
}
.thread-row:last-child { border-bottom: 0; }
/* Was an inline onmouseover/onmouseout pair, which the CSP blocks. */
.thread-row:hover { background: var(--panel-raised); }

.thread-head {
    display: flex;
    align-items: baseline;
    gap: 10px;
}
.thread-peer { font-weight: 600; font-size: 15px; color: var(--ink); }
.thread-peer.big { font-size: 19px; letter-spacing: -.2px; }
.thread-via  { color: var(--ink-dim); font-size: 12px; }
.thread-when {
    margin-left: auto;
    color: var(--ink-faint);
    font: 400 12px/1 var(--data-font);
    white-space: nowrap;
}
.thread-preview {
    color: var(--ink-dim);
    font-size: 14px;
    margin-top: 4px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.thread-preview .failed { color: var(--bad); }

.thread-title {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 14px;
}

.newthread {
    display: flex;
    gap: 12px;
    align-items: flex-end;
    flex-wrap: wrap;
}

/* Thread */

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

.msg { display: flex; margin-bottom: 12px; justify-content: flex-start; }
.msg.out { justify-content: flex-end; }
.msg-inner { max-width: 76%; }

.msg-bubble {
    background: var(--panel-raised);
    color: var(--ink);
    padding: 9px 13px;
    border-radius: var(--radius-bubble);
    border-bottom-left-radius: var(--radius-bubble-tail);
    border: 1px solid transparent;
    white-space: pre-wrap;
    word-wrap: break-word;
    font-size: 15px;
}
/* Outbound is NOT a solid amber fill. #e8a33d behind white text is about
   1.9:1, which fails contrast badly. This is the same translucent treatment
   .btn-primary already uses: it still reads unmistakably as "mine". */
.msg.out .msg-bubble {
    background: rgba(232, 163, 61, 0.13);
    border-color: rgba(232, 163, 61, 0.45);
    border-bottom-left-radius: var(--radius-bubble);
    border-bottom-right-radius: var(--radius-bubble-tail);
}
.msg.out.failed .msg-bubble {
    background: rgba(201, 96, 79, 0.13);
    border-color: rgba(201, 96, 79, 0.5);
}

.msg-media { margin-top: 6px; }
.msg-media img {
    max-width: 100%;
    display: block;
    border-radius: 12px;
    border: 1px solid var(--line);
}
.msg-noattach { color: var(--ink-dim); font-size: 12px; margin-top: 4px; }

.msg-meta {
    font-size: 11px;
    color: var(--ink-faint);
    margin-top: 4px;
    text-align: left;
}
.msg.out .msg-meta { text-align: right; }

/* Painted by sms-thread.js via data-state, not by inline style. */
.msg-status[data-state="ok"]      { color: var(--ok); }
.msg-status[data-state="pending"] { color: var(--warn); }
.msg-status[data-state="failed"]  { color: var(--bad); }

.msg-error {
    font-size: 11px;
    color: var(--bad);
    margin-top: 2px;
    text-align: right;
}

/* Composer */

.composer textarea {
    resize: vertical;
    margin-bottom: 10px;
    width: 100%;
}
.composer-row {
    display: flex;
    gap: 10px;
    align-items: center;
    flex-wrap: wrap;
}
.counter { font-size: 12px; }
.counter.over { color: var(--warn); }

.badge.shortcode {
    font-weight: 500;
    color: var(--ink-dim);
    border: 1px solid var(--line);
    margin-left: 6px;
    vertical-align: middle;
}

/* --- Wake-ups ------------------------------------------------------------ */

.wake-form label { display: block; margin-bottom: 12px; }
.quickset {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 14px;
}
.wake-rows td { padding: 9px 10px; vertical-align: middle; }
.wake-rows .actions { text-align: right; }
/* A file whose time has passed is one pbx_spool has not run. Make it loud:
   the alternative is a wake-up that silently did not happen. */
.wake-rows tr.overdue td { background: rgba(212, 135, 79, 0.09); }
.badge.warn { color: var(--warn); border-color: var(--warn); }
.badge.ok   { color: var(--ok);   border-color: var(--ok); }
.badge.bad  { color: var(--bad);  border-color: var(--bad); }
.linkbtn.danger { color: var(--bad); }

/* Call outcome pill for a wake-up: the PBX called you. */
.disp.wakeup { color: var(--lamp); }

/* Unread counts.
 *
 * Amber, because in this palette --lamp is the "look here" colour and that is
 * the entire job. Rendered only when non-zero: a persistent "0" is noise, and
 * an absent badge when the SMS database is down is deliberate - see
 * unread_count() in app.py. */
/* Badge only - a count pill. NOT a row modifier: a bare .unread on a
   .thread-row would paint the whole row amber, because this rule matches any
   element carrying the class. Rows use .is-unread instead. */
.unread {
    display: inline-block;
    min-width: 17px;
    padding: 1px 5px;
    margin-left: 6px;
    border-radius: 9px;
    background: var(--lamp);
    color: var(--panel-deep);
    font: 600 11px/1.45 var(--data-font);
    text-align: center;
    vertical-align: 1px;
}
nav.tabs a .unread { margin-left: 5px; }
.thread-row.is-unread .thread-peer { color: var(--lamp); }
.thread-row.is-unread .thread-preview { color: var(--ink); }
