<script setup lang="ts">
import { kGlass, kRange } from 'konsta/vue'
import {
  BellOff,
  Bluetooth,
  Calculator,
  Camera,
  Flashlight,
  Moon,
  Pause,
  Plane,
  Play,
  RadioTower,
  Signal,
  SkipBack,
  SkipForward,
  Sun,
  TimerReset,
  Volume2,
  Wifi,
} from 'lucide-vue-next'
import {
  computed,
  nextTick,
  onBeforeUnmount,
  ref,
  watch,
  type CSSProperties,
} from 'vue'
import { useRouter } from 'vue-router'

import { usePhoneStore } from '@/stores/phone'
import { useMusicStore } from '@/stores/music'
import { useEasyShareStore } from '@/stores/easyshare'
import type { EasySharePayload } from '@/types/easyshare'
import { nuiCall } from '@/utils/nui'
import { bindPointerDragSession } from '@/utils/pointerDragSession'

const props = defineProps<{ opened: boolean }>()
const emit = defineEmits<{ close: [] }>()

type ConnectivityPreference =
  | 'airplaneMode'
  | 'bluetoothEnabled'
  | 'cellularEnabled'
  | 'focusMode'
  | 'wifiEnabled'

const phone = usePhoneStore()
const music = useMusicStore()
const easyShare = useEasyShareStore()
const router = useRouter()
const panel = ref<HTMLElement | null>(null)
const brightness = ref(phone.preferences.settings.screenBrightness)
const volume = ref(
  Math.round(
    (phone.preferences.settings.notificationVolume +
      phone.preferences.settings.ringtoneVolume) /
      2,
  ),
)
const flashlightActive = ref(false)
const flashlightPending = ref(false)
const easySharePending = ref(false)
const previousAlertVolume = ref(volume.value || 75)
const sliderDragActive = ref(false)
type SliderKind = 'brightness' | 'volume'
type SliderDrag = {
  animationFrame: number | null
  currentValue: number
  kind: SliderKind
  lastClientY: number
  pendingClientY: number
  pointerId: number
  pointerType: string
  stopMouse: () => void
  stopPointer: () => void
  target: HTMLElement
}
let sliderDrag: SliderDrag | null = null

const inactiveGlassColors = {
  bgIos: 'bg-[rgba(72,72,74,0.58)]',
  shadowIos: 'shadow-ios-dark-glass',
}
const focusColors = computed(() =>
  phone.preferences.settings.focusMode
    ? {
        bgIos: 'bg-[#5e5ce6]',
        shadowIos: 'shadow-ios-dark-glass',
      }
    : inactiveGlassColors,
)
const alertsMuted = computed(() => volume.value === 0)
const alertMuteColors = computed(() =>
  alertsMuted.value
    ? {
        bgIos: 'bg-white',
        shadowIos: 'shadow-ios-light-glass',
      }
    : inactiveGlassColors,
)
const flashlightColors = computed(() =>
  flashlightActive.value
    ? {
        bgIos: 'bg-white',
        shadowIos: 'shadow-ios-light-glass',
      }
    : inactiveGlassColors,
)
const brightnessStyle = computed<CSSProperties>(() => ({
  '--control-level': `${brightness.value}%`,
}))
const volumeStyle = computed<CSSProperties>(() => ({
  '--control-level': `${volume.value}%`,
}))

function togglePreference(key: ConnectivityPreference): void {
  phone.setPreference(key, !phone.preferences.settings[key])
}

function updateBrightness(event: Event): void {
  const nextValue = Number.parseInt(
    (event.target as HTMLInputElement).value,
    10,
  )
  brightness.value = nextValue
  phone.preferences.settings.screenBrightness = nextValue
}

function saveBrightness(event: Event): void {
  phone.setPreference(
    'screenBrightness',
    Number.parseInt((event.target as HTMLInputElement).value, 10),
  )
}

function updateVolume(event: Event): void {
  volume.value = Number.parseInt((event.target as HTMLInputElement).value, 10)
}

