<script setup lang="ts">
import {
  SkyBlock,
  SkyButton,
  SkyDialog,
  SkyDialogButton,
  SkyGlass,
  SkyList,
  SkyField,
  SkyAppPage,
  SkySheet,
  SkyTabBar,
  SkyTabButton,
} from '@/ui'
import {
  Camera,
  Check,
  ChevronRight,
  ChevronLeft,
  Clock3,
  ContactRound,
  Delete,
  Info,
  Images,
  Grid3X3,
  Mail,
  MessageCircle,
  MicOff,
  MoreHorizontal,
  Phone,
  PhoneIncoming,
  PhoneOff,
  PhoneOutgoing,
  Plus,
  Search,
  Smartphone,
  Star,
  UserRound,
  Video,
  Volume2,
  X,
} from 'lucide-vue-next'
import { computed, nextTick, onBeforeUnmount, onMounted, ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'

import { useCallsStore } from '@/stores/calls'
import { useEasyShareStore } from '@/stores/easyshare'
import { useMessageMediaStore } from '@/stores/messageMedia'
import { useMessagesStore } from '@/stores/messages'
import { usePhoneStore } from '@/stores/phone'
import type { EasySharePayload } from '@/types/easyshare'
import type { PhoneContact, RecentCall } from '@/types/phone'
import { nuiCall } from '@/utils/nui'
import { formatPhoneNumber, normalizePhoneNumber } from '@/utils/phone'

type PhoneTab = 'recents' | 'contacts' | 'keypad'
type RecentFilter = 'all' | 'missed'
type ContactProfileAction = 'message' | 'call' | 'video' | 'mail'
type ContactPhotoContext = {
  avatarMediaId: number | null
  avatarUrl: string
  contactId?: string
  email: string
  firstName: string
  lastName: string
  notes: string
  organization: string
  phoneNumber: string
}

const phone = usePhoneStore()
const calls = useCallsStore()
const easyShare = useEasyShareStore()
const mediaPicker = useMessageMediaStore()
const messages = useMessagesStore()
const route = useRoute()
const router = useRouter()
const tab = ref<PhoneTab>('recents')
const query = ref('')
const recentQuery = ref('')
const recentFilter = ref<RecentFilter>('all')
const selectedNumber = ref('')
const viewingOwnCard = ref(false)
const phoneContent = ref<HTMLElement | null>(null)
const keypad = ref('')
const editorOpened = ref(false)
const editingContact = ref<PhoneContact | null>(null)
const contactFirstName = ref('')
const contactLastName = ref('')
const contactOrganization = ref('')
const contactEmail = ref('')
const contactNotes = ref('')
const contactNumber = ref('')
const contactAvatarMediaId = ref<number | null>(null)
const contactAvatarUrl = ref('')
const error = ref('')
const callMoreOpened = ref(false)
const callKeypadOpened = ref(false)
const inCallKeypad = ref('')
const blockDialogOpened = ref(false)
const blockTargetNumber = ref('')
const callSpeakerPending = ref(false)
const callMutePending = ref(false)
const callElapsedSeconds = ref(0)
let callClock: number | null = null
const tabs = [
  { id: 'recents', icon: Clock3 },
  { id: 'contacts', icon: ContactRound },
  { id: 'keypad', icon: Phone },
] as const
const keypadKeys = [
  { digit: '1', letters: '' },
  { digit: '2', letters: 'ABC' },
  { digit: '3', letters: 'DEF' },
  { digit: '4', letters: 'GHI' },
  { digit: '5', letters: 'JKL' },
  { digit: '6', letters: 'MNO' },
  { digit: '7', letters: 'PQRS' },
  { digit: '8', letters: 'TUV' },
  { digit: '9', letters: 'WXYZ' },
  { digit: '*', letters: '' },
  { digit: '0', letters: '+' },
  { digit: '#', letters: '' },
] as const
const contactProfileActions = [
  { id: 'message', icon: MessageCircle },
  { id: 'call', icon: Phone },
  { id: 'video', icon: Video },
  { id: 'mail', icon: Mail },
] as const
const contactAlphabet = [...'ABCDEFGHIJKLMNOPQRSTUVWXYZ', '#']
const visibleContacts = computed(() => {
  const needle = query.value.trim().toLowerCase()
  if (!needle) return calls.contacts
  return calls.contacts.filter(
    (contact) =>
      contact.name.toLowerCase().includes(needle) ||
      contact.phone_number.includes(needle.replace(/\D/g, '')),
  )
})
const contactsByNumber = computed(
  () =>
    new Map(calls.contacts.map((contact) => [contact.phone_number, contact])),
)
const groupedContacts = computed(() => {
  const groups = new Map<string, PhoneContact[]>()
  const sorted = [...visibleContacts.value].sort((left, right) =>
    left.name.localeCompare(right.name, phone.lang, { sensitivity: 'base' }),
  )
  for (const contact of sorted) {
    const firstCharacter = contact.name.trim().charAt(0).toUpperCase()
    const letter = /^[A-Z]$/.test(firstCharacter) ? firstCharacter : '#'
    const group = groups.get(letter) ?? []
    group.push(contact)
    groups.set(letter, group)
  }
  return contactAlphabet
    .filter((letter) => groups.has(letter))
    .map((letter) => ({ contacts: groups.get(letter) ?? [], letter }))
})
const favoriteContacts = computed(() =>
  calls.contacts
    .filter((contact) => Boolean(contact.favorite))
    .sort((left, right) =>
      left.name.localeCompare(right.name, phone.lang, { sensitivity: 'base' }),
    ),
)
const visibleRecents = computed(() => {
  const needle = recentQuery.value.trim().toLowerCase()
  return calls.recents.filter((recent) => {
    const contact = calls.contacts.find(
      (entry) => entry.phone_number === recent.other_number,
    )
    const matchesFilter =
      recentFilter.value === 'all' ||
      ['missed', 'no_answer'].includes(recent.status)
    const matchesQuery =
      !needle ||
      recent.other_number.includes(needle.replace(/\D/g, '')) ||
      contact?.name.toLowerCase().includes(needle)
    return matchesFilter && matchesQuery
  })
})
const selectedContact = computed(
  () =>
    calls.contacts.find(
      (contact) => contact.phone_number === selectedNumber.value,
    ) ?? null,
)
const selectedHistory = computed(() =>
  calls.recents.filter(
    (recent) => recent.other_number === selectedNumber.value,
  ),
)
const selectedDisplayName = computed(() => {
  if (viewingOwnCard.value) return phone.t('Apps.phone.myCard')
  return selectedContact.value?.name ?? formatPhoneNumber(selectedNumber.value)
})
const keypadDisplay = computed(() => {
  if (!keypad.value) return ''
  return /[*#]/.test(keypad.value)
    ? keypad.value
    : formatPhoneNumber(keypad.value)
})
const keypadSuggestions = computed(() => {
  const enteredDigits = keypad.value.replace(/\D/g, '')
  if (enteredDigits.length < 2 || /[*#]/.test(keypad.value)) return []
  return calls.contacts
    .filter((contact) =>
      contact.phone_number.replace(/\D/g, '').startsWith(enteredDigits),
    )
    .sort((left, right) => {
      const leftExact = left.phone_number.replace(/\D/g, '') === enteredDigits
      const rightExact = right.phone_number.replace(/\D/g, '') === enteredDigits
      if (leftExact !== rightExact) return leftExact ? -1 : 1
      return left.name.localeCompare(right.name, phone.lang, {
        sensitivity: 'base',
      })
    })
})
const activeCallLabel = computed(() => {
  const call = calls.activeCall
  if (!call) return ''
  if (call.state === 'ringing') {
    return phone.t(
      call.direction === 'incoming'
        ? 'Apps.phone.incoming'
        : 'Apps.phone.calling',
    )
  }
  const key = call.state === 'no_answer' ? 'noAnswer' : call.state
  return phone.t(`Apps.phone.${key}`)
})
const activeCallStatus = computed(() => {
  if (calls.activeCall?.state !== 'connected') return activeCallLabel.value
  const minutes = Math.floor(callElapsedSeconds.value / 60)
  const seconds = String(callElapsedSeconds.value % 60).padStart(2, '0')
  return `${String(minutes).padStart(2, '0')}:${seconds}`
})
const activeCallContact = computed(
  () =>
    calls.contacts.find(
      (contact) => contact.phone_number === calls.activeCall?.otherNumber,
    ) ?? null,
)
const contactEditorInitials = computed(() =>
  contactFirstName.value.trim().charAt(0).toUpperCase(),
)

function eventValue(event: Event): string {
  return (event.target as HTMLInputElement).value
}

function contactNameFor(number: string): string {
  return contactsByNumber.value.get(number)?.name ?? formatPhoneNumber(number)
}

function openContact(contact?: PhoneContact, number = ''): void {
  editingContact.value = contact ?? null
  const nameParts = contact?.name.trim().split(/\s+/) ?? []
  contactFirstName.value = nameParts.shift() ?? ''
  contactLastName.value = nameParts.join(' ')
  contactOrganization.value = contact?.organization ?? ''
  contactEmail.value = contact?.email ?? ''
  contactNotes.value = contact?.notes ?? ''
  contactNumber.value = contact?.phone_number ?? number
  contactAvatarMediaId.value = contact?.avatar_media_id ?? null
  contactAvatarUrl.value = contact?.avatar_url ?? ''
  error.value = ''
  editorOpened.value = true
}

function openContactPhotoPicker(source: 'camera' | 'photos'): void {
  mediaPicker.begin('phone:contact-photo', 'photo', '/apps/phone', 1, {
    avatarMediaId: contactAvatarMediaId.value,
    avatarUrl: contactAvatarUrl.value,
    contactId: editingContact.value?.id,
    email: contactEmail.value,
    firstName: contactFirstName.value,
    lastName: contactLastName.value,
    notes: contactNotes.value,
    organization: contactOrganization.value,
    phoneNumber: contactNumber.value,
  } satisfies ContactPhotoContext)
  editorOpened.value = false
  void router.push({
    path: `/apps/${source}`,
    query: { mediaAttachment: 'photo' },
  })
}

function removeContactPhoto(): void {
  contactAvatarMediaId.value = null
  contactAvatarUrl.value = ''
}

function openRecentDetail(number: string): void {
  viewingOwnCard.value = false
  selectedNumber.value = number
  error.value = ''
  void nextTick(() => phoneContent.value?.scrollTo({ top: 0 }))
}

function openMyCard(): void {
  if (!phone.device?.sim) return
  viewingOwnCard.value = true
  selectedNumber.value = phone.device.sim.number
  error.value = ''
  void nextTick(() => phoneContent.value?.scrollTo({ top: 0 }))
}

function closeRecentDetail(): void {
  viewingOwnCard.value = false
  selectedNumber.value = ''
}

function selectTab(nextTab: PhoneTab): void {
  viewingOwnCard.value = false
  selectedNumber.value = ''
  tab.value = nextTab
}

function scrollToContactGroup(letter: string): void {
  const scroller = phoneContent.value
  if (letter === 'favorites') {
    const target = document.getElementById('phone-contact-group-favorites')
    if (!scroller || !target) return
    const scrollTop =
      scroller.scrollTop +
      target.getBoundingClientRect().top -
      scroller.getBoundingClientRect().top -
      8
    scroller.scrollTo({ behavior: 'smooth', top: scrollTop })
    return
  }
  const availableLetters = new Set(
    groupedContacts.value.map((group) => group.letter),
  )
  let targetLetter = letter
  if (!availableLetters.has(targetLetter)) {
    const requestedIndex = contactAlphabet.indexOf(letter)
    for (let distance = 1; distance < contactAlphabet.length; distance += 1) {
      const nextLetter = contactAlphabet[requestedIndex + distance]
      if (nextLetter && availableLetters.has(nextLetter)) {
        targetLetter = nextLetter
        break
      }
      const previousLetter = contactAlphabet[requestedIndex - distance]
      if (previousLetter && availableLetters.has(previousLetter)) {
        targetLetter = previousLetter
        break
      }
    }
  }
  const suffix = targetLetter === '#' ? 'other' : targetLetter.toLowerCase()
  const target = document.getElementById(`phone-contact-group-${suffix}`)
  if (!scroller || !target) return
  const scrollTop =
    scroller.scrollTop +
    target.getBoundingClientRect().top -
    scroller.getBoundingClientRect().top -
    8
  scroller.scrollTo({ behavior: 'smooth', top: scrollTop })
}

async function toggleSelectedFavorite(): Promise<void> {
  const contact = selectedContact.value
  if (!contact) return
  const response = await calls.setContactFavorite(
    contact.id,
    !Boolean(contact.favorite),
  )
  if (!response.success) {
    error.value = phone.t('Apps.phone.errors.contact_favorite_failed')
  }
}

async function saveContact(): Promise<void> {
  if (editingContact.value?.readonly) {
    error.value = phone.t('Apps.phone.errors.readonly_contact')
    return
  }
  const number = normalizePhoneNumber(contactNumber.value)
  const name = [contactFirstName.value, contactLastName.value]
    .map((part) => part.trim())
    .filter(Boolean)
    .join(' ')
  if (!name || !number) {
    error.value = phone.t('Apps.phone.errors.invalid_contact')
    return
  }
  const response = await calls.saveContact({
    avatarMediaId: contactAvatarMediaId.value,
    email: contactEmail.value.trim(),
    id: editingContact.value?.id,
    name,
    notes: contactNotes.value.trim(),
    organization: contactOrganization.value.trim(),
    phoneNumber: number,
  })
  if (!response.success) {
    error.value = phone.t(`Apps.phone.errors.${response.error ?? 'default'}`)
    return
  }
  editorOpened.value = false
  viewingOwnCard.value = false
  selectedNumber.value = number
  void nextTick(() => phoneContent.value?.scrollTo({ top: 0 }))
}

async function openMessage(number: string): Promise<void> {
  error.value = ''
  if (await messages.openThread(number)) {
    void router.push('/apps/messages')
    return
  }
  error.value = phone.t('Apps.phone.errors.message_unavailable')
}

function triggerContactAction(action: ContactProfileAction): void {
  if (action === 'call') {
    if (selectedContact.value?.canCall === false) return
    void startCall(selectedNumber.value)
    return
  }
  if (action === 'message' && selectedContact.value?.canMessage !== false) {
    void openMessage(selectedNumber.value)
  }
}

async function startCall(number: string): Promise<void> {
  error.value = ''
  const response = await calls.dial(number)
  if (!response.success) {
    error.value = phone.t(`Apps.phone.errors.${response.error ?? 'default'}`)
  }
}

async function answerCall(): Promise<void> {
  error.value = ''
  const response = await calls.answer()
  if (!response.success) {
    error.value = phone.t(`Apps.phone.errors.${response.error ?? 'default'}`)
  }
}

async function toggleCallSpeaker(): Promise<void> {
  const call = calls.activeCall
  if (
    !call ||
    call.state !== 'connected' ||
    !call.speakerSupported ||
    callSpeakerPending.value
  ) {
    return
  }

  error.value = ''
  callSpeakerPending.value = true
  const response = await calls.setSpeaker(!call.speakerEnabled)
  callSpeakerPending.value = false
  if (!response.success) {
    error.value = phone.t(`Apps.phone.errors.${response.error ?? 'default'}`)
  }
}

async function toggleCallMute(): Promise<void> {
  const call = calls.activeCall
  if (
    !call ||
    call.state !== 'connected' ||
    !call.muteSupported ||
    callMutePending.value
  ) {
    return
  }

  error.value = ''
  callMutePending.value = true
  const response = await calls.setMuted(!call.muted)
  callMutePending.value = false
  if (!response.success) {
    error.value = phone.t(`Apps.phone.errors.${response.error ?? 'default'}`)
  }
}

function updateCallElapsed(): void {
  const call = calls.activeCall
  if (!call || call.state !== 'connected') {
    callElapsedSeconds.value = 0
    return
  }
  const timestamp = call.answeredAt ?? call.startedAt
  const startedAt = timestamp < 1_000_000_000_000 ? timestamp * 1000 : timestamp
  callElapsedSeconds.value = Math.max(
    0,
    Math.floor((Date.now() - startedAt) / 1000),
  )
}

function openCallContact(): void {
  const call = calls.activeCall
  if (!call) return
  callMoreOpened.value = false
  openContact(activeCallContact.value ?? undefined, call.otherNumber)
}

function shareSelectedContact(): void {
  const contact = selectedContact.value
  if (!contact) return
  easyShare.open({
    appId: 'phone',
    copyText: `${contact.name}\n${contact.phone_number}`,
    id: contact.id,
    imageUrl: contact.avatar_url,
    kind: 'contact',
    subtitle: formatPhoneNumber(contact.phone_number),
    title: contact.name,
  })
}

async function shareOwnProfile(): Promise<void> {
  const response = await nuiCall<EasySharePayload>('easyshare:own-contact')
  if (!response.success || !response.data) {
    error.value = phone.t(
      `Apps.easyShare.errors.${response.error ?? 'request_failed'}`,
    )
    return
  }
  error.value = ''
  easyShare.open(response.data)
}

function messageActiveCaller(): void {
  const number = calls.activeCall?.otherNumber
  callMoreOpened.value = false
  if (number) void openMessage(number)
}

async function removeActiveCallerContact(): Promise<void> {
  const contact = activeCallContact.value
  if (!contact) return
  if (await calls.deleteContact(contact.id)) {
    callMoreOpened.value = false
    return
  }
  error.value = phone.t('Apps.phone.errors.contact_remove_failed')
}

function confirmBlockNumber(number: string): void {
  callMoreOpened.value = false
  blockTargetNumber.value = number
  blockDialogOpened.value = true
}

async function blockNumber(): Promise<void> {
  const number = blockTargetNumber.value
  blockDialogOpened.value = false
  error.value = ''
  const response = await calls.blockNumber(number)
  if (!response.success) {
    error.value = phone.t(`Apps.phone.errors.${response.error ?? 'default'}`)
  }
}

function openCallKeypad(): void {
  callMoreOpened.value = false
  inCallKeypad.value = ''
  callKeypadOpened.value = true
}

function addInCallDigit(digit: string): void {
  if (inCallKeypad.value.length < 24) inCallKeypad.value += digit
}

async function deleteEditedContact(): Promise<void> {
  if (!editingContact.value) return
  if (editingContact.value.readonly) {
    error.value = phone.t('Apps.phone.errors.readonly_contact')
    return
  }
  if (await calls.deleteContact(editingContact.value.id)) {
    editorOpened.value = false
  }
}

function addDigit(digit: string): void {
  if (keypad.value.length < 10) keypad.value += digit
}

function isEditableTarget(target: EventTarget | null): boolean {
  if (!(target instanceof HTMLElement)) return false
  return (
    target.isContentEditable ||
    target instanceof HTMLInputElement ||
    target instanceof HTMLSelectElement ||
    target instanceof HTMLTextAreaElement
  )
}

function handleKeypadKeyboard(event: KeyboardEvent): void {
  if (
    tab.value !== 'keypad' ||
    selectedNumber.value ||
    event.defaultPrevented ||
    event.isComposing ||
    event.altKey ||
    event.ctrlKey ||
    event.metaKey ||
    isEditableTarget(event.target)
  ) {
    return
  }

  if (/^[0-9*#]$/.test(event.key)) {
    event.preventDefault()
    addDigit(event.key)
    return
  }

  if (event.key === 'Backspace' || event.key === 'Delete') {
    event.preventDefault()
    keypad.value = keypad.value.slice(0, -1)
    return
  }

  if (event.key === 'Enter' && keypad.value && !event.repeat) {
    event.preventDefault()
    void startCall(keypad.value)
  }
}

function chooseKeypadSuggestion(contact: PhoneContact): void {
  keypad.value = contact.phone_number.replace(/\D/g, '').slice(0, 10)
}

function recentStatus(recent: RecentCall): string {
  const key = recent.status === 'no_answer' ? 'noAnswer' : recent.status
  return phone.t(`Apps.phone.${key}`)
}

function recentSubtitle(recent: RecentCall): string {
  const status = recentStatus(recent)
  const direction = phone.t(
    `Apps.phone.${recent.direction === 'incoming' ? 'incomingDirection' : 'outgoingDirection'}`,
  )
  if (!recent.duration_seconds) return `${direction} · ${status}`
  const minutes = Math.floor(recent.duration_seconds / 60)
  const seconds = String(recent.duration_seconds % 60).padStart(2, '0')
  return `${direction} · ${status} · ${minutes}:${seconds}`
}

function contactInitials(number: string): string {
  const contact = calls.contacts.find((entry) => entry.phone_number === number)
  if (!contact) return ''
  return contact.name.trim().charAt(0).toUpperCase()
}

function formatRecentDate(value: string): string {
  const date = new Date(value)
  const now = new Date()
  const sameDay =
    date.getFullYear() === now.getFullYear() &&
    date.getMonth() === now.getMonth() &&
    date.getDate() === now.getDate()
  if (sameDay) {
    return new Intl.DateTimeFormat(phone.lang, {
      hour: '2-digit',
      minute: '2-digit',
    }).format(date)
  }
  const daysAgo = Math.floor(
    (new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime() -
      new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime()) /
      86_400_000,
  )
  if (daysAgo < 7) {
    return new Intl.DateTimeFormat(phone.lang, { weekday: 'long' }).format(date)
  }
  return new Intl.DateTimeFormat(phone.lang, {
    day: '2-digit',
    month: '2-digit',
    year: '2-digit',
  }).format(date)
}

onMounted(async () => {
  window.addEventListener('keydown', handleKeypadKeyboard)
  await calls.bootstrap()
  const photoSelection = mediaPicker.consumeMany<ContactPhotoContext>(
    'phone:contact-photo',
  )
  if (photoSelection) {
    const context = photoSelection.context
    editingContact.value = context?.contactId
      ? (calls.contacts.find((contact) => contact.id === context.contactId) ??
        null)
      : null
    contactFirstName.value = context?.firstName ?? ''
    contactLastName.value = context?.lastName ?? ''
    contactEmail.value = context?.email ?? ''
    contactNotes.value = context?.notes ?? ''
    contactOrganization.value = context?.organization ?? ''
    contactNumber.value = context?.phoneNumber ?? ''
    contactAvatarMediaId.value = context?.avatarMediaId ?? null
    contactAvatarUrl.value = context?.avatarUrl ?? ''
    if (photoSelection.media[0]) {
      contactAvatarMediaId.value = photoSelection.media[0].id
      contactAvatarUrl.value = photoSelection.media[0].url
    }
    tab.value = 'contacts'
    editorOpened.value = true
  } else if (typeof route.query.contactId === 'string') {
    const requestedContact = calls.contacts.find(
      (contact) => contact.id === route.query.contactId,
    )
    if (requestedContact) {
      tab.value = 'contacts'
      openRecentDetail(requestedContact.phone_number)
    }
    await router.replace('/apps/phone')
  } else if (typeof route.query.newContactNumber === 'string') {
    tab.value = 'contacts'
    openContact(undefined, route.query.newContactNumber)
    await router.replace('/apps/phone')
  }
  callClock = window.setInterval(updateCallElapsed, 500)
})

onBeforeUnmount(() => {
  window.removeEventListener('keydown', handleKeypadKeyboard)
  if (callClock !== null) window.clearInterval(callClock)
})
</script>

<template>
  <sky-app-page
    class="native-app phone-calls-app"
    :class="{
      'phone-app--light': !phone.isDarkMode,
      'phone-calls-app--profile': Boolean(selectedNumber),
    }"
  >
    <template v-if="calls.activeCall">
      <section
        class="phone-active-call"
        :class="{ 'phone-active-call--more': callMoreOpened }"
      >
        <header class="phone-active-call__identity">
          <div class="phone-active-call__status">
            <span>P</span>
            {{ activeCallStatus }}
          </div>
          <h1>
            {{ contactNameFor(calls.activeCall.otherNumber) }}
          </h1>
          <p v-if="error" class="phone-active-call__error">{{ error }}</p>
        </header>

        <Transition name="call-panel" mode="out-in">
          <div
            v-if="callKeypadOpened"
            key="keypad"
            class="phone-in-call-keypad"
          >
            <div class="phone-in-call-keypad__grid">
              <button
                v-for="key in keypadKeys"
                :key="key.digit"
                type="button"
                @click="addInCallDigit(key.digit)"
              >
                <span>{{ key.digit }}</span>
                <small>{{ key.letters }}</small>
              </button>
            </div>
            <div class="phone-in-call-keypad__footer">
              <sky-button
                rounded
                class="phone-in-call-keypad__end"
                variant="danger"
                @click="calls.hangup()"
              >
                <PhoneOff />
              </sky-button>
              <sky-button
                clear
                class="phone-in-call-keypad__hide"
                @click="callKeypadOpened = false"
                >{{ phone.t('Apps.phone.hideKeypad') }}</sky-button
              >
            </div>
          </div>

          <div
            v-else-if="callMoreOpened"
            key="more"
            class="phone-call-more"
            @click.self="callMoreOpened = false"
          >
            <div class="phone-call-more__list">
              <sky-button
                class="phone-call-more__item phone-call-more__contact-card"
                @click="openCallContact"
              >
                <span class="phone-call-more__avatar">
                  <span v-if="contactInitials(calls.activeCall.otherNumber)">
                    {{ contactInitials(calls.activeCall.otherNumber) }}
                  </span>
                  <UserRound v-else />
                </span>
                <strong>{{
                  phone.t(
                    activeCallContact
                      ? 'Apps.phone.contactCard'
                      : 'Apps.phone.addToContacts',
                  )
                }}</strong>
              </sky-button>

              <sky-button
                class="phone-call-more__item"
                @click="messageActiveCaller"
              >
                <MessageCircle />
                <strong>{{ phone.t('Apps.phone.sendMessage') }}</strong>
              </sky-button>

              <sky-button
                v-if="activeCallContact"
                class="phone-call-more__item phone-call-more__item--danger"
                @click="removeActiveCallerContact"
              >
                <Delete />
                <strong>{{ phone.t('Apps.phone.removeContact') }}</strong>
              </sky-button>

              <sky-button
                class="phone-call-more__item phone-call-more__item--danger"
                @click="confirmBlockNumber(calls.activeCall.otherNumber)"
              >
                <PhoneOff />
                <strong>{{ phone.t('Apps.phone.blockCaller') }}</strong>
              </sky-button>
            </div>
          </div>

          <div v-else key="actions" class="phone-active-call__actions">
            <sky-button
              rounded
              class="phone-call-action"
              :class="{
                'is-active': calls.activeCall.speakerEnabled,
                'is-disabled':
                  calls.activeCall.state !== 'connected' ||
                  !calls.activeCall.speakerSupported,
              }"
              :disabled="
                calls.activeCall.state !== 'connected' ||
                !calls.activeCall.speakerSupported ||
                callSpeakerPending
              "
              :aria-pressed="calls.activeCall.speakerEnabled === true"
              @click="toggleCallSpeaker"
            >
              <Volume2 />
              <span>{{ phone.t('Apps.phone.speaker') }}</span>
            </sky-button>
            <sky-button rounded class="phone-call-action is-disabled" disabled>
              <Video />
              <span>{{ phone.t('Apps.phone.faceTime') }}</span>
            </sky-button>
            <sky-button
              rounded
              class="phone-call-action"
              :class="{
                'is-active': calls.activeCall.muted,
                'is-disabled':
                  calls.activeCall.state !== 'connected' ||
                  !calls.activeCall.muteSupported,
              }"
              :disabled="
                calls.activeCall.state !== 'connected' ||
                !calls.activeCall.muteSupported ||
                callMutePending
              "
              :aria-busy="callMutePending || undefined"
              :aria-pressed="calls.activeCall.muted === true"
              @click="toggleCallMute"
            >
              <MicOff />
              <span>{{ phone.t('Apps.phone.mute') }}</span>
            </sky-button>

            <div class="phone-call-action-anchor">
              <sky-button
                rounded
                class="phone-call-action"
                @click="callMoreOpened = !callMoreOpened"
              >
                <MoreHorizontal />
                <span>{{ phone.t('Apps.phone.more') }}</span>
              </sky-button>
            </div>
            <sky-button
              rounded
              class="phone-call-action phone-call-action--end"
              variant="danger"
              @click="
                calls.activeCall.direction === 'incoming' &&
                calls.activeCall.state === 'ringing'
                  ? calls.decline()
                  : calls.hangup()
              "
            >
              <PhoneOff />
              <span>{{
                phone.t(
                  calls.activeCall.direction === 'incoming' &&
                    calls.activeCall.state === 'ringing'
                    ? 'Apps.phone.decline'
                    : 'Apps.phone.hangup',
                )
              }}</span>
            </sky-button>
            <sky-button
              v-if="
                calls.activeCall.direction === 'incoming' &&
                calls.activeCall.state === 'ringing'
              "
              rounded
              class="phone-call-action phone-call-action--answer"
              @click="answerCall"
            >
              <Phone />
              <span>{{ phone.t('Apps.phone.answer') }}</span>
            </sky-button>
            <sky-button
              v-else
              rounded
              class="phone-call-action"
              @click="openCallKeypad"
            >
              <Grid3X3 />
              <span>{{ phone.t('Apps.phone.keypad') }}</span>
            </sky-button>
          </div>
        </Transition>
      </section>
    </template>

    <template v-else>
      <div
        ref="phoneContent"
        class="phone-call-content"
        :class="{ 'phone-call-content--profile': selectedNumber }"
      >
        <sky-block v-if="!phone.device?.sim" class="text-center">
          <h2>{{ phone.t('Apps.phone.noSim') }}</h2>
          <p class="text-[#8e8e93]">{{ phone.t('Apps.phone.noSimBody') }}</p>
        </sky-block>

        <template v-else-if="selectedNumber">
          <section class="phone-contact-detail">
            <header class="phone-detail-header">
              <sky-button
                rounded
                class="phone-detail-header-button phone-detail-back"
                :aria-label="phone.t('Common.back')"
                @click="closeRecentDetail"
              >
                <ChevronLeft :size="29" :stroke-width="2.4" />
              </sky-button>

              <span class="phone-detail-header-spacer" />

              <sky-button
                v-if="!viewingOwnCard"
                rounded
                class="phone-detail-edit"
                @click="
                  openContact(selectedContact ?? undefined, selectedNumber)
                "
              >
                {{
                  phone.t(
                    selectedContact ? 'Common.edit' : 'Apps.phone.addContact',
                  )
                }}
              </sky-button>
              <span v-else class="phone-detail-edit-spacer" />
            </header>

            <div class="phone-contact-hero">
              <div class="phone-contact-avatar phone-contact-avatar--large">
                <img
                  v-if="selectedContact?.avatar_url"
                  :src="selectedContact.avatar_url"
                  alt=""
                />
                <span v-else-if="contactInitials(selectedNumber)">{{
                  contactInitials(selectedNumber)
                }}</span>
                <UserRound v-else :size="48" :stroke-width="1.8" />
              </div>
              <h2>{{ selectedDisplayName }}</h2>
              <p
                v-if="selectedContact?.organization"
                class="phone-contact-organization"
              >
                {{ selectedContact.organization }}
              </p>
              <p v-if="!selectedContact && !viewingOwnCard">
                {{ phone.t('Apps.phone.unknownCaller') }}
              </p>

              <div class="phone-contact-actions">
                <sky-button
                  v-for="action in contactProfileActions"
                  :key="action.id"
                  rounded
                  class="phone-profile-action"
                  :disabled="
                    viewingOwnCard ||
                    ['video', 'mail'].includes(action.id) ||
                    (action.id === 'call' &&
                      selectedContact?.canCall === false) ||
                    (action.id === 'message' &&
                      selectedContact?.canMessage === false)
                  "
                  :aria-label="phone.t(`Apps.phone.${action.id}`)"
                  @click="triggerContactAction(action.id)"
                >
                  <component :is="action.icon" :size="23" fill="currentColor" />
                </sky-button>
              </div>
            </div>

            <section v-if="viewingOwnCard" class="phone-profile-content">
              <sky-glass class="phone-own-profile-card">
                <div>
                  <span><Phone :size="19" /></span>
                  <p>
                    <small>{{ phone.t('Apps.phone.myNumber') }}</small>
                    <strong>{{ formatPhoneNumber(selectedNumber) }}</strong>
                  </p>
                </div>
                <div>
                  <span><Smartphone :size="19" /></span>
                  <p>
                    <small>{{ phone.t('Apps.phone.device') }}</small>
                    <strong>{{ phone.device?.name }}</strong>
                  </p>
                </div>
              </sky-glass>
              <sky-glass class="phone-profile-card phone-profile-single-option">
                <button type="button" @click="shareOwnProfile">
                  <span>{{ phone.t('Apps.easyShare.shareProfile') }}</span>
                </button>
              </sky-glass>
            </section>

            <section v-else class="phone-profile-content">
              <sky-glass class="phone-profile-card phone-profile-info-card">
                <button
                  type="button"
                  :disabled="selectedContact?.canCall === false"
                  @click="startCall(selectedNumber)"
                >
                  <span>
                    <small>{{ phone.t('Apps.phone.mobile') }}</small>
                    <strong>{{ formatPhoneNumber(selectedNumber) }}</strong>
                  </span>
                  <Phone :size="21" fill="currentColor" />
                </button>
                <button
                  type="button"
                  :disabled="selectedContact?.canMessage === false"
                  @click="openMessage(selectedNumber)"
                >
                  <span>
                    <small>{{ phone.t('Apps.phone.messagesProfile') }}</small>
                    <strong>{{ selectedDisplayName }}</strong>
                  </span>
                  <ChevronRight :size="23" />
                </button>
                <div class="phone-profile-notes">
                  <span>{{ phone.t('Apps.phone.notes') }}</span>
                  <p v-if="selectedContact?.notes">
                    {{ selectedContact.notes }}
                  </p>
                </div>
              </sky-glass>

              <sky-glass class="phone-profile-card phone-profile-options-card">
                <button
                  type="button"
                  :disabled="selectedContact?.canMessage === false"
                  @click="openMessage(selectedNumber)"
                >
                  <span>{{ phone.t('Apps.phone.sendMessage') }}</span>
                </button>
                <button
                  type="button"
                  :disabled="!selectedContact"
                  @click="shareSelectedContact"
                >
                  <span>{{ phone.t('Apps.phone.shareContact') }}</span>
                </button>
                <button
                  type="button"
                  :disabled="!selectedContact"
                  @click="toggleSelectedFavorite"
                >
                  <span>{{
                    phone.t(
                      selectedContact?.favorite
                        ? 'Apps.phone.removeFavorite'
                        : 'Apps.phone.addFavorite',
                    )
                  }}</span>
                </button>
              </sky-glass>

              <sky-glass class="phone-profile-card phone-profile-single-option">
                <button
                  type="button"
                  @click="confirmBlockNumber(selectedNumber)"
                >
                  <span>{{ phone.t('Apps.phone.blockContact') }}</span>
                </button>
              </sky-glass>

              <sky-glass class="phone-history-card">
                <h3>{{ phone.t('Apps.phone.callHistory') }}</h3>
                <div
                  v-for="recent in selectedHistory"
                  :key="recent.id"
                  class="phone-history-row"
                >
                  <span
                    class="phone-history-direction"
                    :class="{
                      'phone-history-direction--missed': [
                        'missed',
                        'no_answer',
                      ].includes(recent.status),
                    }"
                  >
                    <PhoneIncoming
                      v-if="recent.direction === 'incoming'"
                      :size="17"
                    />
                    <PhoneOutgoing v-else :size="17" />
                  </span>
                  <span class="phone-history-copy">
                    <strong>{{ recentStatus(recent) }}</strong>
                    <small>{{ recentSubtitle(recent) }}</small>
                  </span>
                  <time>{{ formatRecentDate(recent.created_at) }}</time>
                </div>
                <p v-if="!selectedHistory.length" class="phone-history-empty">
                  {{ phone.t('Apps.phone.noCallHistory') }}
                </p>
              </sky-glass>
            </section>
          </section>
        </template>

        <template v-else-if="tab === 'recents'">
          <section class="phone-recents">
            <header class="phone-recents-header">
              <div class="phone-recents-filter" role="group">
                <button
                  type="button"
                  :class="{ active: recentFilter === 'all' }"
                  @click="recentFilter = 'all'"
                >
                  {{ phone.t('Apps.phone.allCalls') }}
                </button>
                <button
                  type="button"
                  :class="{ active: recentFilter === 'missed' }"
                  @click="recentFilter = 'missed'"
                >
                  {{ phone.t('Apps.phone.missedCalls') }}
                </button>
              </div>
              <h1>{{ phone.t('Apps.phone.recents') }}</h1>
              <label class="phone-recents-search">
                <Search :size="21" />
                <input
                  :value="recentQuery"
                  :placeholder="phone.t('Apps.phone.searchRecents')"
                  type="search"
                  @input="recentQuery = eventValue($event)"
                />
              </label>
            </header>

            <div v-if="visibleRecents.length" class="phone-recents-list">
              <article
                v-for="recent in visibleRecents"
                :key="recent.id"
                class="phone-recent-row"
              >
                <div class="phone-contact-avatar">
                  <img
                    v-if="contactsByNumber.get(recent.other_number)?.avatar_url"
                    :src="
                      contactsByNumber.get(recent.other_number)?.avatar_url ??
                      ''
                    "
                    alt=""
                  />
                  <span v-else-if="contactInitials(recent.other_number)">{{
                    contactInitials(recent.other_number)
                  }}</span>
                  <UserRound v-else :size="30" :stroke-width="1.8" />
                </div>
                <button
                  class="phone-recent-call"
                  type="button"
                  @click="startCall(recent.other_number)"
                >
                  <span
                    class="phone-recent-name"
                    :class="{
                      'phone-recent-name--missed': [
                        'missed',
                        'no_answer',
                      ].includes(recent.status),
                    }"
                  >
                    {{ contactNameFor(recent.other_number) }}
                  </span>
                  <span class="phone-recent-meta">
                    <PhoneIncoming
                      v-if="recent.direction === 'incoming'"
                      :size="14"
                    />
                    <PhoneOutgoing v-else :size="14" />
                    {{ recentStatus(recent) }}
                  </span>
                </button>
                <time class="phone-recent-date">{{
                  formatRecentDate(recent.created_at)
                }}</time>
                <button
                  class="phone-recent-info"
                  type="button"
                  :aria-label="phone.t('Apps.phone.contactDetails')"
                  @click="openRecentDetail(recent.other_number)"
                >
                  <Info :size="21" />
                </button>
              </article>
            </div>
            <sky-block v-else class="text-center text-[#8e8e93]">{{
              phone.t('Apps.phone.noRecents')
            }}</sky-block>
          </section>
        </template>

        <template v-else-if="tab === 'contacts'">
          <section class="phone-contacts">
            <header class="phone-contacts-header">
              <div class="phone-contacts-toolbar">
                <span aria-hidden="true" />
                <h1>{{ phone.t('Apps.phone.contacts') }}</h1>
                <button
                  class="phone-contacts-add"
                  type="button"
                  :aria-label="phone.t('Apps.phone.addContact')"
                  @click="openContact()"
                >
                  <Plus :size="28" />
                </button>
              </div>

              <label class="phone-contacts-search">
                <Search :size="21" />
                <input
                  :value="query"
                  :placeholder="phone.t('Common.search')"
                  type="search"
                  @input="query = eventValue($event)"
                />
              </label>
            </header>

            <button class="phone-my-card" type="button" @click="openMyCard">
              <div class="phone-contact-avatar">
                <UserRound :size="30" :stroke-width="1.8" />
              </div>
              <span>
                <strong>{{ phone.t('Apps.phone.myCard') }}</strong>
                <small v-if="phone.device?.sim">{{
                  formatPhoneNumber(phone.device.sim.number)
                }}</small>
              </span>
            </button>

            <div v-if="groupedContacts.length" class="phone-contact-groups">
              <section
                v-if="!query && favoriteContacts.length"
                id="phone-contact-group-favorites"
                class="phone-contact-group phone-contact-group--favorites"
              >
                <h2>
                  <Star :size="13" fill="currentColor" />
                  {{ phone.t('Apps.phone.favorites') }}
                </h2>
                <button
                  v-for="contact in favoriteContacts"
                  :key="`favorite-${contact.id}`"
                  class="phone-contact-row"
                  type="button"
                  @click="openRecentDetail(contact.phone_number)"
                >
                  <span class="phone-contact-avatar">
                    <img
                      v-if="contact.avatar_url"
                      :src="contact.avatar_url"
                      alt=""
                    />
                    <template v-else>{{
                      contactInitials(contact.phone_number)
                    }}</template>
                  </span>
                  <span class="phone-contact-name">
                    {{ contact.name }}
                    <small v-if="contact.readonly">{{
                      phone.t('Apps.phone.officialContact')
                    }}</small>
                  </span>
                </button>
              </section>
              <section
                v-for="group in groupedContacts"
                :id="`phone-contact-group-${
                  group.letter === '#' ? 'other' : group.letter.toLowerCase()
                }`"
                :key="group.letter"
                class="phone-contact-group"
              >
                <h2>{{ group.letter }}</h2>
                <button
                  v-for="contact in group.contacts"
                  :key="contact.id"
                  class="phone-contact-row"
                  type="button"
                  @click="openRecentDetail(contact.phone_number)"
                >
                  <span class="phone-contact-avatar">
                    <img
                      v-if="contact.avatar_url"
                      :src="contact.avatar_url"
                      alt=""
                    />
                    <template v-else>{{
                      contactInitials(contact.phone_number)
                    }}</template>
                  </span>
                  <span class="phone-contact-name">
                    {{ contact.name }}
                    <small v-if="contact.readonly">{{
                      phone.t('Apps.phone.officialContact')
                    }}</small>
                  </span>
                </button>
              </section>
            </div>
            <sky-block v-else class="text-center text-[#8e8e93]">{{
              phone.t('Apps.phone.noContacts')
            }}</sky-block>

            <nav
              v-if="!query"
              class="phone-contact-index"
              :aria-label="phone.t('Apps.phone.contactIndex')"
            >
              <button
                v-if="favoriteContacts.length"
                type="button"
                :aria-label="phone.t('Apps.phone.favorites')"
                @click="scrollToContactGroup('favorites')"
              >
                <Star :size="9" fill="currentColor" />
              </button>
              <button
                v-for="letter in contactAlphabet"
                :key="letter"
                type="button"
                @click="scrollToContactGroup(letter)"
              >
                {{ letter }}
              </button>
            </nav>
          </section>
        </template>

        <template v-else>
          <section class="phone-keypad">
            <Transition name="keypad-suggestions">
              <div
                v-if="keypadSuggestions.length"
                class="phone-keypad-suggestions"
                aria-live="polite"
              >
                <button
                  v-for="contact in keypadSuggestions"
                  :key="contact.id"
                  class="phone-keypad-suggestion"
                  type="button"
                  @click="chooseKeypadSuggestion(contact)"
                >
                  <span class="phone-keypad-suggestion__avatar">
                    <img
                      v-if="contact.avatar_url"
                      :src="contact.avatar_url"
                      alt=""
                    />
                    <template v-else>{{
                      contactInitials(contact.phone_number)
                    }}</template>
                  </span>
                  <span class="phone-keypad-suggestion__copy">
                    <strong>{{ contact.name }}</strong>
                    <small>{{ formatPhoneNumber(contact.phone_number) }}</small>
                  </span>
                </button>
              </div>
            </Transition>
            <div class="phone-keypad-number" aria-live="polite">
              {{ keypadDisplay }}
            </div>
            <div class="phone-keypad-grid">
              <button
                v-for="key in keypadKeys"
                :key="key.digit"
                class="phone-keypad-key"
                type="button"
                @click="addDigit(key.digit)"
              >
                <span>{{ key.digit }}</span>
                <small :class="{ 'phone-keypad-plus': key.digit === '0' }">
                  {{ key.letters }}
                </small>
              </button>
            </div>
            <div class="phone-keypad-actions">
              <button
                class="phone-keypad-call"
                type="button"
                @click="startCall(keypad)"
              >
                <Phone :size="31" fill="currentColor" />
              </button>
              <button
                v-if="keypad"
                class="phone-keypad-delete"
                type="button"
                :aria-label="phone.t('Common.delete')"
                @click="keypad = keypad.slice(0, -1)"
              >
                <Delete :size="27" />
              </button>
            </div>
          </section>
        </template>

        <p v-if="error" class="px-5 text-center text-sm text-[#ff3b30]">
          {{ error }}
        </p>
      </div>
      <sky-tab-bar
        icons
        labels
        class="phone-bottom-tabbar"
        :aria-label="phone.t('Apps.phone.name')"
      >
        <sky-tab-button
          v-for="item in tabs"
          :key="item.id"
          :active="tab === item.id"
          :aria-label="phone.t(`Apps.phone.${item.id}`)"
          @click="selectTab(item.id)"
        >
          <template #icon>
            <component :is="item.icon" aria-hidden="true" />
          </template>
          <template #label>{{ phone.t(`Apps.phone.${item.id}`) }}</template>
        </sky-tab-button>
      </sky-tab-bar>
    </template>
  </sky-app-page>

  <div class="phone-contact-editor-sheet">
    <sky-sheet :opened="editorOpened" @backdropclick="editorOpened = false">
      <section
        class="phone-contact-editor"
        :class="{ 'phone-contact-editor--light': !phone.isDarkMode }"
        role="dialog"
        aria-modal="true"
        :aria-label="
          phone.t(
            editingContact?.readonly
              ? 'Apps.phone.officialContact'
              : editingContact
                ? 'Apps.phone.editContact'
                : 'Apps.phone.addContact',
          )
        "
      >
        <header class="phone-contact-editor__header">
          <sky-button
            rounded
            class="phone-contact-editor__header-button"
            :aria-label="phone.t('Common.cancel')"
            @click="editorOpened = false"
          >
            <X :size="27" />
          </sky-button>
          <h2>
            {{
              phone.t(
                editingContact?.readonly
                  ? 'Apps.phone.officialContact'
                  : editingContact
                    ? 'Apps.phone.editContact'
                    : 'Apps.phone.newContact',
              )
            }}
          </h2>
          <sky-button
            v-if="!editingContact?.readonly"
            rounded
            class="phone-contact-editor__header-button"
            :aria-label="phone.t('Common.save')"
            @click="saveContact"
          >
            <Check :size="28" :stroke-width="2.2" />
          </sky-button>
        </header>

        <div class="phone-contact-editor__scroll">
          <div class="phone-contact-editor__photo">
            <div
              class="phone-contact-editor__avatar-wrap"
              :class="{
                'phone-contact-editor__avatar-wrap--has-photo':
                  contactAvatarUrl,
              }"
            >
              <button
                class="phone-contact-editor__avatar"
                type="button"
                :aria-label="phone.t('Apps.phone.choosePhoto')"
                :disabled="editingContact?.readonly"
                @click="openContactPhotoPicker('photos')"
              >
                <img v-if="contactAvatarUrl" :src="contactAvatarUrl" alt="" />
                <span v-else-if="contactEditorInitials">{{
                  contactEditorInitials
                }}</span>
                <UserRound v-else :size="72" :stroke-width="1.35" />
              </button>
              <sky-button
                v-if="contactAvatarUrl && !editingContact?.readonly"
                rounded
                class="phone-contact-editor__remove-photo"
                :aria-label="phone.t('Apps.phone.removePhoto')"
                @click="removeContactPhoto"
              >
                <Delete :size="25" />
                <span>{{ phone.t('Apps.phone.removePhoto') }}</span>
              </sky-button>
            </div>
            <div
              v-if="!editingContact?.readonly"
              class="phone-contact-editor__photo-actions"
            >
              <sky-button
                small
                rounded
                tonal
                @click="openContactPhotoPicker('photos')"
              >
                <Images :size="18" />
                {{ phone.t('Apps.phone.chooseGallery') }}
              </sky-button>
              <sky-button
                small
                rounded
                tonal
                @click="openContactPhotoPicker('camera')"
              >
                <Camera :size="18" />
                {{ phone.t('Apps.phone.takePhoto') }}
              </sky-button>
            </div>
          </div>

          <sky-list strong inset class="phone-contact-editor__name-list">
            <sky-field
              :value="contactFirstName"
              :placeholder="phone.t('Apps.phone.firstName')"
              autocomplete="given-name"
              :readonly="editingContact?.readonly"
              @input="contactFirstName = eventValue($event)"
            />
            <sky-field
              :value="contactLastName"
              :placeholder="phone.t('Apps.phone.lastName')"
              autocomplete="family-name"
              :readonly="editingContact?.readonly"
              @input="contactLastName = eventValue($event)"
            />
            <sky-field
              :value="contactOrganization"
              :placeholder="phone.t('Apps.phone.companyOrGroup')"
              autocomplete="organization"
              :readonly="editingContact?.readonly"
              @input="contactOrganization = eventValue($event)"
            />
            <sky-field
              :value="contactEmail"
              type="email"
              :placeholder="phone.t('Apps.phone.mail')"
              autocomplete="email"
              :readonly="editingContact?.readonly"
              @input="contactEmail = eventValue($event)"
            />
          </sky-list>

          <sky-list strong inset class="phone-contact-editor__number-list">
            <sky-field
              :value="contactNumber"
              :label="phone.t('Apps.phone.mobile')"
              :placeholder="phone.t('Apps.phone.phoneNumber')"
              inputmode="tel"
              autocomplete="tel"
              :readonly="editingContact?.readonly"
              @input="contactNumber = eventValue($event)"
            >
              <template #media>
                <span class="phone-contact-editor__add-icon"
                  ><Plus :size="19"
                /></span>
              </template>
            </sky-field>
          </sky-list>

          <sky-list strong inset class="phone-contact-editor__notes-list">
            <sky-field
              :value="contactNotes"
              type="textarea"
              :placeholder="phone.t('Apps.phone.notes')"
              :maxlength="500"
              autocapitalize="sentences"
              :readonly="editingContact?.readonly"
              @input="contactNotes = eventValue($event)"
            />
          </sky-list>

          <p v-if="error" class="phone-contact-editor__error">{{ error }}</p>

          <sky-button
            v-if="editingContact && !editingContact.readonly"
            class="phone-contact-editor__delete"
            @click="deleteEditedContact"
          >
            {{ phone.t('Apps.phone.deleteContact') }}
          </sky-button>
        </div>
      </section>
    </sky-sheet>
  </div>

  <sky-dialog
    :opened="blockDialogOpened"
    @backdropclick="blockDialogOpened = false"
  >
    <template #title>{{ phone.t('Apps.phone.blockCallerTitle') }}</template>
    <p>
      {{
        phone.t('Apps.phone.blockCallerBody', {
          number: contactNameFor(blockTargetNumber),
        })
      }}
    </p>
    <template #buttons>
      <sky-dialog-button @click="blockDialogOpened = false">{{
        phone.t('Common.cancel')
      }}</sky-dialog-button>
      <sky-dialog-button strong @click="blockNumber">{{
        phone.t('Apps.phone.block')
      }}</sky-dialog-button>
    </template>
  </sky-dialog>
</template>

<style scoped>
.phone-active-call {
  position: absolute;
  z-index: 30;
  inset: 0;
  display: flex;
  min-height: 0;
  flex-direction: column;
  overflow: hidden;
  background: linear-gradient(180deg, #2f4a98 0%, #2a468f 44%, #293044 100%);
  color: white;
  text-align: center;
}

.phone-active-call::before {
  position: absolute;
  z-index: 0;
  inset: 0;
  background: rgba(4, 12, 30, 0.48);
  content: '';
  opacity: 0;
  pointer-events: none;
  transition: opacity 260ms cubic-bezier(0.22, 1, 0.36, 1);
}

.phone-active-call > * {
  position: relative;
  z-index: 1;
}

.phone-active-call--more::before {
  opacity: 1;
}

.phone-active-call--more .phone-active-call__identity {
  opacity: 0.48;
}

.phone-active-call__identity {
  padding: 112px 24px 0;
  transition: opacity 240ms cubic-bezier(0.22, 1, 0.36, 1);
}

.call-panel-enter-active {
  transition:
    opacity 240ms ease-out,
    transform 320ms cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}

.call-panel-leave-active {
  transition:
    opacity 150ms ease-in,
    transform 190ms cubic-bezier(0.4, 0, 1, 1);
  will-change: opacity, transform;
}

.call-panel-enter-from,
.call-panel-leave-to {
  opacity: 0;
}

.phone-active-call__actions.call-panel-enter-from,
.phone-active-call__actions.call-panel-leave-to {
  transform: translateY(18px) scale(0.985);
}

.phone-call-more.call-panel-enter-from,
.phone-call-more.call-panel-leave-to {
  transform: translateY(38px);
}

.phone-in-call-keypad.call-panel-enter-from,
.phone-in-call-keypad.call-panel-leave-to {
  transform: translateY(24px) scale(0.97);
}

@media (prefers-reduced-motion: reduce) {
  .phone-active-call::before,
  .phone-active-call__identity,
  .call-panel-enter-active,
  .call-panel-leave-active {
    transition-duration: 1ms !important;
  }
}

.phone-active-call__status {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  color: rgba(224, 230, 255, 0.66);
  font-size: 25px;
  font-variant-numeric: tabular-nums;
  font-weight: 500;
  line-height: 28px;
}

.phone-active-call__status span {
  display: grid;
  width: 16px;
  height: 16px;
  place-items: center;
  border-radius: 3px;
  background: white;
  color: #172758;
  font-size: 10px;
  font-weight: 800;
  line-height: 1;
}

.phone-active-call__identity h1 {
  max-width: 100%;
  margin: 9px 0 0;
  overflow: hidden;
  font-size: 32px;
  font-weight: 700;
  letter-spacing: -0.8px;
  line-height: 1.08;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.phone-active-call__error {
  margin: 10px 0 0;
  color: #ffb4ae;
  font-size: 12px;
}

.phone-active-call__actions {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 11px 19px;
  width: 100%;
  margin-top: auto;
  padding: 0 28px 48px;
}

.phone-call-action {
  position: relative;
  display: flex !important;
  width: 100% !important;
  height: 108px !important;
  flex-direction: column !important;
  align-items: center !important;
  justify-content: flex-start !important;
  gap: 13px !important;
  padding: 24px 0 0 !important;
  border: 0 !important;
  background: transparent !important;
  box-shadow: none !important;
  color: white !important;
  overflow: visible !important;
  font-size: 14px !important;
  font-weight: 400 !important;
  line-height: 17px !important;
  white-space: nowrap;
}

.phone-call-action-anchor {
  min-width: 0;
  height: 108px;
}

.phone-call-action::before {
  position: absolute;
  z-index: 0;
  top: 0;
  left: 50%;
  width: 80px;
  height: 80px;
  border: 1px solid rgba(215, 225, 255, 0.72);
  border-radius: 50%;
  background: rgba(145, 164, 215, 0.22);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.03);
  content: '';
  transform: translateX(-50%);
  transition:
    background-color 140ms ease,
    transform 140ms ease;
}

.phone-call-action:active::before {
  transform: translateX(-50%) scale(0.94);
}

.phone-call-action > svg,
.phone-call-action > span {
  position: relative;
  z-index: 1;
}

.phone-call-action > svg {
  width: 32px;
  height: 32px;
  flex: none;
  stroke-width: 2.2;
}

.phone-call-action > span {
  position: absolute;
  top: 89px;
  display: block;
  width: 112px;
  overflow: hidden;
  color: #fff;
  line-height: 18px;
  text-overflow: ellipsis;
  transition: none;
}

.phone-call-action.is-active {
  color: #25458e !important;
}

.phone-call-action.is-active::before {
  background: white;
}

.phone-call-action.is-disabled {
  color: rgba(232, 236, 250, 0.56) !important;
  opacity: 1 !important;
}

.phone-call-action.is-disabled > span {
  color: rgba(232, 236, 250, 0.56);
}

.phone-call-action--end::before {
  border-color: rgba(255, 186, 181, 0.72);
  background: #d92d22;
}

.phone-call-action--answer::before {
  border-color: rgba(190, 255, 198, 0.72);
  background: #34a853;
}

.phone-call-more {
  display: flex;
  min-height: 0;
  flex: 1;
  align-items: flex-end;
  padding: 0 34px 34px;
}

.phone-call-more__list {
  display: flex;
  width: 100%;
  flex-direction: column;
  gap: 9px;
}

.phone-call-more__item {
  display: flex !important;
  width: 100% !important;
  height: 58px !important;
  align-items: center !important;
  justify-content: flex-start !important;
  gap: 13px !important;
  padding: 0 27px !important;
  border: 1px solid rgba(118, 137, 191, 0.38) !important;
  border-radius: 30px !important;
  background: rgba(20, 23, 39, 0.55) !important;
  color: white !important;
  box-shadow: none !important;
  text-transform: none !important;
}

.phone-call-more__item:active {
  background: rgba(49, 57, 84, 0.68) !important;
}

.phone-call-more__contact-card {
  height: 72px !important;
  padding: 0 33px !important;
  border-radius: 38px !important;
}

.phone-call-more__item > svg {
  width: 24px;
  height: 24px;
  flex: none;
}

.phone-call-more__item--danger {
  color: #ff6961 !important;
}

.phone-call-more__avatar {
  display: grid;
  width: 45px;
  height: 45px;
  flex: none;
  place-items: center;
  border-radius: 50%;
  background: linear-gradient(145deg, #4b92d1, #195287);
  font-size: 17px;
  font-weight: 700;
}

.phone-call-more__avatar svg {
  width: 24px;
  height: 24px;
}

.phone-call-more__item strong {
  overflow: hidden;
  font-size: 16px;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.phone-in-call-keypad {
  display: flex;
  min-height: 0;
  flex: 1;
  flex-direction: column;
  padding: 0 28px 42px;
}

.phone-in-call-keypad__grid {
  display: grid;
  grid-template-columns: repeat(3, 74px);
  justify-content: center;
  gap: 18px 40px;
  margin-top: auto;
}

.phone-in-call-keypad__grid button {
  display: flex;
  width: 74px;
  height: 74px;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 50%;
  background: linear-gradient(
    180deg,
    rgba(255, 255, 255, 0.16),
    rgba(255, 255, 255, 0.09)
  );
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.14),
    0 5px 14px rgba(8, 20, 55, 0.2);
  backdrop-filter: blur(18px) saturate(145%);
  -webkit-backdrop-filter: blur(18px) saturate(145%);
  color: white;
  transition:
    background-color 120ms ease,
    border-color 120ms ease,
    box-shadow 120ms ease,
    transform 120ms ease;
}

.phone-in-call-keypad__grid button:active {
  background: rgba(151, 176, 231, 0.44);
  transform: scale(0.95);
}

.phone-in-call-keypad__grid span {
  font-size: 32px;
  line-height: 31px;
}

.phone-in-call-keypad__grid small {
  min-height: 10px;
  margin-top: 2px;
  font-size: 8px;
  font-weight: 800;
  letter-spacing: 1.5px;
}

.phone-in-call-keypad__footer {
  display: grid;
  grid-template-columns: repeat(3, 74px);
  align-items: center;
  justify-content: center;
  gap: 40px;
  margin-top: 42px;
}

.phone-in-call-keypad__end {
  grid-column: 2;
  width: 74px !important;
  height: 74px !important;
  padding: 0 !important;
  border: 1px solid rgba(255, 178, 172, 0.78) !important;
  border-radius: 50% !important;
  background: #cf3027 !important;
  color: white !important;
}

.phone-in-call-keypad__end svg {
  width: 30px;
  height: 30px;
}

.phone-in-call-keypad__hide {
  grid-column: 3;
  width: 96px !important;
  margin-left: -11px;
  padding: 0 !important;
  color: white !important;
  font-size: 14px !important;
  font-weight: 400 !important;
  line-height: 18px !important;
  text-align: left;
  white-space: normal !important;
}

@media (max-height: 700px) {
  .phone-active-call__identity {
    padding-top: 86px;
  }

  .phone-active-call__actions {
    gap: 4px 15px;
    padding-bottom: 28px;
  }

  .phone-call-action {
    height: 97px !important;
    padding-top: 20px !important;
  }

  .phone-call-action-anchor {
    height: 97px;
  }

  .phone-call-action::before {
    width: 70px;
    height: 70px;
  }

  .phone-call-action > svg {
    width: 29px;
    height: 29px;
  }

  .phone-call-action > span {
    top: 79px;
  }

  .phone-in-call-keypad {
    padding-bottom: 24px;
  }

  .phone-in-call-keypad__grid {
    grid-template-columns: repeat(3, 64px);
    gap: 10px 34px;
  }

  .phone-in-call-keypad__grid button {
    width: 64px;
    height: 64px;
  }

  .phone-in-call-keypad__footer {
    grid-template-columns: repeat(3, 64px);
    gap: 34px;
    margin-top: 20px;
  }

  .phone-in-call-keypad__end {
    width: 64px !important;
    height: 64px !important;
  }
}

.phone-call-content {
  min-height: 0;
}

.phone-bottom-tabbar {
  --sky-app-accent: #007aff;
}

.phone-recents,
.phone-contacts,
.phone-contact-detail {
  min-height: 100%;
  padding: 8px 15px
    calc(var(--sky-tabbar-height) + var(--sky-safe-area-bottom) + 16px);
}

.phone-contacts {
  position: relative;
  padding-top: 6px;
  padding-right: 24px;
  padding-bottom: 20px;
}

.phone-contacts-header {
  padding-bottom: 16px;
}

.phone-contacts-toolbar {
  display: grid;
  grid-template-columns: 42px 1fr 42px;
  align-items: center;
  margin-bottom: 13px;
}

.phone-contacts-toolbar h1 {
  margin: 0;
  font-size: 17px;
  text-align: center;
}

.phone-contacts-add {
  display: flex;
  width: 42px;
  height: 42px;
  align-items: center;
  justify-content: center;
  border: 1px solid rgba(142, 142, 147, 0.18);
  border-radius: 50%;
  background: rgba(118, 118, 128, 0.14);
  color: inherit;
}

.phone-contacts-search {
  display: flex;
  min-height: 42px;
  align-items: center;
  gap: 9px;
  padding: 0 14px;
  border-radius: 16px;
  background: rgba(118, 118, 128, 0.16);
  color: #8e8e93;
}

.phone-contacts-search input {
  width: 100%;
  border: 0;
  outline: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: 16px;
}

.phone-my-card {
  display: flex;
  width: 100%;
  min-height: 72px;
  align-items: center;
  gap: 12px;
  margin-bottom: 8px;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
}

.phone-my-card > span {
  display: flex;
  min-width: 0;
  flex-direction: column;
}

.phone-my-card strong {
  font-size: 16px;
}

.phone-my-card small {
  margin-top: 2px;
  color: #8e8e93;
  font-size: 12px;
}

.phone-contact-group {
  scroll-margin-top: 10px;
}

.phone-contact-group h2 {
  height: 28px;
  margin: 0;
  padding-top: 4px;
  border-bottom: 1px solid rgba(142, 142, 147, 0.23);
  color: #8e8e93;
  font-size: 13px;
  font-weight: 500;
}

.phone-contact-group--favorites h2 {
  display: flex;
  align-items: flex-start;
  gap: 5px;
  color: #ffcc00;
}

.phone-contact-row {
  display: grid;
  grid-template-columns: 52px minmax(0, 1fr);
  width: 100%;
  min-height: 68px;
  align-items: center;
  gap: 10px;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
}

.phone-contact-row:not(:last-child) .phone-contact-name {
  border-bottom: 1px solid rgba(142, 142, 147, 0.2);
}

.phone-contact-name {
  display: flex;
  min-width: 0;
  min-height: 68px;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 2px;
  overflow: hidden;
  font-size: 16px;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.phone-contact-name small {
  color: #8e8e93;
  font-size: 10px;
  font-weight: 500;
}

.phone-contact-index {
  position: fixed;
  z-index: 40;
  top: 50%;
  right: 5px;
  display: flex;
  flex-direction: column;
  pointer-events: auto;
  transform: translateY(-42%);
}

.phone-contact-index button {
  width: 24px;
  height: 14px;
  padding: 0;
  border: 0;
  background: transparent;
  color: #0a84ff;
  font: inherit;
  font-size: 9px;
  font-weight: 700;
  line-height: 14px;
  cursor: pointer;
  touch-action: manipulation;
}

.phone-contact-index button svg {
  display: block;
  margin: auto;
}

.phone-contact-index button:active {
  border-radius: 7px;
  background: rgba(10, 132, 255, 0.2);
}

.phone-keypad {
  position: relative;
  display: flex;
  min-height: 100%;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  padding: 56px 24px
    calc(var(--sky-tabbar-height) + var(--sky-safe-area-bottom) + 16px);
}

.phone-keypad-number {
  display: flex;
  width: 100%;
  min-height: 50px;
  align-items: center;
  justify-content: center;
  margin-bottom: 14px;
  overflow: hidden;
  font-size: 25px;
  font-weight: 500;
  letter-spacing: 0.4px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.phone-keypad-suggestions {
  position: absolute;
  z-index: 5;
  top: 18px;
  right: 24px;
  left: 24px;
  display: grid;
  width: auto;
  max-height: 132px;
  gap: 6px;
  margin: 0 auto;
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;
  touch-action: pan-y;
  -webkit-overflow-scrolling: touch;
}

.phone-keypad-suggestions::-webkit-scrollbar {
  display: none;
}

.phone-keypad-suggestion {
  display: grid;
  min-height: 46px;
  grid-template-columns: 36px minmax(0, 1fr);
  align-items: center;
  gap: 10px;
  padding: 5px 12px 5px 6px;
  border: 1px solid rgba(255, 255, 255, 0.09);
  border-radius: 18px;
  color: #fff;
  background: rgba(44, 44, 46, 0.82);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.07),
    0 4px 12px rgba(0, 0, 0, 0.16);
  font: inherit;
  text-align: left;
  backdrop-filter: blur(16px) saturate(140%);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
  transition:
    background-color 160ms ease-out,
    border-color 160ms ease-out,
    transform 160ms ease-out;
}

.phone-keypad-suggestion__avatar {
  display: grid;
  width: 36px;
  height: 36px;
  place-items: center;
  overflow: hidden;
  border-radius: 50%;
  background: linear-gradient(145deg, #4b92d1, #195287);
  font-size: 12px;
  font-weight: 700;
}

.phone-keypad-suggestion__avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.phone-keypad-suggestion__copy {
  display: flex;
  min-width: 0;
  flex-direction: column;
}

.phone-keypad-suggestion__copy strong,
.phone-keypad-suggestion__copy small {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.phone-keypad-suggestion__copy strong {
  font-size: 14px;
  font-weight: 600;
  transition: color 160ms ease-out;
}

.phone-keypad-suggestion__copy small {
  margin-top: 1px;
  color: #a5a5aa;
  font-size: 11px;
}

.keypad-suggestions-enter-active,
.keypad-suggestions-leave-active {
  transition:
    opacity 180ms ease,
    transform 220ms cubic-bezier(0.22, 1, 0.36, 1);
}

.keypad-suggestions-enter-from,
.keypad-suggestions-leave-to {
  opacity: 0;
  transform: translateY(-8px);
}

.phone-keypad-grid {
  display: grid;
  grid-template-columns: repeat(3, 78px);
  gap: 18px 22px;
}

.phone-keypad-key {
  display: flex;
  width: 78px;
  height: 78px;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 50%;
  background: linear-gradient(
    180deg,
    rgba(58, 58, 60, 0.92),
    rgba(28, 28, 30, 0.88)
  );
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.1),
    0 5px 14px rgba(0, 0, 0, 0.24);
  backdrop-filter: blur(18px) saturate(145%);
  -webkit-backdrop-filter: blur(18px) saturate(145%);
  color: white;
  font: inherit;
  transition:
    background-color 120ms ease,
    border-color 120ms ease,
    box-shadow 120ms ease,
    transform 120ms ease;
}

.phone-keypad-key:active {
  background: #3a3a3c;
  transform: scale(0.96);
}

.phone-keypad-key > span {
  font-size: 36px;
  font-weight: 400;
  line-height: 34px;
}

.phone-keypad-key > small {
  min-height: 13px;
  margin-top: 3px;
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 2.4px;
  line-height: 10px;
}

.phone-keypad-key > small.phone-keypad-plus {
  font-size: 15px;
  letter-spacing: 0;
}

.phone-keypad-actions {
  position: relative;
  display: flex;
  width: 100%;
  min-height: 82px;
  align-items: center;
  justify-content: center;
  margin-top: 20px;
}

.phone-keypad-call,
.phone-keypad-delete {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  color: white;
}

.phone-keypad-call {
  width: 78px;
  height: 78px;
  border: 1px solid rgba(133, 235, 143, 0.78);
  background: linear-gradient(180deg, #3e9a49, #2f7d39);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.2),
    0 5px 14px rgba(23, 101, 35, 0.3);
}

.phone-keypad-call:active {
  background: #2d7336;
  transform: scale(0.96);
}

.phone-keypad-delete {
  position: absolute;
  left: calc(50% + 62px);
  width: 48px;
  height: 48px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  background: linear-gradient(
    180deg,
    rgba(58, 58, 60, 0.92),
    rgba(28, 28, 30, 0.88)
  );
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.1),
    0 5px 14px rgba(0, 0, 0, 0.24);
  backdrop-filter: blur(18px) saturate(145%);
  -webkit-backdrop-filter: blur(18px) saturate(145%);
  color: #d1d1d6;
}

.phone-keypad-delete:active {
  background: #3a3a3c;
  transform: scale(0.96);
}

@media (max-height: 690px) {
  .phone-keypad {
    padding-top: 20px;
    padding-bottom: calc(
      var(--sky-tabbar-height) + var(--sky-safe-area-bottom) + 8px
    );
  }

  .phone-keypad-suggestions {
    top: 6px;
    max-height: 104px;
  }

  .phone-keypad-grid {
    grid-template-columns: repeat(3, 70px);
    gap: 12px 18px;
  }

  .phone-keypad-key {
    width: 70px;
    height: 70px;
  }

  .phone-keypad-actions {
    min-height: 70px;
    margin-top: 14px;
  }

  .phone-keypad-suggestion:nth-child(n + 2) {
    display: none;
  }

  .phone-keypad-call {
    width: 68px;
    height: 68px;
  }
}

.phone-recents-header {
  padding: 4px 0 14px;
}

.phone-recents-filter {
  display: grid;
  grid-template-columns: 1fr 1fr;
  width: 174px;
  margin: 0 auto 14px;
  padding: 3px;
  border: 1px solid rgba(142, 142, 147, 0.25);
  border-radius: 15px;
  background: rgba(118, 118, 128, 0.14);
}

.phone-recents-filter button {
  min-height: 30px;
  border: 0;
  border-radius: 12px;
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
}

.phone-recents-filter button.active {
  background: rgba(118, 118, 128, 0.34);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
}

.phone-recents-header h1 {
  margin: 0 0 13px;
  font-size: 30px;
  line-height: 1.06;
  letter-spacing: -0.8px;
}

.phone-recents-search {
  display: flex;
  align-items: center;
  gap: 9px;
  min-height: 42px;
  padding: 0 14px;
  border-radius: 16px;
  background: rgba(118, 118, 128, 0.16);
  color: #8e8e93;
}

.phone-recents-search input {
  width: 100%;
  border: 0;
  outline: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: 16px;
}

.phone-recents-list {
  overflow: hidden;
}

.phone-recent-row {
  display: grid;
  grid-template-columns: 52px minmax(0, 1fr) auto 38px;
  align-items: center;
  min-height: 76px;
  column-gap: 10px;
}

.phone-recent-row:not(:last-child) {
  border-bottom: 1px solid rgba(142, 142, 147, 0.2);
}

.phone-contact-avatar {
  display: flex;
  width: 52px;
  height: 52px;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  border-radius: 50%;
  background: linear-gradient(145deg, #5b91c2, #22527d);
  color: white;
  font-size: 19px;
  font-weight: 700;
  letter-spacing: -0.4px;
  overflow: hidden;
}

.phone-contact-avatar img,
.phone-contact-editor__avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.phone-recent-call {
  display: flex;
  min-width: 0;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  align-self: stretch;
  border: 0;
  background: transparent;
  color: inherit;
  text-align: left;
}

.phone-recent-name {
  overflow: hidden;
  max-width: 100%;
  font-size: 16px;
  font-weight: 700;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.phone-recent-name--missed {
  color: #ff453a;
}

.phone-recent-meta {
  display: flex;
  align-items: center;
  gap: 3px;
  overflow: hidden;
  max-width: 100%;
  margin-top: 2px;
  color: #8e8e93;
  font-size: 13px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.phone-recent-date {
  color: #8e8e93;
  font-size: 12px;
  white-space: nowrap;
}

.phone-recent-info {
  display: flex;
  width: 36px;
  height: 36px;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 50%;
  background: rgba(118, 118, 128, 0.14);
  color: #0a84ff;
}

.phone-detail-header {
  display: flex;
  min-height: 38px;
  align-items: center;
}

.phone-detail-back {
  display: flex;
  align-items: center;
  padding: 0;
  border: 0;
  background: transparent;
  color: #0a84ff;
  font: inherit;
  font-size: 15px;
}

.phone-contact-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 6px 0 22px;
  text-align: center;
}

.phone-contact-avatar--large {
  width: 92px;
  height: 92px;
  font-size: 32px;
}

.phone-contact-hero h2 {
  max-width: 100%;
  margin: 12px 0 2px;
  overflow: hidden;
  font-size: 24px;
  letter-spacing: -0.45px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.phone-contact-hero p {
  margin: 0;
  color: #8e8e93;
  font-size: 14px;
}

.phone-contact-hero .phone-contact-organization {
  margin-top: 2px;
  color: rgba(255, 255, 255, 0.72);
  font-size: 15px;
  font-weight: 500;
}

.phone-contact-actions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  width: 100%;
  margin-top: 20px;
}

.phone-contact-actions button {
  display: flex;
  min-width: 0;
  min-height: 70px;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  border: 0;
  border-radius: 14px;
  background: rgba(118, 118, 128, 0.15);
  color: #0a84ff;
  font: inherit;
  font-size: 12px;
}

.phone-contact-actions button > span {
  display: flex;
  min-height: 25px;
  align-items: center;
}

.phone-own-profile-card {
  overflow: hidden;
  border-radius: 16px;
  background: rgba(118, 118, 128, 0.12);
}

.phone-own-profile-card > div {
  display: grid;
  grid-template-columns: 32px minmax(0, 1fr);
  min-height: 62px;
  align-items: center;
  gap: 8px;
  margin-left: 14px;
  padding-right: 14px;
}

.phone-own-profile-card > div:not(:last-child) {
  border-bottom: 1px solid rgba(142, 142, 147, 0.2);
}

.phone-own-profile-card > div > span {
  display: flex;
  width: 30px;
  height: 30px;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: #0a84ff;
  color: white;
}

.phone-own-profile-card p {
  display: flex;
  min-width: 0;
  flex-direction: column;
  margin: 0;
}

.phone-own-profile-card small {
  color: #8e8e93;
  font-size: 11px;
}

.phone-own-profile-card strong {
  overflow: hidden;
  margin-top: 2px;
  font-size: 14px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.phone-history-card {
  overflow: hidden;
  border-radius: 16px;
  background: rgba(118, 118, 128, 0.12);
}

.phone-history-card h3 {
  margin: 0;
  padding: 13px 14px 10px;
  font-size: 15px;
}

.phone-history-row {
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr) auto;
  align-items: center;
  min-height: 58px;
  gap: 8px;
  margin-left: 14px;
  padding-right: 14px;
  border-top: 1px solid rgba(142, 142, 147, 0.2);
}

.phone-history-direction {
  color: #0a84ff;
}

.phone-history-direction--missed {
  color: #ff453a;
}

.phone-history-copy {
  display: flex;
  min-width: 0;
  flex-direction: column;
}

.phone-history-copy strong {
  font-size: 14px;
}

.phone-history-copy small,
.phone-history-row time,
.phone-history-empty {
  color: #8e8e93;
  font-size: 11px;
}

.phone-history-row time {
  white-space: nowrap;
}

.phone-history-empty {
  margin: 0;
  padding: 18px 14px;
  text-align: center;
}

.phone-call-content--profile {
  background: transparent;
  color: #fff;
  scroll-behavior: smooth;
}

.phone-calls-app--profile {
  background: linear-gradient(
    180deg,
    #a8b3b7 0,
    #8991a2 18%,
    #172f50 55%,
    #061426 100%
  ) !important;
  color: #fff;
}

.phone-contact-detail {
  position: relative;
  padding: 0 15px 112px;
}

.phone-detail-header {
  position: sticky;
  z-index: 12;
  top: 0;
  display: grid;
  height: 58px;
  grid-template-columns: 48px minmax(0, 1fr) minmax(48px, auto);
  align-items: start;
  gap: 8px;
  margin: 0 -15px;
  padding: 7px 15px;
  overflow: visible;
}

.phone-detail-header-button,
.phone-detail-edit {
  min-width: 0;
  height: 44px;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.08);
  color: #fff;
  background: rgba(21, 35, 45, 0.88);
  box-shadow: 0 2px 9px rgba(7, 12, 20, 0.16);
}

.phone-detail-header-button {
  width: 44px;
}

.phone-detail-edit {
  justify-self: end;
  width: auto;
  min-width: 86px;
  padding: 0 17px;
  font-size: 16px;
  font-weight: 500;
}

.phone-detail-edit-spacer {
  width: 44px;
}

.phone-detail-header-spacer {
  min-width: 0;
}

.phone-contact-hero {
  padding: 31px 0 19px;
}

.phone-contact-avatar--large {
  width: 148px;
  height: 148px;
  border: 1px solid rgba(255, 255, 255, 0.28);
  background: linear-gradient(
    155deg,
    rgba(176, 188, 195, 0.74),
    rgba(45, 105, 158, 0.66)
  );
  box-shadow:
    inset 0 1px 2px rgba(255, 255, 255, 0.38),
    0 2px 3px rgba(18, 15, 43, 0.25);
  font-size: 64px;
  font-weight: 400;
}

.phone-contact-hero h2 {
  margin: 14px 0 0;
  color: #fff;
  font-size: 29px;
  font-weight: 700;
  letter-spacing: -0.65px;
}

.phone-contact-actions {
  display: grid;
  width: 100%;
  grid-template-columns: repeat(4, 62px);
  justify-content: center;
  gap: 12px;
  margin-top: 22px;
}

.phone-profile-action {
  width: 62px;
  min-width: 62px;
  height: 62px;
  min-height: 62px;
  padding: 0;
  border: 1px solid rgba(10, 132, 255, 0.58);
  border-radius: 50%;
  color: #fff;
  background: rgba(18, 82, 145, 0.72);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.08),
    0 4px 14px rgba(13, 9, 33, 0.18);
}

.phone-profile-action:disabled {
  color: rgba(255, 255, 255, 0.32);
  opacity: 1;
}

.phone-profile-content {
  display: grid;
  gap: 12px;
}

.phone-profile-card,
.phone-own-profile-card,
.phone-history-card {
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.035);
  border-radius: 24px;
  color: #fff;
  background: rgba(18, 43, 69, 0.8);
  box-shadow: 0 8px 22px rgba(5, 4, 20, 0.12);
  backdrop-filter: blur(20px) saturate(125%);
  -webkit-backdrop-filter: blur(20px) saturate(125%);
}

.phone-profile-info-card > button,
.phone-profile-options-card > button,
.phone-profile-single-option > button {
  display: flex;
  width: calc(100% - 30px);
  min-height: 66px;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin: 0 15px;
  padding: 0;
  border: 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.17);
  color: inherit;
  background: transparent;
  font: inherit;
  text-align: left;
}

.phone-profile-info-card > button:last-of-type,
.phone-profile-options-card > button:last-child,
.phone-profile-single-option > button:last-child {
  border-bottom: 0;
}

.phone-profile-info-card > button > span {
  display: flex;
  min-width: 0;
  flex-direction: column;
}

.phone-profile-info-card small {
  color: #64a8ff;
  font-size: 13px;
}

.phone-profile-info-card strong {
  margin-top: 2px;
  overflow: hidden;
  font-size: 15px;
  font-weight: 400;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.phone-profile-info-card > button > svg {
  flex: none;
  color: #0a84ff;
  transition:
    color 160ms ease-out,
    filter 160ms ease-out,
    transform 160ms ease-out;
}

.phone-profile-notes {
  min-height: 105px;
  margin: 0 15px;
  padding: 17px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.17);
  font-size: 15px;
}

.phone-profile-notes > span {
  display: block;
  color: #fff;
}

.phone-profile-notes > p {
  margin: 8px 0 0;
  color: rgba(255, 255, 255, 0.72);
  line-height: 1.4;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}

.phone-profile-options-card > button,
.phone-profile-single-option > button {
  min-height: 54px;
  font-size: 15px;
}

.phone-profile-options-card > button > span,
.phone-profile-single-option > button > span {
  transition:
    color 160ms ease-out,
    transform 160ms ease-out;
}

.phone-profile-options-card > button:disabled,
.phone-profile-single-option > button:disabled {
  color: inherit;
  opacity: 1;
}

.phone-history-card h3 {
  padding: 15px 16px 11px;
  color: #fff;
}

.phone-history-row {
  margin-left: 15px;
  padding-right: 15px;
  border-top-color: rgba(255, 255, 255, 0.17);
}

.phone-history-copy small,
.phone-history-row time,
.phone-history-empty {
  color: rgba(255, 255, 255, 0.62);
}

.phone-contact-editor-sheet :deep(.sky-sheet__panel) {
  width: 100%;
  height: calc(100% - 52px);
  max-height: calc(100% - 52px);
  border-radius: 30px 30px 0 0;
  background: #3a3a3c;
  box-shadow: 0 -10px 35px rgba(0, 0, 0, 0.28);
}

.phone-contact-editor {
  position: relative;
  display: flex;
  height: 100%;
  min-height: 0;
  flex-direction: column;
  overflow: hidden;
  border-radius: inherit;
  color: #fff;
  background: #3a3a3c;
}

.phone-contact-editor::before {
  position: absolute;
  z-index: 3;
  top: 7px;
  left: 50%;
  width: 44px;
  height: 5px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.38);
  content: '';
  transform: translateX(-50%);
}

.phone-contact-editor__header {
  position: relative;
  z-index: 2;
  display: grid;
  height: 78px;
  padding: 18px 18px 6px;
  grid-template-columns: 52px 1fr 52px;
  align-items: center;
  flex: 0 0 78px;
  background: linear-gradient(180deg, #3a3a3c 72%, rgba(58, 58, 60, 0));
}

.phone-contact-editor__header h2 {
  margin: 0;
  font-size: 18px;
  font-weight: 700;
  text-align: center;
}

.phone-contact-editor__header-button {
  width: 46px;
  min-width: 46px;
  height: 46px;
  min-height: 46px;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.2);
  color: #fff;
  background: rgba(28, 28, 30, 0.58);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
}

.phone-contact-editor__header-button:last-child {
  justify-self: end;
  background: rgba(72, 72, 74, 0.76);
}

.phone-contact-editor__scroll {
  min-height: 0;
  flex: 1;
  padding: 2px 14px 42px;
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;
  touch-action: pan-y;
  -webkit-overflow-scrolling: touch;
}

.phone-contact-editor__scroll::-webkit-scrollbar {
  display: none;
}

.phone-contact-editor__avatar {
  display: grid;
  width: 154px;
  height: 154px;
  margin: 0;
  padding: 0;
  place-items: center;
  border: 1px solid rgba(255, 255, 255, 0.11);
  border-radius: 50%;
  color: #fff;
  background: linear-gradient(155deg, #4b92d1 0%, #195287 100%);
  box-shadow:
    inset 0 1px 1px rgba(255, 255, 255, 0.16),
    0 8px 18px rgba(5, 42, 78, 0.24);
  cursor: pointer;
  overflow: hidden;
}

.phone-contact-editor__avatar-wrap {
  position: relative;
  width: 154px;
  height: 154px;
  margin: 4px auto 12px;
  border-radius: 50%;
}

.phone-contact-editor__remove-photo {
  position: absolute !important;
  z-index: 2;
  inset: 0;
  display: flex !important;
  width: 100% !important;
  height: 100% !important;
  flex-direction: column !important;
  gap: 7px !important;
  padding: 0 !important;
  border: 0 !important;
  border-radius: 50% !important;
  color: #fff !important;
  background: rgba(7, 35, 62, 0.7) !important;
  opacity: 0;
  pointer-events: none;
  transform: scale(0.96);
  transition:
    opacity 170ms ease,
    transform 170ms ease !important;
}

.phone-contact-editor__remove-photo > span {
  font-size: 13px;
  font-weight: 600;
}

.phone-contact-editor__avatar-wrap--has-photo:hover
  .phone-contact-editor__remove-photo,
.phone-contact-editor__remove-photo:focus-visible {
  opacity: 1;
  pointer-events: auto;
  transform: scale(1);
}

.phone-contact-editor__avatar img {
  transition:
    filter 170ms ease,
    transform 170ms ease;
}

.phone-contact-editor__avatar-wrap--has-photo:hover
  .phone-contact-editor__avatar
  img {
  filter: brightness(0.58);
  transform: scale(1.015);
}

.phone-contact-editor__avatar span {
  font-size: 53px;
  font-weight: 600;
  letter-spacing: -2px;
}

.phone-contact-editor__photo {
  margin-bottom: 22px;
  text-align: center;
}

.phone-contact-editor__photo-actions {
  display: flex;
  justify-content: center;
  gap: 8px;
}

.phone-contact-editor__photo-actions :deep(button) {
  display: flex;
  align-items: center;
  gap: 6px;
  min-height: 34px;
  padding-inline: 16px;
  color: #0a84ff;
}

.phone-contact-editor__name-list,
.phone-contact-editor__number-list,
.phone-contact-editor__notes-list {
  margin: 0 0 16px;
  color: #fff;
}

.phone-contact-editor__name-list :deep(ul),
.phone-contact-editor__number-list :deep(ul),
.phone-contact-editor__notes-list :deep(ul) {
  overflow: hidden;
  border-radius: 24px;
  background: #2c2c2e;
}

.phone-contact-editor__name-list :deep(li),
.phone-contact-editor__number-list :deep(li),
.phone-contact-editor__notes-list :deep(li) {
  min-height: 58px;
  background: transparent;
}

.phone-contact-editor__name-list :deep(input),
.phone-contact-editor__number-list :deep(input),
.phone-contact-editor__notes-list :deep(textarea) {
  color: #fff;
  font-size: 17px;
}

.phone-contact-editor__name-list :deep(input::placeholder),
.phone-contact-editor__number-list :deep(input::placeholder),
.phone-contact-editor__notes-list :deep(textarea::placeholder) {
  color: #a7a7ac;
  opacity: 1;
}

.phone-contact-editor__notes-list :deep(textarea) {
  min-height: 112px;
  resize: none;
  line-height: 1.35;
}

.phone-contact-editor__add-icon {
  display: grid;
  width: 25px;
  height: 25px;
  place-items: center;
  border-radius: 50%;
  color: #fff;
  background: #30d158;
}

.phone-contact-editor__error {
  margin: -4px 14px 16px;
  color: #ff6961;
  font-size: 13px;
  text-align: center;
}

.phone-contact-editor__delete {
  width: 100%;
  min-height: 56px;
  border-radius: 22px;
  color: #ff453a;
  background: #2c2c2e;
  font-size: 16px;
}

.phone-contact-editor--light {
  color: #111;
  background: #e5e5ea;
}

.phone-contact-editor--light .phone-contact-editor__header {
  background: linear-gradient(180deg, #e5e5ea 72%, rgba(229, 229, 234, 0));
}

.phone-contact-editor--light .phone-contact-editor__header-button {
  border-color: rgba(60, 60, 67, 0.18);
  color: #111;
  background: rgba(255, 255, 255, 0.62);
}

.phone-contact-editor--light .phone-contact-editor__name-list,
.phone-contact-editor--light .phone-contact-editor__number-list,
.phone-contact-editor--light .phone-contact-editor__notes-list {
  color: #111;
}

.phone-contact-editor--light .phone-contact-editor__name-list :deep(ul),
.phone-contact-editor--light .phone-contact-editor__number-list :deep(ul),
.phone-contact-editor--light .phone-contact-editor__notes-list :deep(ul),
.phone-contact-editor--light .phone-contact-editor__delete {
  background: rgba(255, 255, 255, 0.72);
}

.phone-contact-editor--light .phone-contact-editor__name-list :deep(input),
.phone-contact-editor--light .phone-contact-editor__number-list :deep(input),
.phone-contact-editor--light .phone-contact-editor__notes-list :deep(textarea) {
  color: #111;
}

@media (max-width: 360px) {
  .phone-detail-header {
    grid-template-columns: 44px minmax(0, 1fr) minmax(44px, auto);
    gap: 5px;
  }

  .phone-detail-edit {
    min-width: 74px;
    padding: 0 12px;
    font-size: 14px;
  }

  .phone-contact-actions {
    grid-template-columns: repeat(4, 56px);
    gap: 9px;
  }

  .phone-profile-action {
    width: 56px;
    min-width: 56px;
    height: 56px;
    min-height: 56px;
  }
}

.phone-calls-app button:not(:disabled),
.phone-contact-editor button:not(:disabled) {
  cursor: pointer;
}

.phone-recents-filter button,
.phone-recents-search,
.phone-contacts-search,
.phone-recent-row,
.phone-recent-info,
.phone-contacts-add,
.phone-my-card,
.phone-contact-row,
.phone-contact-index button,
.phone-keypad-call,
.phone-profile-action,
.phone-detail-header-button,
.phone-detail-edit,
.phone-profile-info-card > button,
.phone-profile-options-card > button,
.phone-profile-single-option > button,
.phone-call-more__item,
.phone-contact-editor__avatar,
.phone-contact-editor__header-button,
.phone-contact-editor__delete,
.phone-contact-editor__photo-actions :deep(button) {
  transition:
    color 160ms ease-out,
    background-color 160ms ease-out,
    border-color 160ms ease-out,
    box-shadow 160ms ease-out,
    filter 160ms ease-out,
    transform 160ms ease-out;
}

.phone-calls-app button:focus-visible,
.phone-contact-editor button:focus-visible {
  outline: 2px solid #64a8ff;
  outline-offset: 2px;
}

.phone-keypad-key:hover,
.phone-keypad-delete:hover {
  border-color: rgba(255, 255, 255, 0.14);
  background: linear-gradient(
    180deg,
    rgba(68, 68, 70, 0.94),
    rgba(38, 38, 40, 0.9)
  );
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.08),
    0 3px 9px rgba(0, 0, 0, 0.2);
  transform: translateY(-1px);
}

.phone-keypad-call:hover {
  border-color: rgba(151, 245, 161, 0.9);
  background: linear-gradient(180deg, #48aa54, #378c42);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.26),
    0 6px 16px rgba(52, 199, 89, 0.3);
  transform: translateY(-2px) scale(1.015);
}

.phone-in-call-keypad__grid button:hover {
  border-color: rgba(255, 255, 255, 0.22);
  background: linear-gradient(
    180deg,
    rgba(255, 255, 255, 0.2),
    rgba(255, 255, 255, 0.12)
  );
  box-shadow: 0 3px 9px rgba(10, 30, 80, 0.15);
  transform: translateY(-1px);
}

@media (hover: hover) and (pointer: fine) {
  .phone-keypad-suggestion:hover .phone-keypad-suggestion__copy strong {
    color: #68adff;
  }

  .phone-recents-filter button:not(.active):hover {
    background: rgba(118, 118, 128, 0.22);
  }

  .phone-recents-search:hover,
  .phone-contacts-search:hover {
    background: rgba(118, 118, 128, 0.24);
    box-shadow: inset 0 0 0 1px rgba(142, 142, 147, 0.18);
  }

  .phone-recent-row:hover,
  .phone-my-card:hover,
  .phone-contact-row:hover {
    border-radius: 14px;
    background: rgba(118, 118, 128, 0.12);
    box-shadow: inset 0 0 0 1px rgba(142, 142, 147, 0.08);
  }

  .phone-recent-info:hover,
  .phone-contacts-add:hover,
  .phone-contact-index button:hover {
    background: rgba(10, 132, 255, 0.16);
    color: #55aaff;
    transform: translateY(-1px);
  }

  .phone-call-action:not(:disabled):not(.phone-call-action--end):not(
      .phone-call-action--answer
    ):hover::before {
    background: rgba(170, 187, 231, 0.32);
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.12),
      0 4px 12px rgba(11, 23, 62, 0.16);
    transform: translateX(-50%) translateY(-1px) scale(1.012);
  }

  .phone-call-action--end:not(:disabled):hover::before {
    border-color: rgba(255, 190, 185, 0.92);
    background: #ff3b30;
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.2),
      0 5px 14px rgba(215, 45, 34, 0.34);
    transform: translateX(-50%) translateY(-1px) scale(1.012);
  }

  .phone-call-action--answer:not(:disabled):hover::before {
    border-color: rgba(190, 255, 198, 0.9);
    background: #3bc45d;
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.2),
      0 5px 14px rgba(52, 168, 83, 0.3);
    transform: translateX(-50%) translateY(-1px) scale(1.012);
  }

  .phone-call-more__item:not(:disabled):hover {
    border-color: rgba(140, 165, 229, 0.66) !important;
    background: rgba(49, 57, 84, 0.68) !important;
    transform: translateY(-1px);
  }

  .phone-detail-header-button:not(:disabled):hover,
  .phone-detail-edit:not(:disabled):hover {
    border-color: rgba(255, 255, 255, 0.22);
    background: rgba(37, 54, 66, 0.96);
    transform: translateY(-1px);
  }

  .phone-profile-action:not(:disabled):hover {
    border-color: rgba(100, 168, 255, 0.7);
    background: rgba(22, 92, 158, 0.84);
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.1),
      0 4px 12px rgba(5, 42, 78, 0.2);
    transform: translateY(-1px);
  }

  .phone-profile-options-card > button:not(:disabled):hover > span,
  .phone-profile-single-option > button:not(:disabled):hover > span {
    color: #64a8ff;
    transform: translateX(2px);
  }

  .phone-profile-info-card > button:not(:disabled):hover > svg {
    color: #64a8ff;
    filter: brightness(1.08);
    transform: translateX(1px);
  }

  .phone-contact-editor__avatar-wrap:not(
      .phone-contact-editor__avatar-wrap--has-photo
    ):hover
    .phone-contact-editor__avatar {
    border-color: rgba(255, 255, 255, 0.22);
    filter: brightness(1.06);
    transform: scale(1.012);
  }

  .phone-contact-editor__header-button:not(:disabled):hover,
  .phone-contact-editor__photo-actions :deep(button:not(:disabled):hover) {
    filter: brightness(1.08);
    transform: translateY(-1px);
  }

  .phone-contact-editor__delete:not(:disabled):hover {
    background: #38383a;
  }

  .phone-calls-app :deep([data-active-tab] button[aria-pressed='false']:hover) {
    background: rgba(118, 118, 128, 0.14);
    transform: translateY(-1px);
  }
}

@media (hover: none) {
  .phone-contact-editor__remove-photo {
    inset: auto 5px 5px auto;
    width: 44px !important;
    height: 44px !important;
    background: rgba(7, 35, 62, 0.86) !important;
    opacity: 1;
    pointer-events: auto;
    transform: none;
  }

  .phone-contact-editor__remove-photo > span {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .phone-detail-header,
  .phone-calls-app button,
  .phone-contact-editor button {
    transition-duration: 1ms;
    transition-delay: 0ms;
  }
}

.phone-app--light .phone-recents-filter,
.phone-app--light .phone-recents-search,
.phone-app--light .phone-contacts-add,
.phone-app--light .phone-contacts-search,
.phone-app--light .phone-recent-info,
.phone-app--light .phone-contact-actions button,
.phone-app--light .phone-own-profile-card,
.phone-app--light .phone-history-card {
  background: rgba(118, 118, 128, 0.1);
}

.phone-app--light .phone-keypad-suggestion {
  border-color: rgba(60, 60, 67, 0.1);
  color: #111;
  background: rgba(229, 229, 234, 0.88);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.72),
    0 4px 12px rgba(60, 60, 67, 0.12);
}

.phone-app--light .phone-keypad-suggestion__copy small {
  color: #6e6e73;
}

.phone-app--light .phone-keypad-key,
.phone-app--light .phone-keypad-delete {
  border-color: rgba(60, 60, 67, 0.1);
  background: linear-gradient(
    180deg,
    rgba(255, 255, 255, 0.9),
    rgba(229, 229, 234, 0.88)
  );
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.72),
    0 5px 14px rgba(60, 60, 67, 0.14);
  color: #000;
}

.phone-app--light .phone-keypad-key:active,
.phone-app--light .phone-keypad-delete:active {
  background: #d1d1d6;
}

.phone-app--light .phone-keypad-key:hover,
.phone-app--light .phone-keypad-delete:hover {
  border-color: rgba(60, 60, 67, 0.12);
  background: linear-gradient(
    180deg,
    rgba(248, 248, 250, 0.94),
    rgba(222, 222, 227, 0.9)
  );
}
</style>
