  /* Keyboard focus is visible everywhere, in the accent, and only for
     keyboard focus — a mouse click does not draw a ring. */
  :focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
  .field input:focus-visible, .field textarea:focus-visible,
  #search:focus-visible, #nc-input:focus-visible, #text:focus-visible,
  .dial-num:focus-visible { outline: none; }

  * { box-sizing: border-box; }
  html, body { height: 100%; }
  body {
    margin: 0;
    font-family: var(--ui);
    font-size: 14px;
    color: var(--text);
    background: var(--bg);
    background-image: var(--scene);
    background-attachment: fixed;
    -webkit-font-smoothing: antialiased;
  }
  button, input, textarea, select { font: inherit; color: inherit; }
  svg { width: 24px; height: 24px; fill: currentColor; display: block; flex: none; }
  .hidden { display: none !important; }

  /* ---------- sign in ---------- */
  #signin {
    min-height: 100%;
    display: grid;
    place-items: center;
    padding: 24px;
    background: var(--surface-2);
  }
  .card {
    width: 100%;
    max-width: 420px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 40px;
  }
  .card h1 {
    margin: 0 0 8px;
    font-size: 24px;
    font-weight: 400;
    letter-spacing: 0;
  }
  .card p.sub { margin: 0 0 28px; color: var(--text-2); }
  .field { position: relative; margin-bottom: 20px; }
  .field input {
    width: 100%;
    padding: 13px 15px;
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 4px;
    outline: none;
  }
  .field input:focus { border-color: var(--primary); box-shadow: inset 0 0 0 1px var(--primary); }
  .field label {
    position: absolute;
    left: 8px; top: -8px;
    padding: 0 6px;
    font-size: 12px;
    color: var(--text-2);
    background: var(--surface);
  }
  .field input:focus + label { color: var(--primary); }

  .btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    height: 36px;
    padding: 0 24px;
    border: 0;
    border-radius: 4px;
    background: var(--primary);
    color: var(--on-primary);
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
  }
  .btn:hover:not(:disabled) { filter: brightness(1.06); box-shadow: var(--shadow); }
  .btn:disabled { opacity: .5; cursor: default; }
  .btn.text { background: transparent; color: var(--primary); padding: 0 12px; }
  .btn.text:hover:not(:disabled) { background: var(--hover); box-shadow: none; filter: none; }
  .btn.outline {
    background: transparent; color: var(--primary);
    border: 1px solid var(--border);
  }
  .btn.outline:hover:not(:disabled) { background: var(--hover); box-shadow: none; filter: none; }
  .btn.danger { background: transparent; color: var(--danger); border: 1px solid var(--border); }
  .btn.danger:hover:not(:disabled) { background: var(--hover); box-shadow: none; filter: none; }

  .notice {
    margin: 0 0 20px;
    padding: 12px 14px;
    border-radius: 4px;
    background: var(--surface-2);
    color: var(--danger);
    font-size: 13px;
  }
  .notice.ok { color: var(--text); }

  /* ---------- shell ---------- */
  #app { height: 100%; display: flex; flex-direction: column; }

  header.bar {
    flex: none;
    display: flex; align-items: center; justify-content: space-between;
    gap: 10px; padding: 12px 16px 6px;
    background: transparent;   /* the scene shows through, like the app */
    position: relative;        /* the account menu + search hang off this */
  }
  .appmark {
    width: 30px; height: 30px; flex: none;
    border-radius: 9px;
    background: var(--primary);
    display: grid; place-items: center;
  }
  .appmark svg { width: 17px; height: 17px; fill: var(--on-primary); }
  .brand {
    display: flex; align-items: center; gap: 10px;
    font-size: 22px; font-weight: 400; color: var(--text-2);
    margin-right: 8px;
  }
  .brand svg { color: var(--primary); width: 28px; height: 28px; }
  .brand b { color: var(--text); font-weight: 500; }

  /* The active-line chip — the design's "MAIN · 415 555 0142 ▾". */
  .linechip {
    display: inline-flex; align-items: center; gap: 9px; min-width: 0;
    background: var(--glass-2); border: 1px solid var(--border);
    border-radius: 999px; padding: 8px 12px; cursor: pointer; color: var(--text);
  }
  .linechip .ld { width: 7px; height: 7px; border-radius: 50%;
                  background: var(--primary); flex: none; }
  .linechip #linechip-num {
    font: 500 12px var(--mono); letter-spacing: .04em; color: var(--text);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  /* Do Not Disturb, said out loud wherever it applies. */
  .dndchip {
    display: inline-flex; align-items: center; gap: 6px; flex: none;
    padding: 6px 11px; border-radius: 999px;
    background: var(--note-bg); color: var(--note-text);
    font: 600 11px var(--mono); letter-spacing: .06em; text-transform: uppercase;
    white-space: nowrap;
  }
  .dndchip svg { width: 13px; height: 13px; fill: currentColor; }
  header.bar .dndchip { margin-left: -2px; }
  .pane-tools { display: inline-flex; align-items: center; gap: 8px; }
  .pane-tools .icon-btn[aria-pressed="true"] { color: var(--note-text); background: var(--note-bg); }
  .linechip .lcx { width: 14px; height: 14px; fill: var(--text-2); flex: none; }
  .bar-right { display: flex; align-items: center; gap: 4px; flex: none; }
  /* Search is kept but tucked behind an icon; tapping it slides a field
     over the bar. */
  .searchfield { display: none; }
  body.searching .searchfield {
    display: flex; align-items: center; gap: 8px;
    position: absolute; left: 12px; right: 12px; top: 8px; z-index: 6;
    height: 48px; padding: 0 6px 0 14px;
    background: var(--surface-2); border: 1px solid var(--border);
    border-radius: 999px;
  }
  body.searching .linechip, body.searching .bar-right { visibility: hidden; }
  .searchfield > svg { flex: none; width: 20px; height: 20px; fill: var(--text-2); }
  .searchfield input {
    flex: 1; min-width: 0; border: 0; background: transparent; outline: none;
    color: var(--text); font-size: 15px;
  }
  .searchfield input::placeholder { color: var(--text-2); }
  #search-clear { width: 34px; height: 34px; flex: none; }
  #search-clear svg { width: 18px; height: 18px; }

  /* ---------- the account menu ---------- */
  .menu.acct { top: 60px; right: 12px; min-width: 260px; }
  .acct-head {
    display: flex; gap: 12px; align-items: center;
    padding: 14px 18px 12px;
    border-bottom: 1px solid var(--border);
    margin-bottom: 6px;
  }
  .acct-head .face {
    width: 40px; height: 40px; border-radius: 50%; flex: none;
    background: var(--primary); color: var(--on-primary);
    display: grid; place-items: center; font-weight: 500; font-size: 17px;
  }
  .acct-head .whoami { min-width: 0; }
  .acct-head .whoami b {
    display: block; font-weight: 500; font-size: 14px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .acct-head .whoami span { font-size: 12.5px; color: var(--text-2); }
  .brand { min-width: 0; }
  .bar .spacer { flex: 1; }
  .icon-btn {
    display: grid; place-items: center;
    width: 40px; height: 40px;
    border: 0; border-radius: 50%;
    background: transparent; color: var(--text-2);
    cursor: pointer;
    transition: transform .12s ease, color .12s ease;
  }
  .icon-btn:hover { background: var(--hover); }
  .avatar-btn {
    width: 32px; height: 32px; border-radius: 50%; border: 0;
    background: var(--primary); color: var(--on-primary);
    font-weight: 500; cursor: pointer;
  }

  .body { flex: 1; display: flex; min-height: 0; }

  /* Four labeled doors, matching Android HomeNav. */
  nav.bottomnav {
    display: flex; gap: 4px; padding: 6px;
    border-radius: 999px; background: var(--nav-surface);
    border: 1px solid var(--border); box-shadow: var(--shadow);
  }
  nav.bottomnav button {
    flex: 1; min-width: 0; min-height: 58px; padding: 7px 4px;
    display: flex; flex-direction: column; gap: 3px;
    align-items: center; justify-content: center;
    border: 0; background: transparent; color: var(--text-2);
    cursor: pointer; border-radius: 999px;
    transition: background .15s ease, color .15s ease;
  }
  nav.bottomnav .pill { position: relative; display: grid; place-items: center; }
  nav.bottomnav svg { width: 24px; height: 24px; fill: currentColor; }
  nav.bottomnav .nav-label { font-size: 11px; }
  nav.bottomnav button:hover { background: var(--hover); color: var(--text); }
  nav.bottomnav button[aria-selected="true"] {
    background: color-mix(in srgb, var(--text) 12%, transparent);
    color: var(--text); font-weight: 600;
  }
  .navbadge {
    position: absolute; top: -2px; right: 6px;
    min-width: 15px; height: 15px; padding: 0 3px;
    border-radius: 8px;
    background: var(--danger); color: #fff;
    font-size: 9.5px; font-weight: 700; line-height: 15px;
  }

  /* ---------- conversation list ---------- */
  section.list {
    width: var(--list); flex: none;
    border-right: 1px solid var(--border);
    display: flex; flex-direction: column;
    background: var(--surface);
    min-height: 0;
  }
  .list-head {
    flex: none;
    display: flex; align-items: baseline; justify-content: space-between;
    padding: 14px 18px 8px;
  }
  .list-head > span:first-child {
    font: 600 32px var(--ui); letter-spacing: -.03em; color: var(--text);
  }
  /* Assignment filters (Mine / Unassigned) are hidden — the design keeps
     search only, not the team lenses. */
  .list-head .tabs { display: none; }
  .rows {
    flex: 1; overflow-y: auto;
    padding: 8px 12px 14px;
    display: flex; flex-direction: column; gap: 8px;
  }
  /* Each conversation is a rounded Nocturne card, not a flat Material row. */
  .row {
    display: flex; gap: 13px; align-items: flex-start;
    padding: 13px 14px;
    cursor: pointer;
    border: 0; width: 100%; text-align: left;
    background: var(--glass); border-radius: 20px;
  }
  .row:hover { background: var(--hover); }
  .row[aria-selected="true"] { background: var(--selected); }
  .row[aria-selected="true"] .who { color: var(--selected-text); }
  .avatar {
    width: 40px; height: 40px; flex: none;
    border-radius: 50%;
    display: grid; place-items: center;
    color: #fff;
  }
  /* In the design's message/contact lists the avatar is a rounded square. */
  .row .avatar { border-radius: 14px; }
  .avatar svg { width: 22px; height: 22px; }
  .row .mid { flex: 1; min-width: 0; }
  .who {
    font: 600 15px var(--ui); color: var(--text);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .snippet {
    color: var(--text-2); font-size: 13px; margin-top: 4px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .row .when {
    flex: none;
    display: flex; flex-direction: column; align-items: flex-end; gap: 7px;
    font: 500 11px var(--mono); color: var(--text-2);
  }
  .row .when span, .row .when time { font: 500 11px var(--mono); color: var(--text-2); }
  .row.unread .who { font-weight: 600; color: var(--text); }
  .row.unread .snippet { color: var(--text); }
  .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--primary); }

  .section {
    padding: 16px 20px 6px;
    font-size: 12px; font-weight: 500; letter-spacing: .8px;
    text-transform: uppercase; color: var(--text-2);
  }
  .empty {
    padding: 48px 24px; text-align: center; color: var(--text-2);
  }
  .empty svg { width: 48px; height: 48px; margin: 0 auto 16px; opacity: .5; }

  /* A pencil on a circle, and nothing else. Every phone's is, and the
     word beside it was doing no work the icon was not already doing. */
  .fab {
    position: absolute; right: 20px; bottom: 20px;
    display: grid; place-items: center;
    width: 56px; height: 56px; padding: 0;
    border: 0; border-radius: 18px;
    background: var(--primary); color: var(--on-primary);
    box-shadow: var(--shadow); cursor: pointer;
  }
  .fab svg { width: 24px; height: 24px; }

  /* ---------- new chat ----------
     Android's New conversation screen, and not a dialog. A dialog asked
     for the recipient AND the message before it would do anything, which
     makes it a form: you could not look up who you meant, could not
     change your mind about them, and cancelling threw away what you had
     already typed. This is a screen. It picks a person, then opens the
     conversation, and the message is written in the composer like every
     other message in the app. */
  section.newchat {
    width: var(--list); flex: none;
    border-right: 1px solid var(--border);
    display: flex; flex-direction: column;
    background: var(--surface);
    min-width: 0; min-height: 0;
  }
  .nc-head {
    height: 64px; flex: none;
    display: flex; align-items: center; gap: 8px;
    padding: 0 8px 0 6px;
  }
  .nc-head .title { font-size: 20px; font-weight: 400; }
  .nc-row {
    display: flex; align-items: center; gap: 10px;
    padding: 6px 20px 14px;
    border-bottom: 1px solid var(--border);
  }
  .nc-row + .nc-row { padding-top: 12px; }
  .nc-row .nc-label { flex: none; color: var(--text-2); font-size: 15px; }
  /* The field is the row, with no box drawn round it — the divider under
     it is the whole decoration, the way the phone does it. */
  #nc-input, #nc-from {
    flex: 1; min-width: 0; height: 34px;
    border: 0; outline: none; background: transparent;
    color: var(--text); font: inherit; font-size: 15px;
  }
  #nc-from { cursor: pointer; }
  body.composing section.list { display: none; }
  .nc-results { flex: 1; overflow-y: auto; padding-bottom: 12px; }
  /* A conversation row is two lines against a 40px avatar, so the list
     aligns to the top. Half of these are one line — a bare number nobody
     has named — and top-aligning those hangs the text off the avatar's
     forehead. */
  .nc-results .row { align-items: center; }
  .nc-hint { padding: 32px 24px; text-align: center; color: var(--text-2); font-size: 13px; }
  /* The one row that is not a person: "Send to (845) 746-2044", for
     someone who is in no list because you have never texted them. */
  .row .avatar.plain { background: var(--hover) !important; color: var(--text-2); }

  /* ---------- thread ---------- */
  section.thread { flex: 1; display: flex; flex-direction: column; min-width: 0;
                   position: relative; }
  /* A file held over the conversation is an attachment about to happen. */
  section.thread.dropping::after {
    content: ""; position: absolute; inset: 8px; border-radius: 16px;
    border: 2px dashed var(--primary); pointer-events: none;
  }
  /* Something arrived below what you are reading. */
  .jump {
    position: absolute; left: 50%; transform: translateX(-50%);
    bottom: 84px; z-index: 5;
    border: 0; border-radius: 999px; padding: 8px 16px;
    background: var(--primary); color: var(--on-primary);
    font: inherit; font-size: 13px; font-weight: 500;
    box-shadow: 0 2px 8px rgba(0,0,0,.28); cursor: pointer;
  }
  /* Links inside a bubble write in the bubble's own ink — a blue link on
     the blue outbound bubble would vanish. The underline carries it. */
  .bubble a { color: inherit; text-decoration: underline; }
  /* What is written but not sent, on the conversation it belongs to. */
  .snippet .dmark { color: var(--danger); font-weight: 500; }
  .thread-head {
    height: 64px; flex: none; position: relative;
    display: flex; align-items: center; gap: 14px;
    padding: 0 16px;
    border-bottom: 1px solid var(--border);
  }
  .thread-head .back { display: none; }
  .thread-head .avatar { width: 36px; height: 36px; border-radius: 12px; }
  .thread-head .title { font: 600 15px var(--ui); color: var(--text); }
  .thread-head .via {
    font: 400 10.5px var(--mono); letter-spacing: .06em;
    text-transform: uppercase; color: var(--text-2); margin-top: 3px;
  }
  #thread-call { background: var(--selected); color: var(--primary); }

  .messages {
    flex: 1; overflow-y: auto; overflow-x: hidden;
    padding: 20px 24px 8px;
    display: flex; flex-direction: column; gap: 2px;
  }
  /* "Yesterday · 4:23 PM", centred. A conversation is read in bursts
     minutes or months apart, and the useful question at the top of one is
     not which day it was but how long it had been. */
  .daysep {
    align-self: center; margin: 22px 0 14px;
    font-size: 12px; font-weight: 500; color: var(--text-2);
  }
  .daysep:first-child { margin-top: 8px; }
  .msg {
    max-width: min(65%, 560px); position: relative;
    display: flex; flex-direction: column;
  }
  .msg.in { align-self: flex-start; align-items: flex-start; }
  .msg.out { align-self: flex-end; align-items: flex-end; }
  .bubble {
    padding: 10px 16px;
    border-radius: 20px;
    font-size: 15px; line-height: 1.35;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
  }
  .msg.in .bubble { background: var(--bubble-in); color: var(--bubble-in-text); }
  .msg.out .bubble { background: var(--primary); color: var(--on-primary); }
  /* Consecutive bubbles from the same side tuck together, the way every
     messaging app groups a burst into one visual block. */
  .msg.in.mid .bubble, .msg.in.last .bubble { border-top-left-radius: 4px; }
  .msg.in.first .bubble, .msg.in.mid .bubble { border-bottom-left-radius: 4px; }
  .msg.out.mid .bubble, .msg.out.last .bubble { border-top-right-radius: 4px; }
  .msg.out.first .bubble, .msg.out.mid .bubble { border-bottom-right-radius: 4px; }
  .msg + .msg.first { margin-top: 10px; }
  .meta { font-size: 11px; color: var(--text-2); margin: 4px 2px 6px; }
  .meta.bad { color: var(--danger); }
  .bubble.media { padding: 4px; background: transparent !important; }
  /* A measured picture's bubble IS its final shape before the bytes
     arrive: the skeleton shimmers in that exact footprint, and the
     image fades into it without moving a thing. */
  .bubble.media.sized { overflow: hidden; }
  .bubble.media.sized img {
    width: 100%; height: 100%; object-fit: cover; display: block;
    opacity: 1; transition: opacity .25s ease;
  }
  .bubble.media.skeleton { border-radius: 14px; }
  .bubble.media.skeleton img { opacity: 0; }
  .bubble.media.skeleton::before {
    content: ""; position: absolute; inset: 0; border-radius: 14px;
    background: linear-gradient(100deg, var(--bubble-in) 40%,
      rgba(255,255,255,.14) 50%, var(--bubble-in) 60%) 0 0 / 200% 100%;
    animation: shimmer 1.1s linear infinite;
  }
  @keyframes shimmer { to { background-position: -200% 0; } }
  .bubble.media.sized { position: relative; }
  .bubble.media img {
    display: block; max-width: 280px; max-height: 320px;
    border-radius: 14px; cursor: pointer;
  }
  .bubble.attach {
    display: inline-flex; align-items: center; gap: 8px;
    text-decoration: none;
  }
  .bubble.media audio { display: block; max-width: 280px; }

  /* ---------- a voice note ----------
     WhatsApp's, because it is the one everybody has already used ten
     thousand times: a bare play triangle, a waveform with a bead on it
     you can drag, the length under the triangle and the time at the far
     end, and a face with a microphone on it so the bubble says what it is
     before you have read a thing. The browser's own <audio controls> is a
     grey slab with a volume slider and an overflow menu — furniture from
     a media player, in the middle of a conversation. */
  .bubble.voice { padding: 8px 12px 6px 8px; }
  .vn {
    display: grid; column-gap: 8px; align-items: center;
    /* Definite, so the waveform column has something to be the rest OF.
       A percentage here resolves against a bubble that is itself sizing
       to this grid, and the waveform collapses to nothing. */
    width: 300px; max-width: 100%;
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas: "play wave face"
                         "len  when face";
  }
  /* Ours reads the other way round, as it does on the phone. */
  .msg.out .vn {
    grid-template-columns: auto auto minmax(0, 1fr);
    grid-template-areas: "face play wave"
                         "face len  when";
  }
  .vn-play {
    grid-area: play; width: 30px; height: 30px; padding: 0;
    border: 0; background: transparent; color: inherit;
    display: grid; place-items: center; cursor: pointer; opacity: .8;
  }
  .vn-play svg { width: 26px; height: 26px; }
  .vn-wave {
    grid-area: wave; position: relative;
    height: 32px; cursor: pointer; touch-action: none;
    display: flex; align-items: center; gap: 2px;
  }
  .vn-wave .bar {
    flex: 1; min-width: 0; border-radius: 2px;
    background: currentColor; opacity: .35;
  }
  .vn-wave .bar.on { opacity: .95; }
  /* The bead. Where you are, and the thing you drag to be somewhere else. */
  .vn-head {
    position: absolute; top: 50%; left: 0;
    width: 12px; height: 12px; margin: -6px 0 0 -6px;
    border-radius: 50%; pointer-events: none;
  }
  .msg.in .vn-head { background: var(--primary); }
  .msg.out .vn-head { background: var(--on-primary); }
  .vn-len, .vn-when {
    font-size: 11px; opacity: .75; font-variant-numeric: tabular-nums;
    line-height: 1.6;
  }
  .vn-len { grid-area: len; }
  .vn-when { grid-area: when; justify-self: end; }
  .vn-face { grid-area: face; position: relative; width: 40px; height: 40px; }
  .vn-face .avatar { width: 40px; height: 40px; }
  /* Nobody sent this from a face we have a picture of — but the shape is
     half of what makes the bubble recognisable, so it keeps the shape. */
  .vn-face .avatar.ours {
    background: rgba(128, 128, 128, .28);
    /* A wash of whatever the bubble writes in, so it reads on a light
       bubble and a dark one without either being named here. */
    background: color-mix(in srgb, currentColor 22%, transparent);
  }
  .vn-face .mic {
    position: absolute; right: -3px; bottom: -1px;
    width: 18px; height: 18px; border-radius: 50%;
    display: grid; place-items: center;
  }
  .vn-face .mic svg { width: 12px; height: 12px; }
  .msg.in .vn-face .mic { background: var(--primary); color: var(--on-primary); }
  .msg.out .vn-face .mic { background: var(--on-primary); color: var(--primary); }
  .bubble.media video { display: block; max-width: 280px; border-radius: 14px; }

  .composer { flex: none; padding: 12px 24px 20px; position: relative; }
  .pending { padding-left: 84px; }

  .picker { max-width: 520px; }
  .picker .list { max-height: 46vh; overflow-y: auto; margin: 0 -24px; }
  .picker .item {
    display: block; width: 100%; text-align: left;
    padding: 12px 24px; border: 0; background: transparent; cursor: pointer;
  }
  .picker .item:hover { background: var(--hover); }
  .picker .item b { display: block; font-weight: 500; }
  .picker .item span {
    display: block; color: var(--text-2); font-size: 13px; margin-top: 2px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .picker .item .drop {
    float: right; color: var(--text-2); font-size: 12px;
    border: 0; background: transparent; cursor: pointer;
  }

  .headtext { flex: 1; min-width: 0; }
  /* One line each. The header used to carry a wordy assignment dropdown
     beside the name, which squeezed a plain phone number onto two lines
     and left the header looking broken before you had read a word of the
     conversation. Everything that was in there is behind the ⋮ now. */
  .thread-head .title, .thread-head .via {
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }

  /* ---------- picking messages out ----------
     Hold one and the conversation becomes a list you are choosing from:
     the header turns into a count and the two things worth doing to a
     message, and everything in a bubble stops being a control. */
  .selbar {
    position: absolute; inset: 0; z-index: 5;
    display: flex; align-items: center; gap: 4px;
    padding: 0 8px 0 6px;
    background: var(--surface);
  }
  .selcount { flex: 1; min-width: 0; font-size: 18px; font-weight: 500; }
  /* The tint runs the full width of the conversation, not just the
     bubble's — a picked message is a picked ROW, which is what makes a
     column of them readable at a glance. */
  .msg.picked::before {
    content: ""; position: absolute;
    top: -3px; bottom: -3px; left: -1000px; right: -1000px;
    background: var(--selected);
  }
  .msg.picked > * { position: relative; }
  /* A flag anyone in the workspace can see, which is the only kind worth
     having in a shared inbox. */
  .starred {
    display: flex; align-items: center; gap: 4px;
    font-size: 11px; color: var(--star); margin: 3px 2px 0;
  }
  .starred svg { width: 13px; height: 13px; fill: var(--star); }
  body.selecting .messages { cursor: pointer; }
  /* Only where the pointer is a finger. A mouse keeps text selection —
     dragging across a message to copy part of it is a real thing to want,
     and a finger cannot do it anyway without fighting the hold. */
  @media (pointer: coarse) {
    .msg { -webkit-user-select: none; user-select: none;
           -webkit-touch-callout: none; }
  }
  body.selecting .bubble, body.selecting .vn * { pointer-events: none; }
  .btn.danger { background: var(--danger); color: #fff; }

  /* ---------- the overflow menu ---------- */
  .menu {
    position: absolute; top: 56px; right: 8px; z-index: 6;
    min-width: 210px; padding: 6px 0;
    background: var(--surface); border: 1px solid var(--border);
    border-radius: 12px; box-shadow: var(--shadow);
  }
  .menu .item {
    display: block; width: 100%; text-align: left;
    padding: 11px 18px; border: 0; background: transparent;
    color: var(--text); font: inherit; font-size: 14px; cursor: pointer;
  }
  .menu .item:hover { background: var(--hover); }
  .menu .item:disabled { opacity: .4; cursor: default; background: transparent; }

  /* A note is not a message and must not read like one: not a bubble, not
     on either side, and a colour no message ever has. */
  .note {
    align-self: center; max-width: min(78%, 560px);
    margin: 12px 0; padding: 12px 16px;
    background: var(--note-bg); border: 1px solid var(--note-chip);
    border-radius: 14px; font-size: 13px; line-height: 1.45;
    white-space: pre-wrap; overflow-wrap: anywhere;
  }
  .note .byline {
    display: flex; align-items: center; gap: 6px;
    color: var(--note-text); font-size: 11px; font-weight: 500;
    margin-bottom: 4px; text-transform: uppercase; letter-spacing: .6px;
  }
  .note .byline svg { width: 14px; height: 14px; }
  .note .drop {
    float: right; border: 0; background: transparent; cursor: pointer;
    color: var(--text-2); font-size: 11px; padding: 0 0 0 8px;
  }
  .composer-row { display: flex; align-items: flex-end; gap: 8px; }
  /* Recording puts the bar in the composer's place — but the row it
     replaces must not be DISPLAYED away, because hiding an element blurs
     whatever inside it had focus, and blurring the text field drops the
     keyboard. Tapping the microphone would put the keyboard away, and
     the page would jump twice: once as it left, once as it came back.
     Out of flow, no height, invisible and untouchable — but still
     rendered, so the caret stays exactly where it was. */
  .composer-row.stowed {
    position: absolute; height: 0; overflow: hidden;
    opacity: 0; pointer-events: none;
  }
  .pending {
    display: flex; flex-wrap: wrap; gap: 8px;
    padding: 0 0 10px 44px;
  }
  .pending:empty { display: none; }
  .att {
    display: inline-flex; align-items: center; gap: 8px;
    padding: 6px 6px 6px 12px; border-radius: 16px;
    background: var(--surface-2); font-size: 13px; max-width: 260px;
  }
  .att span {
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .att button {
    border: 0; background: transparent; color: var(--text-2);
    cursor: pointer; display: grid; place-items: center; padding: 0;
  }
  .att svg { width: 18px; height: 18px; }
  .att.busy { opacity: .6; }
  /* ---------- recording ----------
     What the phone shows while you are talking into it: how long you have
     been going, what the microphone is actually hearing, and — once the
     recording is locked and your thumb is free — throw it away, hold on,
     or send it.

     The live waveform is not decoration. A timer counting up tells you a
     recording is RUNNING; only the waveform tells you it is picking YOU
     up, which is the thing worth knowing before you have said thirty
     seconds into a muted microphone. */
  .recbar {
    display: flex; flex-direction: column; gap: 10px;
    padding: 10px 18px 12px; margin-bottom: 10px;
    background: var(--surface-2); border-radius: 24px;
  }
  .recline { display: flex; align-items: center; gap: 12px; }
  .recline #rectime {
    font-size: 14px; font-variant-numeric: tabular-nums; min-width: 34px;
  }
  .livewave {
    flex: 1; min-width: 0; height: 28px;
    display: flex; align-items: center; gap: 2px;
  }
  .livewave .bar {
    flex: 1; min-width: 0; height: 8%;
    border-radius: 2px; background: var(--text-2); opacity: .85;
  }
  .rechint { color: var(--text-2); font-size: 13px; text-align: center; }
  .reccontrols {
    display: flex; align-items: center; justify-content: space-between;
    padding: 0 4px;
  }
  .recpause {
    width: 48px; height: 48px; padding: 0;
    border: 0; border-radius: 50%; background: transparent;
    color: var(--danger); display: grid; place-items: center; cursor: pointer;
  }
  .recpause svg { width: 30px; height: 30px; }
  .reddot {
    width: 10px; height: 10px; border-radius: 50%; flex: none;
    background: var(--danger); animation: pulse 1.2s infinite;
  }
  /* Paused is a still picture: the dot stops, and so does the waveform. */
  .recbar.paused .reddot { animation: none; opacity: .4; }
  .recbar.paused .livewave { opacity: .45; }
  @keyframes pulse { 50% { opacity: .25; } }
  @media (prefers-reduced-motion: reduce) { .reddot { animation: none; } }
  .composer .inputwrap {
    flex: 1; display: flex; align-items: flex-end; gap: 8px;
    background: var(--surface-2);
    border-radius: 24px;
    padding: 6px 8px 6px 18px;
  }
  /* What the next message costs, once that stops being obvious. */
  .cost {
    align-self: flex-end; flex: none; padding: 0 2px 10px;
    font-size: 11px; color: var(--text-2);
    font-variant-numeric: tabular-nums;
  }
  .cost.over { color: var(--note-text); font-weight: 500; }
  /* The conversation list's three lenses. */
  .tabs { display: flex; gap: 6px; margin-left: auto; }
  .tabs button {
    border: 1px solid var(--border); background: transparent;
    color: var(--text-2); font: inherit; font-size: 12.5px;
    padding: 4px 12px; border-radius: 999px; cursor: pointer;
  }
  .tabs button[aria-selected="true"] {
    background: var(--primary-soft);
    border-color: transparent; color: var(--primary); font-weight: 500;
  }
  .who .bell { width: 14px; height: 14px; vertical-align: -2px;
               margin-left: 6px; fill: var(--text-2); }
  .who .pinned { width: 13px; height: 13px; vertical-align: -2px;
                 margin-left: 6px; fill: var(--text-2);
                 transform: rotate(35deg); }
  /* A snooze that has rung: the thread is back, saying why it is back. */
  .nap-due { font-size: 11px; margin-left: 6px; }
  /* The banner over a snoozed conversation. */
  .napbar {
    display: flex; align-items: center; gap: 10px;
    padding: 8px 16px; font-size: 12.5px; color: var(--text-2);
    background: var(--primary-soft);
  }
  .napbar button { border: 0; background: none; color: var(--primary);
                   font: inherit; font-size: 12.5px; font-weight: 500;
                   cursor: pointer; padding: 0; white-space: nowrap; }
  /* Suggested replies: a quiet row of taps above the composer. */
  .smart { display: flex; gap: 8px; padding: 8px 12px 0;
           overflow-x: auto; scrollbar-width: none; }
  .smart::-webkit-scrollbar { display: none; }
  .smart .chip {
    border: 1px solid transparent;
    background: var(--primary-soft);
    color: var(--primary); font: inherit; font-size: 13px;
    padding: 7px 14px; border-radius: 999px; cursor: pointer;
    white-space: nowrap; flex: none; max-width: 340px;
    overflow: hidden; text-overflow: ellipsis;
    animation: chipin .18s ease-out;
  }
  .smart .chip:hover { border-color: var(--primary); }
  @keyframes chipin { from { opacity: 0; transform: translateY(4px); } }
  #wand.busy svg { animation: wandspin 1s linear infinite; }
  @keyframes wandspin { to { transform: rotate(360deg); } }
  /* A tapback folded onto the bubble it reacted to. */
  .tap {
    position: absolute; bottom: -10px; font-size: 12px; line-height: 1;
    padding: 3px 6px; border-radius: 999px;
    background: var(--surface-2);
    border: 1px solid var(--border); box-shadow: 0 1px 2px rgba(0,0,0,.08);
    z-index: 1; pointer-events: none;
  }
  .msg.out .tap { left: -6px; }
  .msg.in .tap { right: -6px; }
  .msg.hastap { margin-bottom: 12px; }
  /* A message that exists but has not left yet. */
  .msg.sched .bubble {
    background: transparent; border: 1.5px dashed var(--border);
    color: var(--text);
  }
  /* What the first link in a message points at, once the server has
     looked: a title, the site, a line of description — no image, because
     img-src is 'self' and a preview is not worth widening that. */
  .linkcard {
    display: block; max-width: 320px; margin: 4px 0 2px;
    padding: 10px 12px; border-radius: 14px;
    background: var(--surface-2); border: 1px solid var(--border);
    color: var(--text); text-decoration: none; font-size: 13px;
  }
  .linkcard:hover { background: var(--hover); }
  .linkcard b { display: block; font-weight: 600; line-height: 1.3;
                overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2;
                -webkit-box-orient: vertical; }
  .linkcard .lc-desc { display: block; color: var(--text-2); margin-top: 3px;
                       overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2;
                       -webkit-box-orient: vertical; }
  .linkcard .lc-host { display: block; margin-top: 5px; color: var(--text-2);
                       font: 500 10.5px var(--mono); letter-spacing: .06em;
                       text-transform: uppercase; }
  .schedmeta { font-size: 11px; color: var(--text-2);
               margin: 4px 2px 6px; display: flex; gap: 10px; align-items: center; }
  .schedmeta.bad { color: var(--danger); }
  .schedmeta button {
    border: 0; background: none; color: var(--primary); font: inherit;
    font-size: 11px; font-weight: 500; cursor: pointer; padding: 0;
  }
  .transcript {
    font-size: 13px; color: var(--text-2); max-width: 280px;
    margin: 4px 6px 2px; font-style: italic;
  }
  /* Seated in the meta row, START of the `when` cell — the timestamp
     keeps the end. A grid child with NO area auto-places into a phantom
     extra row, which is exactly what this button used to do: an
     invisible band of dead space under every untranscribed note (and
     invisible twice over on our own bubbles, where --primary text sat
     on the --primary bubble). It writes in the bubble's own ink now. */
  .vn-tx { grid-area: when; justify-self: start; align-self: center;
           border: 0; background: none; color: inherit; opacity: .8;
           font: inherit; font-size: 11px; font-weight: 600;
           cursor: pointer; padding: 2px 8px 2px 0; }
  .composer textarea {
    flex: 1; border: 0; background: transparent; outline: none;
    resize: none; padding: 8px 0; max-height: 120px; line-height: 1.4;
  }
  /* Held, not tapped: the browser must not select text, scroll the
     thread, or raise a long-press menu under a finger that is recording. */
  @media print {
    /* "Print conversation" means the CONVERSATION: no rails, no composer,
       no buttons — the messages, flowing, however many pages they take. */
    nav, section.list, .thread-head .icon-btn, .composer, .fab, .jump,
    .selbar, #wall, .vn-tx, .schedmeta button { display: none !important; }
    section.thread { display: flex !important; }
    .messages { overflow: visible !important; height: auto !important; }
    body { background: #fff; }
  }
  #mic { touch-action: none; -webkit-user-select: none; user-select: none;
         -webkit-touch-callout: none; }
  #mic.holding { color: var(--danger); transform: scale(1.25); }
  .recbar.cancelling { color: var(--danger); }
  .recbar.cancelling .rechint { color: var(--danger); }
  .recbar.cancelling .livewave .bar { background: var(--danger); }

  .send {
    width: 40px; height: 40px; flex: none;
    display: grid; place-items: center;
    border: 0; border-radius: 50%;
    background: transparent; color: var(--text-2);
    cursor: pointer;
  }
  .send.ready { background: var(--primary); color: var(--on-primary); }
  .send:disabled { cursor: default; }
  .wall {
    flex: none; margin: 0 20px 14px; padding: 14px 16px;
    border-radius: 14px; background: var(--note-bg);
    color: var(--note-text); font-size: 13px; line-height: 1.45;
  }
  .wall .btn.text { margin: 8px 0 0 -12px; color: var(--note-text); }

  /* ---------- settings ---------- */
  .settings { flex: 1; overflow-y: auto; }
  body.settings-open section.list { display: none; }
  .settings .inner { max-width: 720px; margin: 0 auto; padding: 32px 24px 64px; }
  .settings h2 { font-size: 22px; font-weight: 400; margin: 0 0 24px; }

  /* Android-Settings shape: a home of category rows that open detail
     pages, each with a back arrow and sub-section headers. */
  .cat-card, .cat-row {
    display: flex; align-items: center; gap: 16px; width: 100%;
    text-align: left; background: none; border: 0; cursor: pointer;
    color: var(--text); font: inherit; padding: 14px 8px;
    border-radius: 12px;
  }
  .cat-card { padding: 16px; background: var(--surface-2); margin-bottom: 8px; }
  .cat-card:hover, .cat-row:hover { background: var(--surface-2); }
  .cat-ic {
    flex: none; width: 40px; height: 40px; border-radius: 50%;
    display: grid; place-items: center;
    background: color-mix(in srgb, var(--primary) 16%, transparent);
  }
  .cat-ic svg { width: 22px; height: 22px; fill: var(--primary); }
  .cat-body { flex: 1; min-width: 0; }
  .cat-body b { display: block; font-weight: 500; font-size: 15px; }
  .cat-body > span {
    display: block; color: var(--text-2); font-size: 13px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .cat-chev { width: 22px; height: 22px; fill: var(--text-2); flex: none; }
  .cat-head { display: flex; align-items: center; gap: 6px; margin: 0 0 8px; }
  .cat-head h2 { margin: 0; }
  .cat-back {
    background: none; border: 0; cursor: pointer; padding: 6px;
    display: grid; place-items: center; border-radius: 50%; color: var(--text);
  }
  .cat-back:hover { background: var(--surface-2); }
  .cat-back svg { width: 24px; height: 24px; fill: currentColor; }
  .subhead {
    font-size: 12px; font-weight: 600; text-transform: uppercase;
    letter-spacing: .8px; color: var(--primary); margin: 24px 0 0;
  }
  .subhead:first-child { margin-top: 4px; }

  .group { margin-bottom: 40px; }
  .group > h3 {
    font-size: 13px; font-weight: 500; text-transform: uppercase;
    letter-spacing: .8px; color: var(--text-2);
    margin: 0 0 4px; padding-bottom: 8px;
    border-bottom: 1px solid var(--border);
  }
  .setting {
    display: flex; align-items: center; gap: 24px;
    padding: 18px 0;
    border-bottom: 1px solid var(--border);
  }
  .setting .label { flex: 1; min-width: 0; }
  .setting .label b { display: block; font-weight: 500; }
  .setting .label span { color: var(--text-2); font-size: 13px; }
  .setting .control { flex: none; }
  select.control, .setting select {
    height: 36px; padding: 0 10px;
    border: 1px solid var(--border); border-radius: 4px;
    background: var(--surface);
  }
  .switch {
    width: 36px; height: 14px; border-radius: 7px;
    background: var(--border); position: relative; cursor: pointer;
    border: 0; padding: 0;
  }
  .switch::after {
    content: ""; position: absolute; top: -3px; left: 0;
    width: 20px; height: 20px; border-radius: 50%;
    background: var(--surface); box-shadow: var(--shadow);
    transition: left .15s;
  }
  .switch[aria-checked="true"] { background: color-mix(in srgb, var(--primary) 50%, transparent); }
  .switch[aria-checked="true"]::after { left: 16px; background: var(--primary); }
  .pwform { padding: 8px 0 20px; display: none; }
  .pwform.open { display: block; }
  .pwform .field { max-width: 380px; }
  .chips { display: flex; flex-wrap: wrap; gap: 8px; }
  .chip {
    padding: 6px 12px; border-radius: 16px;
    border: 1px solid var(--border); font-size: 13px; color: var(--text-2);
  }

  /* ---------- dialog ---------- */
  dialog {
    border: 0; border-radius: 8px; padding: 0;
    background: var(--surface); color: var(--text);
    box-shadow: var(--shadow); max-width: 440px; width: calc(100% - 48px);
  }
  dialog::backdrop { background: rgba(0,0,0,.5); }
  dialog .dlg { padding: 24px; }
  dialog h3 { margin: 0 0 20px; font-size: 18px; font-weight: 500; }
  dialog .actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 12px; }
  dialog textarea {
    width: 100%; min-height: 96px; resize: vertical;
    padding: 12px 14px; border: 1px solid var(--border);
    border-radius: 4px; background: transparent; outline: none;
  }
  #lightbox { max-width: 92vw; background: transparent; box-shadow: none; }
  #lightbox img { max-width: 92vw; max-height: 88vh; display: block; border-radius: 8px; }

  .toast {
    position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%);
    background: var(--toast-bg); color: var(--toast-text); padding: 14px 20px;
    border-radius: 4px; max-width: calc(100% - 32px); text-align: center;
    font-size: 13px; box-shadow: var(--shadow); z-index: 10;
  }

  /* ---------- phone ---------- */
  @media (max-width: 860px) {
    nav.rail { display: none; }
    section.list { width: 100%; border-right: 0; }
    section.newchat { width: 100%; border-right: 0; }
    section.thread { display: none; }
    .search { max-width: none; }
    /* The wordmark is the first thing to go on a phone. There is not
       room for "Messages", a search field, and the two buttons at once,
       and of those four the search field is the one that has to stay
       usable — the icon beside it already says which app this is. */
    .brand span { display: none; }
    .brand { margin-right: 0; }
    .bar .spacer { display: none; }
    body.viewing section.list { display: none; }
    body.viewing section.thread { display: flex; }
    body.viewing header.bar { display: none; }
    /* Picking who to text takes the whole phone, exactly as it does on
       the phone: no app bar above it, no list behind it. */
    body.composing header.bar { display: none; }
    .thread-head .back { display: grid; }
    .msg { max-width: 82%; }
    .messages { padding: 16px 12px 4px; }
    .composer { padding: 8px 12px 14px; }
  }

/* ---------- the read-only support view ---------- */
/* An operator looking over the workspace's shoulder: one unmissable
   banner, and the acting tools put away. The SERVER refuses every
   mutation regardless — this is honesty, not enforcement. */
#support-banner {
  background: var(--warn-soft, #F6EFDF); color: var(--warn, #A56A00);
  text-align: center; font-size: 13px; font-weight: 600;
  padding: 8px 14px; position: sticky; top: 0; z-index: 60;
}
body.readonly #composer,
body.readonly #compose { display: none !important; }

/* ---- softphone: in-call overlay + dialer ---- */
/* The in-call view owns the screen and is dark in either theme, the same
 * choice the native app makes: a call is a mode, not a page. The layout
 * is the native InCallScreen verbatim: a held call's card at the top,
 * a knocking caller's card under it, the person centered over a soft
 * glow, the frosted control grid, and the hang-up pill. */
/* A call is a mode, not a page: the call screen and the dialer keep the
   night palette whichever theme the page wears, so the tokens their
   parts read are pinned to the dark values here. */
dialog.incall {
  color-scheme: dark;
  --surface: #0b0d10; --surface-2: #14171c;
  --hover: rgba(255,255,255,.07); --glass: rgba(255,255,255,.05);
  --glass-2: rgba(255,255,255,.08);
  --text: #eef1f5; --text-2: rgba(235,240,248,.55);
  --border: rgba(255,255,255,.08);
  --primary: #3fd39a; --on-primary: #06231a;
  --primary-soft: rgba(63,211,154,.14);
  --selected: rgba(63,211,154,.16); --selected-text: #bff0dd;
  --danger: #e5484d; --note-bg: #3a3323; --note-text: #fdd663;
}
dialog.incall {
  max-width: none; max-height: none;
  width: 100%; height: 100dvh; margin: 0; border-radius: 0;
  background: linear-gradient(180deg, #0d1017, #0b0d13 55%, #090b10);
  color: #f2f4f8;
  flex-direction: column; padding: 0; border: 0;
  position: relative; overflow: hidden;
}
/* Same [open] discipline as the dialer: a closed call screen must not
   keep covering the page. */
dialog.incall[open] { display: flex; }
dialog.incall::backdrop { background: #090b10; }
@media (min-width: 861px) {
  dialog.incall {
    width: 400px; height: min(760px, calc(100dvh - 48px));
    margin: auto; border-radius: 28px;
  }
  dialog.incall::backdrop { background: rgba(6, 8, 12, .86); }
}
/* The soft bloom behind the caller. */
dialog.incall::before {
  content: ""; position: absolute; inset: 0 0 auto; height: 430px;
  background: radial-gradient(ellipse at 50% 30%,
    rgba(63, 211, 154, .16), transparent 70%);
  pointer-events: none;
}
.incall-scene {
  position: relative; display: flex; flex-direction: column;
  align-items: center; flex: 1; min-height: 0; width: 100%;
  padding: 14px 24px 0;
}
.held-card, .wait-card {
  display: flex; align-items: center; gap: 12px; width: 100%;
  border-radius: 22px; padding: 12px 14px; margin-bottom: 10px;
  background: rgba(255,255,255,.05);
  border: 1px solid rgba(255,255,255,.078);
}
.wait-card {
  background: rgba(52,158,82,.08); border-color: rgba(61,193,99,.24);
}
.held-card .avatar { width: 40px; height: 40px; font-size: 16px; flex: none; }
.held-meta {
  flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px;
}
.held-name {
  font-size: 15px; font-weight: 700; color: #f2f4f8;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.held-sub { font-size: 12px; color: rgba(235,240,248,.38); }
.swap-pill {
  display: inline-flex; align-items: center; gap: 6px; flex: none;
  border-radius: 999px; padding: 9px 14px; cursor: pointer;
  background: var(--selected); border: 1px solid rgba(63,211,154,.3);
  color: var(--primary); font-size: 13px; font-weight: 700;
}
.swap-pill svg { width: 16px; height: 16px; fill: currentColor; }
.incall-id {
  flex: 1; min-height: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center;
}
.incall-avatar {
  width: 116px; height: 116px; border-radius: 50%;
  background: rgba(255,255,255,.08); color: #bff0dd;
  display: flex; align-items: center; justify-content: center;
  margin-bottom: 22px; position: relative; font-weight: 600;
}
.incall-avatar svg { width: 64px; height: 64px; fill: currentColor; }
/* The design's green pulse ring around the caller. */
.incall-avatar::after {
  content: ""; position: absolute; inset: 0; border-radius: 50%;
  border: 1.5px solid rgba(63,211,154,.7); pointer-events: none;
  animation: incall-pulse 2.4s ease-out infinite;
}
@keyframes incall-pulse {
  0% { transform: scale(1); opacity: .6; }
  70% { transform: scale(1.55); opacity: 0; }
  100% { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .incall-avatar::after { animation: none; opacity: .45; }
}
/* Call-quality chip under the timer. */
.incall-quality {
  display: inline-flex; align-items: center; gap: 8px; margin-top: 14px;
  padding: 7px 14px; border-radius: 999px; background: rgba(255,255,255,.07);
  font: 500 10.5px var(--mono); letter-spacing: .08em; text-transform: uppercase;
  color: rgba(235,240,248,.72);
}
.incall-quality .q-dot {
  width: 6px; height: 6px; border-radius: 50%; background: var(--primary);
}
.incall-chips { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
                justify-content: center; }
/* The socket under the call is being brought back. */
.incall-quality.reconnecting .q-dot { background: var(--note-text);
                                      animation: pulse 1.2s infinite; }
/* The recording indicator: a small red-dot chip, never hidden by a
   setting — being recorded is not a preference. */
.incall-rec {
  display: inline-flex; align-items: center; gap: 7px; margin-top: 14px;
  padding: 7px 12px; border-radius: 999px;
  background: rgba(229,72,77,.16); border: 1px solid rgba(229,72,77,.35);
  font: 700 10.5px var(--mono); letter-spacing: .12em; color: #ffb4b6;
}
.incall-rec .rec-dot { width: 7px; height: 7px; border-radius: 50%;
                       background: #ff5c61; animation: pulse 1.6s infinite; }
.incall-name { font-size: 28px; font-weight: 700; text-align: center; }
.incall-number {
  font-size: 16px; color: rgba(235,240,248,.62); margin-top: 8px;
}
.incall-status {
  font-size: 15px; color: rgba(235,240,248,.38); margin-top: 8px;
  min-height: 20px; text-align: center;
}
.incall-status.timer { color: var(--primary); font-weight: 700; }
.incall-status.failed { color: var(--danger); }
/* Conference mode: the identity shrinks and the room's people take the
   middle of the screen. */
.incall-scene.conf .incall-id { flex: none; padding: 8px 0 12px; }
.incall-scene.conf .incall-avatar { display: none; }
.incall-scene.conf .incall-name { font-size: 24px; }
.conf-list {
  flex: 1; min-height: 0; width: 100%; overflow-y: auto;
  display: flex; flex-direction: column; gap: 8px; padding-bottom: 10px;
}
.conf-row {
  display: flex; align-items: center; gap: 12px;
  border-radius: 20px; padding: 10px 12px;
  background: rgba(255,255,255,.043);
  border: 1px solid rgba(255,255,255,.059);
}
.conf-row .avatar { width: 38px; height: 38px; font-size: 15px; flex: none; }
.conf-row .round.small { background: rgba(255,255,255,.08); }
.conf-row .round.small.on,
.conf-row .round.small.kick { background: rgba(242,139,130,.2); }
.incall-foot {
  width: 100%; display: flex; flex-direction: column; align-items: center;
  padding: 0 24px max(30px, env(safe-area-inset-bottom));
}
.ring-block, .ctrl-block {
  width: 100%; display: flex; flex-direction: column; align-items: center;
}
.scene-pill {
  display: inline-flex; align-items: center; gap: 8px;
  border-radius: 999px; padding: 11px 18px; margin-bottom: 34px;
  background: rgba(255,255,255,.055);
  border: 1px solid rgba(255,255,255,.078);
  color: #f2f4f8; font-size: 13px; cursor: pointer;
}
.scene-pill svg { width: 17px; height: 17px; fill: currentColor; }
.ring-row {
  width: 100%; display: flex; justify-content: space-between;
  padding: 0 18px; margin-bottom: 10px;
}
.biground {
  display: flex; flex-direction: column; align-items: center; gap: 10px;
}
.biground > span { font-size: 13px; color: rgba(235,240,248,.62); }
.round {
  width: 64px; height: 64px; border-radius: 50%; border: 0;
  background: #3c4043; color: #fff; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  flex: none;
}
.round svg { width: 28px; height: 28px; fill: currentColor; }
.round.answer { background: linear-gradient(135deg, #3dc163, #1e9e4a); }
.round.hangup { background: linear-gradient(135deg, #f0574c, #d93025); }
.round.active { background: #e8eaed; color: #202124; }
.round.big { width: 78px; height: 78px; }
.round.big svg { width: 34px; height: 34px; }
.round.small { width: 40px; height: 40px; }
.round.small svg { width: 19px; height: 19px; }
.round:hover { filter: brightness(1.12); }
/* The frosted control tiles, three to a row like the native grid. */
.tile-row { width: 100%; display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-bottom: 12px; }
.glass-tile {
  flex: 1; min-width: 0; display: flex; flex-direction: column;
  align-items: center; gap: 8px; border: 0; background: none;
  color: inherit; cursor: pointer; padding: 0; font: inherit;
}
.tile-box {
  width: 100%; height: 68px; border-radius: 24px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(255,255,255,.067);
  border: 1px solid rgba(255,255,255,.078);
}
.tile-box svg { width: 26px; height: 26px; fill: #f2f4f8; }
.glass-tile:hover .tile-box { background: rgba(255,255,255,.1); }
/* A control the browser can't honor (Speaker where output can't be routed)
   reads as unavailable — dimmed, but still tappable so a tap can say why. */
.glass-tile.unavailable { opacity: .4; }
.glass-tile.unavailable:hover .tile-box { background: rgba(255,255,255,.067); }
.tile-label { font-size: 12px; color: rgba(235,240,248,.62); }
.glass-tile.on .tile-box { background: #e8eaed; border-color: #e8eaed; }
.glass-tile.on .tile-box svg { fill: #17191e; }
.glass-tile.accent .tile-box {
  background: var(--selected); border-color: rgba(63,211,154,.34);
}
.glass-tile.accent .tile-box svg { fill: var(--primary); }
.glass-tile.accent .tile-label { color: var(--primary); font-weight: 700; }
.end-pill {
  width: 78px; height: 78px; border-radius: 50%; border: 0;
  background: linear-gradient(135deg, #f0574c, #d93025); color: #fff;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; margin-top: 10px; flex: none;
}
.end-pill svg { width: 30px; height: 30px; fill: currentColor; }
.end-pill:hover { filter: brightness(1.12); }
.wide-pill {
  width: 200px; height: 60px; border-radius: 30px; border: 0;
  background: linear-gradient(135deg, #2a2f3a, #232833); color: #f2f4f8;
  font-size: 16px; font-weight: 700; cursor: pointer; margin-top: 10px;
}
.wide-pill.go {
  width: 100%; max-width: 280px; height: 54px; border-radius: 27px;
  background: linear-gradient(135deg, #3dc163, #1e9e4a); color: #fff;
  margin-top: 14px;
}
/* ---- the sheets over a call: keypad (DTMF), a number to add or
   transfer to, the decline texts. Native's SheetScrim, bottom-anchored. */
.sheet-scrim {
  position: absolute; inset: 0; background: rgba(6,8,12,.6); z-index: 5;
}
.call-sheet {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 6;
  display: flex; flex-direction: column; align-items: center;
  background: #14181f; border-radius: 28px 28px 0 0;
  padding: 10px 26px calc(24px + env(safe-area-inset-bottom));
}
.sheet-grip {
  width: 42px; height: 4px; border-radius: 2px;
  background: rgba(255,255,255,.22); margin-bottom: 14px; flex: none;
}
.sheet-title { font-size: 16px; font-weight: 700; margin-bottom: 12px; }
.sheet-sub {
  font-size: 12px; color: rgba(235,240,248,.38); margin-bottom: 14px;
}
.dtmf-typed {
  font-size: 30px; font-weight: 700; letter-spacing: 5px; min-height: 38px;
  max-width: 100%; overflow: hidden; white-space: nowrap;
}
.sheet-keys {
  padding: 0; grid-template-columns: repeat(3, 64px); gap: 10px 22px;
}
.sheet-keys .dial-key {
  width: 64px; height: 64px; font-size: 22px; border-radius: 22px;
  border: 1px solid rgba(255,255,255,.078);
}
.sheet-link {
  border: 0; background: none; color: var(--primary); font-size: 14px;
  font-weight: 700; cursor: pointer; margin-top: 14px; padding: 6px 10px;
}
/* "Transfer to a contact": the book, searched from inside the sheet. */
.num-search { width: 100%; max-width: 300px; position: relative; margin-bottom: 6px; }
.num-search input {
  width: 100%; height: 38px; padding: 0 14px; border-radius: 999px;
  border: 1px solid rgba(255,255,255,.1); background: rgba(255,255,255,.06);
  color: #f2f4f8; outline: none; font-size: 14px;
}
.num-search input::placeholder { color: rgba(235,240,248,.4); }
.num-matches { display: flex; flex-direction: column; gap: 4px; margin-top: 6px;
               max-height: 150px; overflow-y: auto; }
.num-matches:empty { display: none; }
.num-matches button {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; text-align: left; border: 0; border-radius: 12px;
  padding: 9px 12px; cursor: pointer; font: inherit;
  background: rgba(255,255,255,.06); color: #f2f4f8; font-size: 13.5px;
}
.num-matches button span { color: rgba(235,240,248,.55); font: 400 11.5px var(--mono); }
.num-matches button:hover { background: rgba(255,255,255,.1); }
.num-row {
  display: flex; align-items: center; gap: 10px;
  margin-bottom: 10px; min-height: 40px;
}
.num-display { font-size: 24px; font-weight: 700; }
.num-display.empty { color: rgba(235,240,248,.38); }
.num-row .icon-btn svg { fill: rgba(235,240,248,.62); }
.reply-list { width: 100%; display: flex; flex-direction: column; gap: 8px; }
.reply-row {
  text-align: left; border-radius: 18px; padding: 14px 16px; cursor: pointer;
  background: rgba(255,255,255,.067);
  border: 1px solid rgba(255,255,255,.078);
  color: #f2f4f8; font-size: 14px; font-family: inherit;
}
.reply-row:hover { background: rgba(255,255,255,.1); }

/* The dialer is the native DialpadScreen, verbatim: a full scene on a
   phone, a tall rounded card on a desktop — back arrow + "New call",
   two recents as avatar chips, the number huge and centered in the
   breathing room, circular keys with their letters, the green call
   button with backspace beside it. */
.dialpad {
  max-width: none; max-height: none;
  width: 100%; height: 100dvh; margin: 0; border-radius: 0;
  background: linear-gradient(180deg, #12161f, #0b0d13);
  color: var(--text);
  flex-direction: column;
}
/* Only while OPEN — an unconditional display would override the UA's
   dialog:not([open]) { display:none } and leave a closed dialer
   covering the whole page. */
.dialpad[open] { display: flex; }
.dialpad::backdrop { background: rgba(6, 8, 12, .86); }
@media (min-width: 861px) {
  .dialpad {
    width: 400px; height: min(760px, calc(100dvh - 48px));
    margin: auto; border-radius: 28px;
  }
}
.dialpad .dial-head {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 16px 0 8px;
}
/* The line you're calling from — the design's green dot + MAIN · number. */
.dial-line {
  display: inline-flex; align-items: center; gap: 9px;
  font: 500 12px/1 var(--mono); letter-spacing: .06em;
  color: rgba(235,240,248,.82);
}
.dial-dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--primary);
  flex: none;
}
/* The number sits low, just above the keys, left-aligned like the mock. */
.dial-display {
  flex: 1; min-height: 0; display: flex; flex-direction: column;
  justify-content: flex-end; padding: 0 26px 22px;
}
.dial-num {
  width: 100%; border: 0; outline: 0; background: transparent;
  color: var(--text); font: 500 42px/1 var(--ui);
  text-align: left; padding: 0; letter-spacing: -.02em;
}
.dial-num::placeholder { color: rgba(235,240,248,.3); font-weight: 500; }
.dial-sub {
  font: 400 12.5px var(--mono); letter-spacing: .04em;
  color: rgba(235,240,248,.42); margin-top: 9px; min-height: 15px;
  text-transform: uppercase;
}
/* A sentence, not a label: the emergency notice keeps its own case. */
.dial-sub.warn {
  font: 500 13px/1.35 var(--ui); letter-spacing: 0; text-transform: none;
  color: #fdd663;
}
.dial-keys {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 12px; padding: 0 22px;
}
.dial-key {
  height: 70px; border: 0; border-radius: 24px;
  background: rgba(255,255,255,.06); color: var(--text);
  font: 400 27px/1 var(--ui); cursor: pointer;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 2px;
}
.dial-key small {
  font: 500 8.5px/1 var(--mono); letter-spacing: .16em;
  color: rgba(235,240,248,.38); min-height: 9px;
}
.dial-key:hover { background: rgba(255,255,255,.1); }
.dial-key:active { background: rgba(255,255,255,.14); }
/* The quick-dial row: favorites as avatar chips above the number. */
.dial-favs {
  display: flex; gap: 14px; padding: 18px 26px 0; overflow-x: auto;
  scrollbar-width: none; flex: none;
}
.dial-favs::-webkit-scrollbar { display: none; }
.dial-favs button {
  flex: none; display: flex; flex-direction: column; align-items: center; gap: 6px;
  width: 64px; border: 0; background: none; color: var(--text-2);
  font: 500 11px var(--ui); cursor: pointer; padding: 0;
}
.dial-favs button .avatar { width: 46px; height: 46px; border-radius: 16px; }
.dial-favs button span:last-child {
  max-width: 64px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dial-favs button:hover { color: var(--text); }
.dial-rec {
  text-align: center; padding: 12px 24px 0;
  font: 500 10.5px var(--mono); letter-spacing: .1em; text-transform: uppercase;
  color: #ffb4b6;
}
.dial-foot {
  display: flex; align-items: center; justify-content: center;
  padding: 22px 0 max(24px, env(safe-area-inset-bottom));
}
.dial-side { width: 74px; display: flex; justify-content: center; }
.dial-foot .round { width: 78px; height: 78px; margin: 0 26px; }
.dial-foot .round svg { width: 30px; height: 30px; }
/* The design's soft glow ring around the green call button. */
.dial-call { box-shadow: 0 0 0 10px rgba(63,211,154,.12); }
.dial-call:hover { box-shadow: 0 0 0 10px rgba(63,211,154,.18); }

  /* ---------- the phone tabs (Calls / Contacts / Voicemail), v2.8 ---- */
  .phonepane {
    flex: 1; min-width: 0; min-height: 0;
    position: relative;
    display: none; flex-direction: column;
    background: transparent;
  }
  body.tab-calls #callspane,
  body.tab-detail #calldetail,
  body.tab-contacts #contactspane,
  body.tab-voicemail #vmpane { display: flex; }
  body.tab-calls section.list, body.tab-calls section.thread,
  body.tab-detail section.list, body.tab-detail section.thread,
  body.tab-contacts section.list, body.tab-contacts section.thread,
  body.tab-voicemail section.list, body.tab-voicemail section.thread {
    display: none;
  }
  .pane-head {
    flex: none;
    display: flex; align-items: baseline; justify-content: space-between;
    padding: 14px 18px 8px;
    font: 600 32px var(--ui); letter-spacing: -.03em; color: var(--text);
  }
  /* A quiet link in the phone header — e.g. "Voicemail" under the Phone tab. */
  .head-link {
    border: 0; background: none; cursor: pointer;
    font: 500 13px var(--ui); color: var(--primary);
    padding: 6px 4px;
  }
  .chiprow {
    flex: none;
    display: flex; gap: 8px;
    padding: 4px 16px 10px;
  }
  .chip {
    border: 0;
    background: var(--glass-2);
    color: var(--text-2);
    font: 500 12.5px var(--ui);
    padding: 7px 15px;
    border-radius: 999px;
    cursor: pointer;
  }
  .chip[aria-selected="true"] { background: var(--nav-on); color: var(--nav-on-text); font-weight: 600; }
  .daylabel {
    padding: 12px 18px 4px;
    font: 500 10px var(--mono); letter-spacing: .14em;
    text-transform: uppercase; color: var(--text-2);
  }
  /* Recents and contacts are rounded Nocturne cards. */
  #call-rows, #contact-rows {
    padding: 8px 12px 14px;
    display: flex; flex-direction: column; gap: 8px;
  }
  .callrow, .contactrow {
    display: flex; gap: 13px; align-items: center;
    width: 100%;
    padding: 13px 14px;
    border: 0; text-align: left; color: var(--text);
    cursor: pointer;
    background: var(--glass); border-radius: 20px;
  }
  .callrow:hover, .contactrow:hover { background: var(--hover); }
  .callrow .avatar, .contactrow .avatar { border-radius: 14px; }
  .callrow .who, .contactrow .who { flex: 1; min-width: 0; }
  .callrow .who b, .contactrow .who b {
    display: block; font: 600 15px var(--ui); color: var(--text);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .callrow.missed .who b { color: var(--missed); }
  .callrow .what, .contactrow .what {
    display: flex; align-items: center; gap: 5px;
    font-size: 12.5px; color: var(--text-2); margin-top: 3px;
  }
  .contactrow .what { font: 400 11.5px var(--mono); }
  .contactrow .notes {
    font: 400 12px var(--ui); color: var(--text-2); margin-top: 2px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .callrow .what svg { width: 14px; height: 14px; }
  .callrow.missed .what svg { color: var(--missed); }
  .callrow time { font: 500 11.5px var(--mono); color: var(--text-2); flex: none; }
  .ghostbtn {
    flex: none;
    width: 38px; height: 38px; border-radius: 50%;
    border: 0; padding: 0; cursor: pointer;
    background: var(--selected); color: var(--primary);
    display: grid; place-items: center;
  }
  .ghostbtn:hover { filter: brightness(1.15); }
  .ghostbtn svg { width: 18px; height: 18px; }
  .ghostbtn.quiet { background: var(--glass-2); color: var(--text-2); }

  /* ---------- favorites ---------- */
  .favstrip {
    flex: none; display: flex; gap: 14px; padding: 4px 18px 12px;
    overflow-x: auto; scrollbar-width: none;
    width: 100%; max-width: 880px; margin: 0 auto;
  }
  .favstrip::-webkit-scrollbar { display: none; }
  .favstrip button {
    flex: none; display: flex; flex-direction: column; align-items: center; gap: 6px;
    width: 66px; border: 0; background: none; color: var(--text-2);
    font: 500 11.5px var(--ui); cursor: pointer; padding: 0;
  }
  .favstrip button .avatar { width: 50px; height: 50px; border-radius: 18px; }
  .favstrip button span:last-child {
    max-width: 66px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .favstrip button:hover { color: var(--text); }

  /* ---------- voicemail ---------- */
  #vm-rows { padding: 8px 12px 14px; display: flex; flex-direction: column; gap: 8px; }
  .vmrow {
    display: flex; flex-direction: column; gap: 10px;
    padding: 13px 14px; border-radius: 20px;
    background: var(--glass); color: var(--text);
  }
  .vmrow.unheard { background: var(--glass-2); }
  .vm-head { display: flex; gap: 13px; align-items: center; }
  .vm-head .avatar { border-radius: 14px; }
  .vm-head .who { flex: 1; min-width: 0; }
  .vm-head .who b {
    display: block; font: 600 15px var(--ui);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .vm-head .who .what { font: 400 11.5px var(--mono); color: var(--text-2); margin-top: 3px; }
  .vm-head .dot { flex: none; }
  .vm-play {
    display: flex; align-items: center; gap: 10px;
  }
  .vm-play audio { flex: 1; min-width: 0; height: 36px; }
  .vm-actions { display: flex; gap: 8px; flex-wrap: wrap; }
  .vm-actions .btn { height: 32px; padding: 0 14px; font-size: 13px; }
  .vm-actions .spacer { flex: 1; }
  .vm-actions .btn.text.danger { color: var(--danger); }

  /* ---------- the sending cap, on the composer ---------- */
  .limitline {
    margin: 0 0 8px; padding: 8px 14px; border-radius: 12px;
    font-size: 12.5px; line-height: 1.4;
    background: var(--note-bg); color: var(--note-text);
  }
  .limitline.stop { background: var(--danger); color: #fff; }

  /* ---------- appearance: the segmented choice ---------- */
  .segmented {
    display: inline-flex; padding: 3px; border-radius: 999px;
    background: var(--glass-2); border: 1px solid var(--border);
  }
  .segmented button {
    border: 0; background: transparent; color: var(--text-2);
    font: 500 13px var(--ui); padding: 7px 14px; border-radius: 999px;
    cursor: pointer;
  }
  .segmented button[aria-pressed="true"] { background: var(--nav-on); color: var(--nav-on-text); }

  /* ---------- auto-replies ---------- */
  .ar-days { display: flex; flex-direction: column; gap: 6px; margin: 4px 0 8px; }
  .ar-day {
    display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px;
    padding: 8px 10px; border-radius: 12px; background: var(--glass);
  }
  .ar-day .day { width: 44px; font: 600 12px var(--mono); letter-spacing: .06em;
                 text-transform: uppercase; color: var(--text); }
  .ar-day label { display: inline-flex; align-items: center; gap: 6px;
                  font-size: 13px; color: var(--text-2); cursor: pointer; }
  .ar-day .times { display: inline-flex; align-items: center; gap: 8px;
                   margin-left: auto; }
  .ar-day input[type="time"] {
    height: 32px; padding: 0 6px; border: 1px solid var(--border);
    border-radius: 8px; background: var(--surface); color: var(--text);
    min-width: 0; width: 118px;
  }
  .ar-day .to { color: var(--text-2); font-size: 12px; }
  .ar-day.closed input[type="time"], .ar-day.closed .to { opacity: .35; }
  .ar-block { padding: 12px 0; border-bottom: 1px solid var(--border); }
  .ar-block > label { display: block; margin-bottom: 8px; }
  .ar-block b { display: block; font-weight: 500; }
  .ar-block > label span, .ar-hint { display: block; color: var(--text-2); font-size: 13px; }
  .ar-block textarea, .ar-block > input {
    width: 100%; padding: 10px 12px; border: 1px solid var(--border);
    border-radius: 8px; background: var(--surface); color: var(--text);
    outline: none; font: inherit; resize: vertical;
  }
  .ar-block textarea:focus, .ar-block > input:focus { border-color: var(--primary); }
  .ar-keywords { display: flex; flex-direction: column; gap: 8px; margin: 10px 0 4px; }
  .ar-kw { display: flex; gap: 8px; align-items: center; }
  .ar-kw input {
    height: 36px; padding: 0 10px; border: 1px solid var(--border);
    border-radius: 8px; background: var(--surface); color: var(--text); outline: none;
    min-width: 0;
  }
  .ar-kw input:focus { border-color: var(--primary); }
  .ar-kw .kw-word { width: 120px; flex: none; font-family: var(--mono); text-transform: uppercase; }
  .ar-kw .kw-reply { flex: 1; }
  .ar-actions { display: flex; justify-content: flex-end; padding-top: 16px; }
  #ar-form.readonly input, #ar-form.readonly textarea, #ar-form.readonly .switch,
  #ar-form.readonly button { pointer-events: none; opacity: .7; }
  #ar-form.readonly .ar-actions, #ar-form.readonly #ar-kw-add,
  #ar-form.readonly .ar-kw .icon-btn { display: none; }

  /* ---------- blocked numbers ---------- */
  .blk-add { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; padding: 14px 0 6px; }
  .blk-list { display: flex; flex-direction: column; gap: 8px; padding-top: 8px; }
  .blk-row {
    display: flex; align-items: center; gap: 12px; padding: 10px 14px;
    border-radius: 14px; background: var(--glass);
  }
  .blk-row .who { flex: 1; min-width: 0; }
  .blk-row .who b { display: block; font: 500 14px var(--mono); }
  .blk-row .who span { display: block; color: var(--text-2); font-size: 12.5px;
                       overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* ---------- passkeys ---------- */
  .pk-list { display: flex; flex-direction: column; gap: 8px; padding: 4px 0 12px; }
  .pk-row {
    display: flex; align-items: center; gap: 12px; padding: 10px 14px;
    border-radius: 14px; background: var(--glass);
  }
  .pk-row .who { flex: 1; min-width: 0; }
  .pk-row .who b { display: block; font-weight: 500; }
  .pk-row .who span { display: block; color: var(--text-2); font-size: 12.5px; }
  .pk-add { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; padding: 4px 0 12px; }
  .passkey-row { display: flex; align-items: center; gap: 12px; margin-top: 22px; }
  .passkey-row .or { color: var(--text-2); font-size: 13px; }
  .passkey-row .btn svg { width: 18px; height: 18px; }

  /* ---------- E911 ---------- */
  .e911 {
    margin: 0 0 40px; padding: 14px 16px; border-radius: 14px;
    background: var(--note-bg); color: var(--note-text); font-size: 13px; line-height: 1.45;
  }
  .e911 b { display: block; margin-bottom: 4px; }

  /* ---------- the contact editor's two flags ---------- */
  .ct-flags { display: flex; gap: 8px; flex-wrap: wrap; margin: -6px 0 16px; }
  .ct-flags .flag {
    display: inline-flex; align-items: center; gap: 7px;
    border: 1px solid var(--border); background: transparent; color: var(--text-2);
    border-radius: 999px; padding: 7px 12px; font: inherit; font-size: 13px; cursor: pointer;
  }
  .ct-flags .flag svg { width: 16px; height: 16px; }
  .ct-flags .flag[aria-pressed="true"] { border-color: transparent; }
  #ct-fav[aria-pressed="true"] { background: var(--primary-soft); color: var(--star); }
  #ct-block[aria-pressed="true"] { background: var(--danger); color: #fff; }
  .field textarea {
    width: 100%; padding: 13px 15px; background: transparent;
    border: 1px solid var(--border); border-radius: 4px; outline: none;
    resize: vertical; min-height: 64px; font: inherit;
  }
  .field textarea:focus { border-color: var(--primary); box-shadow: inset 0 0 0 1px var(--primary); }
  .field textarea:focus + label { color: var(--primary); }

  /* ---------- one number's story (call detail) ---------- */
  .cd-top { flex: none; padding: 8px 6px 0; }
  #cd-body { padding-bottom: 24px; }
  .cd-hero {
    display: flex; flex-direction: column; align-items: center;
    padding: 4px 20px 18px;
    text-align: center;
  }
  .cd-hero .avatar {
    width: 84px; height: 84px; border-radius: 50%;
    display: grid; place-items: center;
    color: #fff; font-size: 34px; font-weight: 500;
  }
  .cd-hero b { font-size: 24px; font-weight: 700; margin-top: 12px; }
  .cd-hero span { font-size: 14px; color: var(--text-2); margin-top: 3px; }
  .cd-tiles { display: flex; gap: 14px; margin-top: 16px; }
  .cd-tile {
    display: flex; flex-direction: column; align-items: center; gap: 6px;
    border: 0; background: transparent; cursor: pointer;
    color: var(--text-2); font-size: 12px;
  }
  .cd-tile .tile {
    width: 60px; height: 60px; border-radius: 20px;
    background: var(--glass);
    display: grid; place-items: center;
    color: var(--text);
  }
  .cd-tile.prime .tile { background: var(--primary); color: var(--on-primary); }
  .cd-tile:hover .tile { background: var(--hover); }
  .cd-tile.prime:hover .tile { background: var(--primary); }
  .cd-stats { font-size: 13px; color: var(--text-2); margin-top: 14px; }
  .cd-row {
    display: flex; gap: 12px; align-items: center;
    padding: 8px 20px;
  }
  .cd-row .glyph {
    width: 40px; height: 40px; border-radius: 50%; flex: none;
    background: var(--glass);
    display: grid; place-items: center;
    color: var(--text-2);
  }
  .cd-row .glyph svg { width: 18px; height: 18px; }
  .cd-row.missed .glyph { color: var(--danger); }
  /* A call's recording, indented under its row's text. */
  .cd-rec { padding: 0 20px 8px 72px; }
  .cd-rec audio { display: block; width: 100%; max-width: 420px; height: 36px; }
  .cd-tile.on .tile { background: var(--primary-soft); color: var(--star); }
  .cd-tile.blocked .tile { background: var(--danger); color: #fff; }
  .cd-notes {
    font-size: 13px; color: var(--text-2); margin-top: 8px; max-width: 420px;
    white-space: pre-wrap; overflow-wrap: anywhere;
  }
  .cd-row .who { flex: 1; min-width: 0; }
  .cd-row .who b { display: block; font-size: 14.5px; font-weight: 500; }
  .cd-row .who span { font-size: 12.5px; color: var(--text-2); }
  .cd-row time { font-size: 12px; color: var(--text-2); }

  /* ---------- contacts ---------- */
  .letterhead {
    padding: 14px 20px 4px;
    font-size: 11px; font-weight: 600; letter-spacing: .1em;
    color: var(--text-2);
  }
  .vm-empty {
    flex: 1;
    display: flex; flex-direction: column; align-items: center;
    justify-content: center; gap: 8px;
    padding: 0 44px 60px; text-align: center;
  }
  .vm-empty svg { width: 52px; height: 52px; color: var(--text-2); }
  .vm-empty b { font-size: 17px; }
  .vm-empty span { font-size: 13.5px; color: var(--text-2); line-height: 1.45; }
  /* A quiet destructive action — "Remove", "Delete" — is red TEXT, not a
     red button: the solid .btn.danger rule above would otherwise paint
     red words on a red block and the label would vanish. */
  .btn.text.danger { background: transparent; color: var(--danger); }
  .btn.text.danger:hover:not(:disabled) { background: var(--hover); }

  /* The phone tabs read like the app on a phone; on a desktop their
   * content holds a comfortable column instead of stretching. */
  .pane-head, .chiprow, #calls-note, #vm-note, .phonepane .rows, .cd-top, #cd-body {
    width: 100%; max-width: 880px;
    margin-left: auto; margin-right: auto;
  }
  #vm-note, #calls-note { margin-top: 8px; width: calc(100% - 24px); }
  #cd-body { overflow-y: auto; }
  .phonepane .rows { overflow-y: auto; }
  @media (max-width: 860px) {
    body.viewing nav.bottomnav { display: none; }
    body.composing nav.bottomnav { display: none; }
    body.settings-open nav.bottomnav { display: none; }
  }


/* Responsive workspace. The phone keeps Android's floating pill; desktop
   uses the same controls in a compact floating sidebar. */
#app { height: 100dvh; min-height: 0; position: relative; }
#nav-voicemail {
  display: inline-flex; align-items: center; gap: 6px; position: relative;
  min-height: 40px; border: 1px solid var(--border); border-radius: 999px;
  padding: 7px 11px; font: 500 12px var(--ui); cursor: pointer;
  color: var(--text); background: var(--glass);
}
#nav-voicemail .pill { position: relative; }
#nav-voicemail svg { width: 18px; height: 18px; }
#nav-voicemail .navbadge { position: static; display: inline-block; margin-left: 3px; }
body.tab-keypad #keypadpane { display: flex; }
body.tab-keypad section.list, body.tab-keypad section.thread { display: none; }
#keypadpane { overflow-y: auto; }
.keypad-layout { width: 100%; max-width: 1040px; margin: 0 auto; display: flex; gap: 32px; padding: 16px 28px 28px; }
#dialpad {
  position: static; display: flex; flex: 0 1 400px; width: 100%; height: auto;
  min-height: 570px; max-height: none; margin: 0; border-radius: 28px;
  background: var(--surface); color: var(--text); border: 1px solid var(--border);
}
#dialpad .dial-head { padding-top: 16px; }
#dialpad .dial-display { min-height: 116px; }
#dialpad .dial-line { border: 0; background: transparent; cursor: pointer; padding: 8px; color: var(--text); }
#dialpad .dial-num { color: var(--text); font-size: clamp(26px, 7vw, 38px); }
#dialpad .dial-num::placeholder, #dialpad .dial-sub { color: var(--text-2); }
#dialpad .dial-key { background: var(--glass-2); color: var(--text); height: 64px; }
#dialpad .dial-key small { color: var(--text-2); font-size: 10px; }
#dialpad .dial-foot { padding: 22px 0 28px; }
#dialpad .dial-side { width: 50px; }
#dialpad .dial-back svg, #dial-back svg { fill: var(--text-2); }
.keypad-recents { flex: 1; min-width: 0; padding-top: 8px; }
.keypad-recents h2 { font-size: 18px; margin: 0 0 16px; }
.keypad-recents .callrow { padding-left: 0; padding-right: 0; }
.keypad-recents #keypad-recents { color: var(--text-2); }
.callrow.selected { background: var(--selected); }
.minicall { background: var(--nav-surface); border: 1px solid var(--border); border-radius: 18px;
  display: flex; align-items: center; gap: 10px; padding: 8px; margin: 0 16px 16px 0; }
.minicall button { cursor: pointer; border: 0; border-radius: 12px; min-height: 44px; padding: 8px 14px; background: var(--glass); }
#minicall-open { flex: 1; min-width: 0; display: flex; align-items: center; gap: 12px; text-align: left; background: transparent; }
#minicall-open > span:nth-child(2) { flex: 1; min-width: 0; }
#minicall-open b { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#minicall-status { display: block; color: var(--text-2); font: 12px var(--mono); }
.minicall-dot { width: 9px; height: 9px; background: var(--primary); border-radius: 50%; flex: none; }
.minicall .minicall-end { background: var(--danger); color: #fff; }
.minimize-call { align-self: flex-end; margin: 0 0 10px; }
@media (min-width: 861px) {
  #app { display: grid; grid-template-columns: 136px minmax(0,1fr); grid-template-rows: auto minmax(0,1fr) auto; }
  #app > header.bar { grid-column: 1 / -1; padding: 18px 24px; gap: 18px; }
  #app > header.bar::before { content: "Sonaline"; font-size: 22px; font-weight: 600; letter-spacing: -.6px; }
  #app > .body { grid-column: 2; grid-row: 2; border: 1px solid var(--border); border-radius: 24px; overflow: hidden; margin: 0 16px 16px 0; background: var(--surface); }
  nav.bottomnav { grid-column: 1; grid-row: 2 / 4; flex-direction: column; align-self: start; margin: 0 16px; border-radius: 28px; }
  nav.bottomnav button { flex: none; min-height: 70px; border-radius: 22px; padding: 12px 6px; }
  nav.bottomnav .nav-label { font-size: 12px; }
  .searchfield, body.searching .searchfield { display: flex; align-items: center; position: static; order: 1;
    max-width: 440px; flex: 1; height: 44px; padding: 0 12px; margin-left: auto; gap: 8px;
    background: var(--glass); border: 1px solid var(--border); border-radius: 999px; }
  .bar-right { order: 2; }
  body.searching .linechip, body.searching .bar-right { visibility: visible; }
  #search-open, #search-cancel { display: none; }
  .minicall { grid-column: 2; grid-row: 3; }
  body.tab-detail #callspane { display: flex; flex: 0 0 360px; border-right: 1px solid var(--border); }
  body.tab-detail #callspane .pane-head { flex-wrap: wrap; gap: 8px; }
  body.tab-detail #callspane .chiprow { flex-wrap: wrap; }
  #calldetail { background: var(--glass); }
  .thread-head { min-height: 76px; }
}
@media (min-width: 861px) and (max-width: 1100px) {
  #app { grid-template-columns: 108px minmax(0,1fr); }
  nav.bottomnav { margin: 0 10px; }
  .keypad-layout { gap: 16px; padding: 12px 18px; }
  .keypad-recents .callrow time { display: none; }
  body.tab-detail #callspane { flex-basis: 310px; }
}
@media (max-width: 860px) {
  nav.bottomnav { position: absolute; z-index: 5; left: 50%; transform: translateX(-50%);
    bottom: max(12px, env(safe-area-inset-bottom)); width: calc(100% - 48px); max-width: 320px; margin: 0; }
  section.list > .rows, .phonepane > .rows { padding-bottom: calc(104px + env(safe-area-inset-bottom)); }
  #list .fab, .phonepane .fab { bottom: calc(104px + env(safe-area-inset-bottom)); }
  .keypad-layout { padding: 0 12px calc(104px + env(safe-area-inset-bottom)); justify-content: center; }
  .keypad-recents { display: none; }
  #dialpad { flex-basis: 400px; min-height: 530px; border: 0; background: transparent; }
  #keypadpane > .pane-head { padding-bottom: 0; }
  #dial-close { display: none; }
  #dialpad .dial-head { padding-top: 0; }
  #dialpad .dial-display { min-height: 92px; }
  .minimize-call, .minicall { display: none !important; }
  .composer { padding-bottom: max(14px, env(safe-area-inset-bottom)); }
  .pane-head { flex-wrap: wrap; gap: 8px; }
  .pane-tools { flex-wrap: wrap; }
  .icon-btn, .avatar-btn { min-width: 44px; min-height: 44px; }
  input, textarea, select { font-size: max(16px, 1em); }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; scroll-behavior: auto !important; }
}
/* Flex children must shrink below the textarea's intrinsic width. */
.composer .inputwrap, .composer textarea, .thread-head .headtext { min-width: 0; }
.composer textarea { width: 100%; }
.line-picker-hint { color: var(--text-2); line-height: 1.5; }
#line-picker-list { display: flex; flex-direction: column; gap: 8px; }
.line-choice { border: 1px solid var(--border); border-radius: 16px; background: var(--glass); padding: 14px; text-align: left; cursor: pointer; }
.line-choice b, .line-choice span { display: block; }
.line-choice span { color: var(--text-2); font: 12px var(--mono); margin-top: 4px; }
.line-choice[aria-pressed="true"] { border-color: var(--primary); background: var(--primary-soft); }
.line-choice:disabled { opacity: .6; cursor: default; }