function saveVolume(event: Event): void {
  const nextValue = Number.parseInt(
    (event.target as HTMLInputElement).value,
    10,
  )
  if (nextValue > 0) previousAlertVolume.value = nextValue
  phone.setAlertVolumes(nextValue)
}

function toggleAlertMute(): void {
  if (alertsMuted.value) {
    volume.value = previousAlertVolume.value
  } else {
    previousAlertVolume.value = volume.value
    volume.value = 0
  }
  phone.setAlertVolumes(volume.value)
}

function sliderRange(kind: SliderKind): { maximum: number; minimum: number } {
  return kind === 'brightness'
    ? { maximum: 100, minimum: 10 }
    : { maximum: 100, minimum: 0 }
}

function applySliderValue(drag: SliderDrag, value: number): void {
  drag.currentValue = value
  if (drag.kind === 'brightness') {
    brightness.value = value
    phone.preferences.settings.screenBrightness = value
    return
  }
  volume.value = value
}

function updateSliderDrag(clientY: number, drag: SliderDrag): void {
  const rect = drag.target.getBoundingClientRect()
  const { maximum, minimum } = sliderRange(drag.kind)
  const deltaY = clientY - drag.lastClientY
  drag.lastClientY = clientY
  const nextValue =
    Math.round(
      Math.min(
        maximum,
        Math.max(
          minimum,
          drag.currentValue - (deltaY / rect.height) * (maximum - minimum),
        ),
      ) * 100,
    ) / 100
  applySliderValue(drag, nextValue)
}

function queueSliderDrag(clientY: number, drag: SliderDrag): void {
  drag.pendingClientY = clientY
  if (drag.animationFrame !== null) return
  drag.animationFrame = window.requestAnimationFrame(() => {
    drag.animationFrame = null
    if (sliderDrag !== drag) return
    updateSliderDrag(drag.pendingClientY, drag)
  })
}

function flushSliderDrag(clientY: number, drag: SliderDrag): void {
  drag.pendingClientY = clientY
  if (drag.animationFrame !== null) {
    window.cancelAnimationFrame(drag.animationFrame)
    drag.animationFrame = null
  }
  updateSliderDrag(drag.pendingClientY, drag)
}

function cancelSliderAnimation(drag: SliderDrag): void {
  if (drag.animationFrame === null) return
  window.cancelAnimationFrame(drag.animationFrame)
  drag.animationFrame = null
}

function bindSliderMouseFallback(drag: SliderDrag): () => void {
  let active = true
  const cleanup = (): void => {
    if (!active) return
    active = false
    window.removeEventListener('mousemove', onMouseMove, true)
    window.removeEventListener('mouseup', onMouseUp, true)
    window.removeEventListener('blur', onBlur, true)
  }
  const onMouseMove = (event: MouseEvent): void => {
    if (!active || sliderDrag !== drag) return
    queueSliderDrag(event.clientY, drag)
  }
  const onMouseUp = (event: MouseEvent): void => {
    if (!active || sliderDrag !== drag) return
    flushSliderDrag(event.clientY, drag)
    cleanup()
    finishSliderDrag(true)
  }
  const onBlur = (): void => {
    if (!active || sliderDrag !== drag) return
    cleanup()
    finishSliderDrag(true)
  }

  window.addEventListener('mousemove', onMouseMove, true)
  window.addEventListener('mouseup', onMouseUp, true)
  window.addEventListener('blur', onBlur, true)
  return cleanup
}

function continueSliderSurfaceDrag(event: MouseEvent | PointerEvent): void {
  const drag = sliderDrag
  if (!drag) return
  event.preventDefault()
  queueSliderDrag(event.clientY, drag)
}

function finishSliderSurfaceDrag(event: MouseEvent | PointerEvent): void {
  const drag = sliderDrag
  if (!drag) return
  event.preventDefault()
  flushSliderDrag(event.clientY, drag)
  finishSliderDrag(true)
}

function finishSliderDrag(save: boolean): void {
  const drag = sliderDrag
  if (!drag) return
  sliderDrag = null
  sliderDragActive.value = false
  cancelSliderAnimation(drag)
  drag.stopPointer()
  drag.stopMouse()
  if (!save) return
  if (drag.kind === 'brightness') {
    const nextValue = Math.round(brightness.value)
    brightness.value = nextValue
    phone.preferences.settings.screenBrightness = nextValue
    phone.setPreference('screenBrightness', nextValue)
    return
  }
  const nextValue = Math.round(volume.value)
  volume.value = nextValue
  if (nextValue > 0) previousAlertVolume.value = nextValue
  phone.setAlertVolumes(nextValue)
}

function startSliderDrag(kind: SliderKind, event: PointerEvent): void {
  if (event.button !== 0) return
  finishSliderDrag(true)
  const target = event.currentTarget as HTMLElement
  const pointerId = event.pointerId
  const initialValue = kind === 'brightness' ? brightness.value : volume.value
  const drag: SliderDrag = {
    animationFrame: null,
    currentValue: initialValue,
    kind,
    lastClientY: event.clientY,
    pendingClientY: event.clientY,
    pointerId,
    pointerType: event.pointerType,
    stopMouse: () => {},
    stopPointer: () => {},
    target,
  }
  sliderDrag = drag
  sliderDragActive.value = true
  applySliderValue(drag, initialValue)
  drag.stopPointer = bindPointerDragSession(window, pointerId, {
    cancel: () => {
      if (drag.pointerType === 'touch') {
        finishSliderDrag(true)
        return
      }
      drag.stopPointer()
      drag.stopPointer = () => {}
    },
    move: (moveEvent) => queueSliderDrag(moveEvent.clientY, drag),
    up: (upEvent) => {
      flushSliderDrag(upEvent.clientY, drag)
      finishSliderDrag(true)
    },
  })
  if (event.pointerType !== 'touch') {
    drag.stopMouse = bindSliderMouseFallback(drag)
  }
}

async function toggleFlashlight(): Promise<void> {
  if (flashlightPending.value) return
  const enabled = !flashlightActive.value
  flashlightActive.value = enabled
  flashlightPending.value = true
  const response = await nuiCall('camera:setFlash', { enabled })
  if (!response.success) flashlightActive.value = !enabled
  flashlightPending.value = false
}

async function shareOwnContact(): Promise<void> {
  if (easySharePending.value) return
  easySharePending.value = true
  const response = await nuiCall<EasySharePayload>('easyshare:own-contact')
  easySharePending.value = false
  if (!response.success || !response.data) {
    console.error(
      '[ControlCenter] Could not load own EasyShare contact.',
      response.error,
    )
    return
  }
  emit('close')
  easyShare.open(response.data)
  await easyShare.showNearby()
}

function openApp(path: string): void {
  emit('close')
  void router.push(path)
}

function openTimer(): void {
  emit('close')
  void router.push({ path: '/apps/clock', query: { section: 'timer' } })
}

watch(
  () => props.opened,
  (opened) => {
    if (!opened) {
      finishSliderDrag(true)
      return
    }
    brightness.value = phone.preferences.settings.screenBrightness
    volume.value = Math.round(
      (phone.preferences.settings.notificationVolume +
        phone.preferences.settings.ringtoneVolume) /
        2,
    )
    if (volume.value > 0) previousAlertVolume.value = volume.value
    void nextTick(() => panel.value?.focus({ preventScroll: true }))
  },
)

onBeforeUnmount(() => {
  finishSliderDrag(true)
  if (flashlightActive.value)
    void nuiCall('camera:setFlash', { enabled: false })
})
</script>

<template>
  <Transition name="control-center">
    <section
      v-if="opened"
      class="control-center"
      :class="{ 'control-center--slider-dragging': sliderDragActive }"
      role="dialog"
      aria-modal="true"
      :aria-label="phone.t('ControlCenter.label')"
    >
      <button
        class="control-center__backdrop"
        type="button"
        tabindex="-1"
        :aria-label="phone.t('ControlCenter.close')"
        @click="emit('close')"
      ></button>

      <div ref="panel" class="control-center__panel" tabindex="-1">
        <div class="control-center__top-grid">
          <k-glass
            class="control-center__connectivity"
            :colors="inactiveGlassColors"
            :highlight="false"
          >
            <button
              type="button"
              class="control-center__connectivity-button"
              :class="{
                'control-center__connectivity-button--airplane':
                  phone.preferences.settings.airplaneMode,
              }"
              :aria-label="phone.t('ControlCenter.airplaneMode')"
              :aria-pressed="phone.preferences.settings.airplaneMode"
              @click="togglePreference('airplaneMode')"
            >
              <Plane aria-hidden="true" />
            </button>
            <button
              type="button"
              class="control-center__connectivity-button"
              :class="{
                'control-center__connectivity-button--cellular':
                  phone.preferences.settings.cellularEnabled,
              }"
              :aria-label="phone.t('ControlCenter.cellular')"
              :aria-pressed="phone.preferences.settings.cellularEnabled"
              @click="togglePreference('cellularEnabled')"
            >
              <Signal aria-hidden="true" />
            </button>
            <button
              type="button"
              class="control-center__connectivity-button"
              :class="{
                'control-center__connectivity-button--wifi':
                  phone.preferences.settings.wifiEnabled,
              }"
              :aria-label="phone.t('ControlCenter.wifi')"
              :aria-pressed="phone.preferences.settings.wifiEnabled"
              @click="togglePreference('wifiEnabled')"
            >
              <Wifi aria-hidden="true" />
            </button>
            <button
              type="button"
              class="control-center__connectivity-button"
              :class="{
                'control-center__connectivity-button--bluetooth':
                  phone.preferences.settings.bluetoothEnabled,
              }"
              :aria-label="phone.t('ControlCenter.bluetooth')"
              :aria-pressed="phone.preferences.settings.bluetoothEnabled"
              @click="togglePreference('bluetoothEnabled')"
            >
              <Bluetooth aria-hidden="true" />
            </button>
          </k-glass>

          <k-glass
            class="control-center__media"
            :colors="inactiveGlassColors"
            :highlight="false"
          >
            <div class="control-center__media-copy">
              <span>{{ phone.t('ControlCenter.media') }}</span>
              <strong>{{
                music.currentTrack?.title ?? phone.t('ControlCenter.notPlaying')
              }}</strong>
              <small v-if="music.currentTrack">{{
                music.currentTrack.artist
              }}</small>
            </div>
            <div class="control-center__media-controls">
              <button
                type="button"
                :disabled="!music.currentTrack"
                :aria-label="phone.t('ControlCenter.previous')"
                @click="music.previous"
              >
                <SkipBack aria-hidden="true" />
              </button>
              <button
                type="button"
                :disabled="!music.currentTrack && !music.allTracks.length"
                :aria-label="
                  phone.t(
                    music.isPlaying ? 'Common.pause' : 'ControlCenter.play',
                  )
                "
                @click="music.toggle"
              >
                <Pause v-if="music.isPlaying" aria-hidden="true" />
                <Play v-else aria-hidden="true" />
              </button>
              <button
                type="button"
                :disabled="!music.currentTrack"
                :aria-label="phone.t('ControlCenter.next')"
                @click="music.next"
              >
                <SkipForward aria-hidden="true" />
              </button>
            </div>
          </k-glass>
        </div>

        <div class="control-center__middle-grid">
          <div class="control-center__round-control">
            <k-glass
              component="button"
              type="button"
              class="control-center__round-button"
              :class="{
                'control-center__round-button--light': alertsMuted,
              }"
              :colors="alertMuteColors"
              :aria-label="
                phone.t(
                  alertsMuted
                    ? 'ControlCenter.unmuteRingtone'
                    : 'ControlCenter.muteRingtone',
                )
              "
              :aria-pressed="alertsMuted"
              @click="toggleAlertMute"
            >
              <BellOff aria-hidden="true" />
            </k-glass>
          </div>

          <div class="control-center__round-control">
            <k-glass
              component="button"
              type="button"
              class="control-center__round-button"
              :colors="inactiveGlassColors"
              :disabled="easySharePending || !phone.device?.sim"
              :aria-label="phone.t('ControlCenter.easyShareContact')"
              @click="shareOwnContact"
            >
              <RadioTower aria-hidden="true" />
            </k-glass>
          </div>

          <k-glass
            class="control-center__slider control-center__slider--brightness"
            :colors="inactiveGlassColors"
            :highlight="false"
            :style="brightnessStyle"
            @pointerdown="startSliderDrag('brightness', $event)"
          >
            <span
              class="control-center__slider-level"
              aria-hidden="true"
            ></span>
            <k-range
              class="control-center__range"
              :value="brightness"
              :min="10"
              :max="100"
              :aria-label="phone.t('ControlCenter.brightness')"
              @input="updateBrightness"
              @change="saveBrightness"
            />
            <Sun
              class="control-center__slider-icon"
              fill="currentColor"
              aria-hidden="true"
            />
          </k-glass>

          <k-glass
            class="control-center__slider control-center__slider--volume"
            :colors="inactiveGlassColors"
            :highlight="false"
            :style="volumeStyle"
            @pointerdown="startSliderDrag('volume', $event)"
          >
            <span
              class="control-center__slider-level"
              aria-hidden="true"
            ></span>
            <k-range
              class="control-center__range"
              :value="volume"
              :min="0"
              :max="100"
              :aria-label="phone.t('ControlCenter.volume')"
              @input="updateVolume"
              @change="saveVolume"
            />
            <Volume2
              class="control-center__slider-icon"
              fill="currentColor"
              aria-hidden="true"
            />
          </k-glass>

          <k-glass
            component="button"
            type="button"
            class="control-center__focus-button"
            :colors="focusColors"
            :aria-label="phone.t('ControlCenter.focus')"
            :aria-pressed="phone.preferences.settings.focusMode"
            @click="togglePreference('focusMode')"
          >
            <Moon aria-hidden="true" />
            <span>{{ phone.t('ControlCenter.focus') }}</span>
          </k-glass>
        </div>

        <nav
          class="control-center__quick-actions"
          :aria-label="phone.t('ControlCenter.quickActions')"
        >
          <div class="control-center__quick-action">
            <k-glass
              component="button"
              type="button"
              class="control-center__quick-button"
              :class="{
                'control-center__quick-button--flashlight-active':
                  flashlightActive,
              }"
              :colors="flashlightColors"
              :disabled="flashlightPending"
              :aria-label="phone.t('ControlCenter.flashlight')"
              :aria-pressed="flashlightActive"
              @click="toggleFlashlight"
            >
              <Flashlight aria-hidden="true" />
            </k-glass>
            <span>{{ phone.t('ControlCenter.flashlight') }}</span>
          </div>
          <div class="control-center__quick-action">
            <k-glass
              component="button"
              type="button"
              class="control-center__quick-button"
              :colors="inactiveGlassColors"
              :aria-label="phone.t('ControlCenter.timer')"
              @click="openTimer"
            >
              <TimerReset aria-hidden="true" />
            </k-glass>
            <span>{{ phone.t('ControlCenter.timer') }}</span>
          </div>
          <div class="control-center__quick-action">
            <k-glass
              component="button"
              type="button"
              class="control-center__quick-button"
              :colors="inactiveGlassColors"
              :aria-label="phone.t('ControlCenter.camera')"
              @click="openApp('/apps/camera')"
            >
              <Camera aria-hidden="true" />
            </k-glass>
            <span>{{ phone.t('ControlCenter.camera') }}</span>
          </div>
          <div class="control-center__quick-action">
            <k-glass
              component="button"
              type="button"
              class="control-center__quick-button"
              :colors="inactiveGlassColors"
              :aria-label="phone.t('ControlCenter.calculator')"
              @click="openApp('/apps/calculator')"
            >
              <Calculator aria-hidden="true" />
            </k-glass>
            <span>{{ phone.t('ControlCenter.calculator') }}</span>
          </div>
        </nav>
      </div>

      <div
        v-if="sliderDragActive"
        class="control-center__slider-drag-surface"
        aria-hidden="true"
        @mousemove="continueSliderSurfaceDrag"
        @mouseup="finishSliderSurfaceDrag"
        @pointermove="continueSliderSurfaceDrag"
        @pointerup="finishSliderSurfaceDrag"
      ></div>
    </section>
  </Transition>
</template>

<style scoped>
.control-center {
  position: absolute;
  z-index: 95;
  inset: 0;
  overflow: hidden;
  color: #fff;
  isolation: isolate;
}

.control-center__backdrop {
  position: absolute;
  z-index: 0;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  background:
    radial-gradient(circle at 16% 12%, rgb(77 96 135 / 24%), transparent 46%),
    linear-gradient(180deg, #191b23 0%, #11131a 100%);
}

@supports (
  (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))
) {
  .control-center__backdrop {
    background:
      radial-gradient(circle at 16% 12%, rgb(77 96 135 / 14%), transparent 46%),
      linear-gradient(180deg, rgb(20 22 29 / 72%) 0%, rgb(13 15 21 / 86%) 100%);
    backdrop-filter: blur(32px) brightness(0.76) saturate(0.82);
    -webkit-backdrop-filter: blur(32px) brightness(0.76) saturate(0.82);
  }
}

.control-center__panel {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 100%;
  height: 100%;
  padding: 70px 18px 30px;
  outline: none;
  pointer-events: none;
  transform-origin: calc(100% - 38px) 18px;
}

.control-center__slider-drag-surface {
  position: absolute;
  z-index: 20;
  inset: 0;
  cursor: ns-resize;
  pointer-events: auto;
  touch-action: none;
}

.control-center__top-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  pointer-events: auto;
}

.control-center__connectivity,
.control-center__media {
  min-width: 0;
  height: 154px;
  border-radius: 34px;
}

.control-center__connectivity {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-template-rows: repeat(2, 1fr);
  gap: 10px;
  padding: 12px;
}

.control-center__connectivity-button {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  border: 0;
  border-radius: 50%;
  color: #fff;
  background: rgba(72, 72, 74, 0.64);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.14),
    0 2px 5px rgba(0, 0, 0, 0.28);
  transition:
    background 180ms ease,
    box-shadow 180ms ease,
    transform 160ms ease;
}

.control-center__connectivity-button--airplane {
  background: #ff9f0a;
}

.control-center__connectivity-button--cellular {
  background: #34c759;
}

.control-center__connectivity-button--wifi,
.control-center__connectivity-button--bluetooth {
  background: #0a84ff;
}

.control-center__connectivity-button:active,
.control-center__round-button:active,
.control-center__quick-button:active {
  transform: scale(0.92);
}

.control-center__connectivity-button svg {
  width: 27px;
  height: 27px;
  stroke-width: 2.3;
}

.control-center__connectivity-button:first-child svg {
  fill: currentcolor;
  stroke-width: 1.5;
}

.control-center__media {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 21px 18px 17px;
}

.control-center__media-copy {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.control-center__media-copy span {
  color: rgba(255, 255, 255, 0.66);
  font-size: 11px;
  font-weight: 600;
}

.control-center__media-copy strong {
  overflow: hidden;
  font-size: 17px;
  line-height: 1.2;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.control-center__media-controls {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.control-center__media-controls button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  padding: 0;
  border: 0;
  color: rgba(255, 255, 255, 0.88);
  background: transparent;
}

.control-center__media-controls button:nth-child(2) svg {
  width: 31px;
  height: 31px;
  fill: currentcolor;
}

.control-center__media-controls svg {
  width: 25px;
  height: 25px;
  fill: currentcolor;
}

.control-center__middle-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  grid-template-rows: repeat(2, 73px);
  gap: 10px;
  min-height: 156px;
  pointer-events: auto;
}

.control-center__round-control,
.control-center__quick-action {
  display: flex;
  min-width: 0;
  flex-direction: column;
  align-items: center;
  gap: 7px;
}

.control-center__round-control {
  justify-content: center;
}

.control-center__round-control > span,
.control-center__quick-action > span {
  width: 100%;
  overflow: hidden;
  color: rgba(255, 255, 255, 0.82);
  font-size: 10px;
  font-weight: 600;
  line-height: 1.15;
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.control-center__round-button {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 73px;
  height: 73px;
  border: 0;
  border-radius: 50%;
  color: #fff;
  transition: transform 160ms ease;
}

.control-center__round-button--light {
  color: #ff453a;
}

.control-center__focus-button {
  display: flex;
  grid-column: 1 / span 2;
  grid-row: 2;
  align-items: center;
  gap: 13px;
  min-width: 0;
  height: 73px;
  padding: 0 22px;
  border: 0;
  border-radius: 37px;
  color: #fff;
  font-size: 15px;
  font-weight: 650;
  transition: transform 160ms ease;
}

.control-center__focus-button:active {
  transform: scale(0.96);
}

.control-center__focus-button svg {
  width: 27px;
  height: 27px;
  fill: currentcolor;
}

.control-center__round-button svg,
.control-center__quick-button svg {
  width: 27px;
  height: 27px;
  stroke-width: 2;
}

.control-center__slider {
  position: relative;
  grid-row: 1 / span 2;
  height: 156px;
  overflow: hidden;
  border-radius: 38px;
  cursor: pointer;
  touch-action: none;
}

.control-center__slider--brightness {
  grid-column: 3;
}

.control-center__slider--volume {
  grid-column: 4;
}

.control-center__slider-level {
  position: absolute;
  z-index: 0;
  right: 0;
  bottom: 0;
  left: 0;
  height: var(--control-level);
  background: rgba(255, 255, 255, 0.96);
  transition: height 160ms cubic-bezier(0.2, 0.8, 0.2, 1);
  will-change: height;
}

.control-center--slider-dragging .control-center__slider-level {
  transition: none;
}

.control-center__range {
  position: absolute;
  z-index: 2;
  top: 50%;
  left: 50%;
  width: 172px;
  height: 58px !important;
  transform: translate(-50%, -50%) rotate(-90deg);
  pointer-events: none;
}

.control-center__range :deep(span) {
  opacity: 0;
}

.control-center__range :deep(input) {
  height: 58px !important;
}

.control-center__range :deep(input::-webkit-slider-thumb) {
  opacity: 0;
}

.control-center__range :deep(input::-moz-range-thumb) {
  opacity: 0;
}

.control-center__slider-icon {
  position: absolute;
  z-index: 3;
  bottom: 18px;
  left: 50%;
  width: 25px;
  height: 25px;
  color: #0a84ff;
  transform: translateX(-50%);
  pointer-events: none;
}

.control-center__quick-button.control-center__quick-button--flashlight-active {
  color: #bf5af2 !important;
}

.control-center__slider--brightness .control-center__slider-icon {
  color: #ffd60a;
}

.control-center__quick-actions {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
  pointer-events: auto;
}

.control-center__quick-button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 73px;
  height: 73px;
  border: 0;
  border-radius: 50%;
  color: #fff;
  transition: transform 160ms ease;
}

.control-center__quick-button:disabled {
  opacity: 0.72;
}

.control-center-enter-active,
.control-center-leave-active {
  transition: opacity 280ms ease;
}

.control-center-enter-active .control-center__panel {
  transition: transform 440ms cubic-bezier(0.16, 1, 0.3, 1);
}

.control-center-leave-active .control-center__panel {
  transition: transform 260ms cubic-bezier(0.7, 0, 0.84, 0);
}

.control-center-enter-from,
.control-center-leave-to {
  opacity: 0;
}

.control-center-enter-from .control-center__panel,
.control-center-leave-to .control-center__panel {
  transform: translate3d(28px, -22px, 0) scale(0.84);
}

@media (prefers-reduced-motion: reduce) {
  .control-center-enter-active,
  .control-center-leave-active,
  .control-center-enter-active .control-center__panel,
  .control-center-leave-active .control-center__panel,
  .control-center__connectivity-button,
  .control-center__round-button,
  .control-center__focus-button,
  .control-center__quick-button {
    transition-duration: 1ms;
  }
}
</style>
