<script setup>
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { useRouter } from 'vue-router'
import { useAuthStore } from '../stores/auth'
import { api } from '../lib/api'
import SvgIcon from '../components/SvgIcon.vue'
import { displayInitialFrom } from '../lib/display'
import { homePath, loginPath } from '../lib/paths'
import { toApiUrl } from '../lib/runtime'
import { useToast } from '../composables/useToast'
import keyIcon from '../assets/icons/key.svg'
import logoutIcon from '../assets/icons/logout.svg'
import openInNewIcon from '../assets/icons/open_in_new.svg'

const router = useRouter()
const auth = useAuthStore()
const toast = useToast()

const error = ref('')
const saving = ref(false)
const passwordSaving = ref(false)
const nickname = ref('')
const nicknameError = ref('')
const previewUrl = ref('')
const avatarFile = ref(null)
const removeAvatar = ref(false)
const fileInput = ref(null)
const currentPassword = ref('')
const nextPassword = ref('')
const nextPasswordConfirm = ref('')
const currentPasswordError = ref('')
const nextPasswordError = ref('')
const activeModal = ref('')
const nicknameDraft = ref('')
const nicknameDraftError = ref('')
const nicknameInput = ref(null)
const currentPasswordInput = ref(null)

watch(error, (message) => {
  if (!message) return
  toast.error(message)
  error.value = ''
})

watch(
  () => auth.user,
  (user) => {
    nickname.value = user?.nickname || ''
    if (!activeModal.value || activeModal.value !== 'nickname') {
      nicknameDraft.value = user?.nickname || ''
    }
  },
  { immediate: true }
)

const avatarUrl = computed(() => {
  if (previewUrl.value) return previewUrl.value
  if (removeAvatar.value) return ''
  if (!auth.user?.avatarSrc) return ''
  return toApiUrl(auth.user.avatarSrc)
})

const authReady = computed(() => auth.hydrated)
const displayInitial = computed(() => displayInitialFrom(auth.user?.nickname, auth.user?.email, 'U'))
const authEmail = computed(() => auth.user?.email || '')
const nicknameUpdatedAt = computed(() => Number(auth.user?.nicknameUpdatedAt || 0))
const nicknameChangeAvailableAt = computed(() => Number(auth.user?.nicknameChangeAvailableAt || 0))
const nicknameChangeIntervalMs = computed(() => Number(auth.user?.nicknameChangeIntervalMs || 0))
const nicknameChangeIntervalLabel = computed(() => String(auth.user?.nicknameChangeIntervalLabel || '2주'))
const canChangeNicknameNow = computed(() => {
  if (nicknameChangeIntervalMs.value <= 0) return true
  if (!nicknameUpdatedAt.value) return true
  return Date.now() >= nicknameChangeAvailableAt.value
})
onMounted(async () => {
  if (!auth.hydrated) await auth.refresh()
  if (!auth.user) {
    router.replace(loginPath())
    return
  }
  nickname.value = auth.user?.nickname || ''
  nicknameDraft.value = auth.user?.nickname || ''
  removeAvatar.value = false
  window.addEventListener('keydown', handleWindowKeydown)
})

onBeforeUnmount(() => {
  if (previewUrl.value) URL.revokeObjectURL(previewUrl.value)
  window.removeEventListener('keydown', handleWindowKeydown)
})

function formatDateTime(timestamp) {
  if (!timestamp) return '제한 없음'
  return new Intl.DateTimeFormat('ko-KR', {
    year: 'numeric',
    month: 'short',
    day: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
  }).format(timestamp)
}

function handleWindowKeydown(event) {
  if (event.key !== 'Escape' || !activeModal.value) return
  closeActiveModal()
}

function closeActiveModal() {
  if (activeModal.value === 'nickname') closeNicknameModal()
  if (activeModal.value === 'password') closePasswordModal()
}

function openAvatarPicker() {
  fileInput.value?.click()
}

function onAvatarChange(e) {
  const file = e.target.files && e.target.files[0]
  if (!file) return

  error.value = ''
  removeAvatar.value = false
  avatarFile.value = file
  if (previewUrl.value) URL.revokeObjectURL(previewUrl.value)
  previewUrl.value = URL.createObjectURL(file)
  saveAvatarChanges()
}

function clearProfileFieldErrors() {
  nicknameError.value = ''
  nicknameDraftError.value = ''
}

function clearPasswordFieldErrors() {
  currentPasswordError.value = ''
  nextPasswordError.value = ''
}

function clearAvatar() {
  error.value = ''
  avatarFile.value = null
  removeAvatar.value = true
  if (previewUrl.value) {
    URL.revokeObjectURL(previewUrl.value)
    previewUrl.value = ''
  }
  if (fileInput.value) fileInput.value.value = ''
  saveAvatarChanges()
}

async function saveProfile(nextNickname = nickname.value) {
  error.value = ''
  clearProfileFieldErrors()

  if (String(nextNickname || '').trim().length < 2) {
    nicknameError.value = '닉네임은 2자 이상 입력해주세요.'
    nicknameDraftError.value = nicknameError.value
    error.value = '닉네임을 확인해주세요.'
    return false
  }

  saving.value = true
  try {
    const fd = new FormData()
    fd.append('nickname', String(nextNickname || '').trim())
    if (avatarFile.value) fd.append('avatar', avatarFile.value)
    if (removeAvatar.value) fd.append('removeAvatar', '1')

    const res = await fetch(toApiUrl('/api/auth/profile'), {
      method: 'POST',
      credentials: 'include',
      body: fd,
    })
    const data = await res.json()
    if (!res.ok) {
      const requestError = new Error('profile_update_failed')
      requestError.data = data
      requestError.status = res.status
      throw requestError
    }
    auth.user = data.user
    nickname.value = data.user?.nickname || ''
    nicknameDraft.value = data.user?.nickname || ''
    avatarFile.value = null
    removeAvatar.value = false
    if (previewUrl.value) {
      URL.revokeObjectURL(previewUrl.value)
      previewUrl.value = ''
    }
    if (fileInput.value) fileInput.value.value = ''
    toast.success('프로필을 저장했어요.')
    return true
  } catch (e2) {
    const code = e2?.data?.error
    if (code === 'nickname_taken') {
      nicknameError.value = '이미 사용 중인 닉네임입니다.'
      nicknameDraftError.value = nicknameError.value
      error.value = '닉네임이 이미 사용 중이에요.'
    } else if (code === 'nickname_reserved') {
      nicknameError.value = '운영자/관리자처럼 혼동될 수 있는 닉네임은 사용할 수 없어요.'
      nicknameDraftError.value = nicknameError.value
      error.value = '사용할 수 없는 닉네임이에요.'
    } else if (code === 'nickname_change_locked') {
      const intervalLabel = String(e2?.data?.nicknameChangeIntervalLabel || nicknameChangeIntervalLabel.value || '2주')
      nicknameDraftError.value = `닉네임은 ${intervalLabel}에 한 번만 바꿀 수 있어요. ${formatDateTime(e2?.data?.nicknameChangeAvailableAt)} 이후 다시 시도해주세요.`
      error.value = '닉네임 변경 가능 시점이 아직 아니에요.'
    } else {
      error.value = '프로필 저장에 실패했어요.'
    }
    return false
  } finally {
    saving.value = false
  }
}

async function saveNickname() {
  const ok = await saveProfile(nicknameDraft.value)
  if (!ok) return
  closeNicknameModal()
}

async function saveAvatarChanges() {
  await saveProfile(nickname.value)
}

async function savePassword() {
  error.value = ''
  clearPasswordFieldErrors()

  if (nextPassword.value.length < 6) {
    nextPasswordError.value = '새 비밀번호는 6자 이상 입력해주세요.'
    error.value = '새 비밀번호를 확인해주세요.'
    return
  }

  if (nextPassword.value !== nextPasswordConfirm.value) {
    nextPasswordError.value = '비밀번호 확인이 일치하지 않아요.'
    error.value = '비밀번호 확인이 일치하지 않아요.'
    return
  }

  passwordSaving.value = true
  try {
    const data = await api.changePassword({
      currentPassword: currentPassword.value,
      nextPassword: nextPassword.value,
    })
    auth.user = data.user
    toast.success('비밀번호를 변경했어요.')
    closePasswordModal()
  } catch (e2) {
    if (e2?.data?.error === 'invalid_current_password') {
      currentPasswordError.value = '현재 비밀번호가 일치하지 않아요.'
      error.value = '현재 비밀번호가 일치하지 않아요.'
    } else {
      error.value = '비밀번호 변경에 실패했어요.'
    }
  } finally {
    passwordSaving.value = false
  }
}

function openNicknameModal() {
  clearProfileFieldErrors()
  nicknameDraft.value = nickname.value
  activeModal.value = 'nickname'
  nextTick(() => {
    nicknameInput.value?.focus()
    nicknameInput.value?.select?.()
  })
}

function closeNicknameModal() {
  activeModal.value = ''
  nicknameDraftError.value = ''
  nicknameDraft.value = nickname.value
}

function openPasswordModal() {
  clearPasswordFieldErrors()
  currentPassword.value = ''
  nextPassword.value = ''
  nextPasswordConfirm.value = ''
  activeModal.value = 'password'
  nextTick(() => {
    currentPasswordInput.value?.focus()
  })
}

function closePasswordModal() {
  activeModal.value = ''
  clearPasswordFieldErrors()
  currentPassword.value = ''
  nextPassword.value = ''
  nextPasswordConfirm.value = ''
}

async function logout() {
  await auth.logout()
  toast.success('로그아웃했어요.')
  router.push(homePath())
}
</script>

<template>
  <section class="pageWrap">
    <header class="pageHead">
      <div class="pageHead__main">
        <div class="pageHead__eyebrow">Account</div>
        <h2 class="pageHead__title">설정</h2>
        <div class="pageHead__desc">닉네임은 변경은 쿨타임이 있으니 신중하게 설정해주세요.</div>
      </div>
    </header>

    <section v-if="!authReady" class="settingsScreen settingsScreen--loading">
      <div class="settingsLoading">계정 정보를 불러오고 있어요.</div>
    </section>

    <section v-else-if="auth.user" class="settingsScreen">
      <div class="settingsDeck">
        <article class="settingsThemeCard settingsThemeCard--hero">
          <div class="settingsThemeCard__eyebrow">Profile</div>
          <div class="settingsThemeCard__title">기본 계정 정보</div>

          <div class="settingsHero">
            <div class="settingsAvatarColumn">
              <div class="avatarButtonWrap">
                <button class="avatarButton" type="button" @click="openAvatarPicker">
                  <img v-if="avatarUrl" :src="avatarUrl" class="avatarButton__image" alt="avatar" draggable="false" />
                  <div v-else class="avatarButton__fallback">{{ displayInitial }}</div>
                  <div class="avatarButton__overlay">
                    <span>{{ avatarUrl ? '이미지 변경' : '이미지 추가' }}</span>
                  </div>
                </button>
                <button
                  v-if="avatarUrl || previewUrl"
                  class="avatarButton__remove"
                  type="button"
                  aria-label="프로필 이미지 삭제"
                  @click="clearAvatar"
                >
                  <svg viewBox="0 0 24 24" aria-hidden="true">
                    <path d="M6 6l12 12M18 6L6 18" />
                  </svg>
                </button>
              </div>
              <div v-if="auth.user.isAdmin" class="roleBadge">Administrator</div>
              <input ref="fileInput" class="hiddenInput" type="file" accept="image/*" :disabled="saving" @change="onAvatarChange" />
            </div>

            <div class="settingsHero__body">
              <div class="settingsSummaryList">
                <div class="settingsSummaryItem">
                  <div class="settingsSummaryItem__label">닉네임</div>
                  <div class="settingsSummaryItem__valueRow">
                    <div class="settingsSummaryItem__value">{{ nickname || '미설정' }}</div>
                    <button
                      v-if="canChangeNicknameNow"
                      class="settingsIconAction"
                      type="button"
                      aria-label="닉네임 변경"
                      title="닉네임 변경"
                      @click="openNicknameModal"
                    >
                      <SvgIcon :src="openInNewIcon" :size="18" />
                    </button>
                  </div>
                </div>

                <div class="settingsSummaryItem">
                  <div class="settingsSummaryItem__label">ID (이메일)</div>
                  <div class="settingsSummaryItem__valueRow">
                    <div class="settingsSummaryItem__value">{{ authEmail }}</div>
                  </div>
                </div>
              </div>

            </div>
          </div>
        </article>

        <article class="settingsThemeCard settingsThemeCard--compact">
          <div class="settingsThemeCard__eyebrow">Security</div>
          <div class="settingsThemeCard__title">보안 설정</div>
          <div class="settingsCompactRow">
            <div>
              <div class="settingsCompactRow__title">비밀번호</div>
              <div class="settingsCompactRow__desc">현재 비밀번호 확인 후 새 비밀번호로 변경합니다.</div>
            </div>
            <button class="settingsIconAction settingsIconAction--solid" type="button" aria-label="비밀번호 변경" title="비밀번호 변경" @click="openPasswordModal">
              <SvgIcon :src="keyIcon" :size="18" />
            </button>
          </div>
        </article>

        <article class="settingsThemeCard settingsThemeCard--compact">
          <div class="settingsThemeCard__eyebrow">Session</div>
          <div class="settingsThemeCard__title">계정 상태</div>
          <div class="settingsCompactList">
            <div class="settingsCompactRow">
              <div>
                <div class="settingsCompactRow__title">가입일</div>
                <div class="settingsCompactRow__desc">{{ formatDateTime(auth.user.createdAt) }}</div>
              </div>
            </div>
            <div class="settingsCompactRow">
              <div>
                <div class="settingsCompactRow__title">로그아웃</div>
                <div class="settingsCompactRow__desc">이 기기에서 현재 세션을 종료합니다.</div>
              </div>
              <button class="settingsIconAction settingsIconAction--solid" type="button" aria-label="로그아웃" title="로그아웃" @click="logout">
                <SvgIcon :src="logoutIcon" :size="18" />
              </button>
            </div>
          </div>
        </article>
      </div>
    </section>

    <div v-if="activeModal === 'nickname'" class="settingsModalOverlay" @click.self="closeNicknameModal">
      <div class="settingsModalCard" role="dialog" aria-modal="true" aria-labelledby="nicknameModalTitle">
        <div id="nicknameModalTitle" class="settingsModalCard__title">닉네임 변경</div>
        <div class="settingsModalCard__desc">
          닉네임은 공개 티어표의 작성자 이름으로 보이며,
          {{ nicknameChangeIntervalMs > 0 ? `한 번 변경하면 ${nicknameChangeIntervalLabel}이 지나야 다시 바꿀 수 있어요.` : '현재는 변경 주기 제한이 없습니다.' }}
        </div>
        <label class="field">
          <span class="field__label">새 닉네임</span>
          <input ref="nicknameInput" v-model="nicknameDraft" class="field__input" maxlength="40" placeholder="표시용 닉네임" />
          <span v-if="nicknameDraftError" class="field__error">{{ nicknameDraftError }}</span>
          <span class="field__hint">{{ nicknameDraft.length }}/40자</span>
        </label>
        <div class="settingsModalCard__actions">
          <button class="btn btn--ghost" type="button" @click="closeNicknameModal">취소</button>
          <button class="btn btn--save" type="button" :disabled="saving || !canChangeNicknameNow" @click="saveNickname">
            {{ saving ? '저장 중...' : '닉네임 저장' }}
          </button>
        </div>
      </div>
    </div>

    <div v-if="activeModal === 'password'" class="settingsModalOverlay" @click.self="closePasswordModal">
      <div class="settingsModalCard" role="dialog" aria-modal="true" aria-labelledby="passwordModalTitle">
        <div id="passwordModalTitle" class="settingsModalCard__title">비밀번호 변경</div>
        <div class="settingsModalCard__desc">현재 비밀번호를 확인한 뒤 새 비밀번호로 바꿉니다.</div>

        <div class="settingsModalFields">
          <label class="field">
            <span class="field__label">현재 비밀번호</span>
            <input
              ref="currentPasswordInput"
              v-model="currentPassword"
              class="field__input"
              type="password"
              autocomplete="current-password"
              maxlength="120"
              placeholder="현재 비밀번호"
            />
            <span v-if="currentPasswordError" class="field__error">{{ currentPasswordError }}</span>
          </label>

          <label class="field">
            <span class="field__label">새 비밀번호</span>
            <input
              v-model="nextPassword"
              class="field__input"
              type="password"
              autocomplete="new-password"
              maxlength="120"
              placeholder="새 비밀번호"
            />
            <span v-if="nextPasswordError" class="field__error">{{ nextPasswordError }}</span>
            <span class="field__hint">6~120자 입력 가능 · {{ nextPassword.length }}/120자</span>
          </label>

          <label class="field">
            <span class="field__label">새 비밀번호 확인</span>
            <input
              v-model="nextPasswordConfirm"
              class="field__input"
              type="password"
              autocomplete="new-password"
              maxlength="120"
              placeholder="새 비밀번호 확인"
            />
          </label>
        </div>

        <div class="settingsModalCard__actions">
          <button class="btn btn--ghost" type="button" @click="closePasswordModal">취소</button>
          <button class="btn btn--save" type="button" :disabled="passwordSaving" @click="savePassword">
            {{ passwordSaving ? '변경 중...' : '비밀번호 변경' }}
          </button>
        </div>
      </div>
    </div>
  </section>
</template>

<style scoped>
.settingsScreen {
  display: grid;
  gap: 24px;
  padding-top: 4px;
}

.settingsScreen--loading {
  min-height: 240px;
  align-items: center;
}

.settingsLoading {
  color: var(--theme-text-muted);
  font-size: 15px;
}

.settingsDeck {
  width: min(100%, 1040px);
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 20px;
}

.settingsThemeCard {
  display: grid;
  gap: 12px;
  min-width: 0;
  padding: 22px;
  border-radius: 24px;
  border: 1px solid var(--theme-border);
  background: var(--theme-pill-bg);
}

.settingsThemeCard--hero {
  grid-column: 1 / -1;
}

.settingsThemeCard--compact {
  grid-template-rows: auto auto minmax(0, 1fr);
}

.settingsThemeCard__eyebrow {
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--theme-text-soft);
}

.settingsThemeCard__title {
  font-size: 24px;
  font-weight: 800;
  color: var(--theme-text-strong);
  letter-spacing: -0.03em;
}

.settingsThemeCard__desc {
  color: var(--theme-text-muted);
  line-height: 1.6;
}

.settingsHero {
  display: grid;
  grid-template-columns: 160px minmax(0, 1fr);
  gap: 24px;
  align-items: start;
  padding-top: 4px;
}

.settingsAvatarColumn {
  display: grid;
  justify-items: center;
  gap: 12px;
}

.avatarButtonWrap {
  position: relative;
  width: 132px;
  height: 132px;
}

.avatarButton {
  position: relative;
  width: 132px;
  height: 132px;
  border: 1px solid var(--theme-border-strong);
  border-radius: 9999px;
  background: var(--theme-surface);
  color: var(--theme-text);
  overflow: hidden;
  cursor: pointer;
  display: grid;
  place-items: center;
}

.avatarButton__image {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.avatarButton__fallback {
  font-size: 34px;
  font-weight: 900;
  color: var(--theme-text);
}

.avatarButton__overlay {
  position: absolute;
  inset: auto 0 0 0;
  padding: 12px 10px;
  background: linear-gradient(180deg, transparent, rgba(0, 0, 0, 0.72));
  font-size: 12px;
  font-weight: 700;
  color: #fff;
}

.avatarButton__remove {
  position: absolute;
  top: 0;
  right: 0;
  width: 30px;
  height: 30px;
  border: 1px solid var(--theme-border-strong);
  border-radius: 999px;
  background: var(--theme-surface);
  color: var(--theme-text);
  display: grid;
  place-items: center;
  cursor: pointer;
}

.avatarButton__remove svg {
  width: 14px;
  height: 14px;
  stroke: currentColor;
  stroke-width: 2.1;
  fill: none;
  stroke-linecap: round;
}

.avatarButton__remove:hover {
  background: rgba(190, 24, 24, 0.88);
  color: var(--theme-accent-text);
}

.hiddenInput {
  display: none;
}

.settingsHero__body {
  display: grid;
  gap: 16px;
}

.settingsSummaryList {
  display: grid;
  gap: 12px;
}

.settingsSummaryItem {
  display: grid;
  gap: 6px;
  padding: 16px 18px;
  border-radius: 18px;
  border: 1px solid var(--theme-border);
  background: var(--theme-surface);
}

.settingsSummaryItem__label {
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--theme-text-soft);
}

.settingsSummaryItem__value {
  font-size: 18px;
  font-weight: 700;
  color: var(--theme-text-strong);
  word-break: break-word;
}

.settingsSummaryItem__valueRow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.settingsSummaryItem__meta {
  font-size: 13px;
  color: var(--theme-text-muted);
  line-height: 1.6;
}

.settingsActionRow {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
}

.settingsCompactList {
  display: grid;
  gap: 10px;
  height: 100%;
}

.settingsCompactRow {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  align-items: center;
  min-height: 100%;
  padding: 16px 18px;
  border-radius: 18px;
  border: 1px solid var(--theme-border);
  background: var(--theme-surface);
}

.settingsCompactRow__title {
  font-size: 16px;
  font-weight: 700;
  color: var(--theme-text-strong);
}

.settingsCompactRow__desc {
  margin-top: 4px;
  color: var(--theme-text-muted);
  line-height: 1.6;
  word-break: keep-all;
}

.field {
  display: grid;
  gap: 8px;
}

.field__label {
  font-size: 13px;
  color: var(--theme-text-muted);
}

.field__input {
  width: 100%;
  padding: 14px 16px;
  border: 1px solid var(--theme-border-strong);
  border-radius: 16px;
  background: var(--theme-surface);
  color: var(--theme-text);
  outline: none;
  font-size: 16px;
  letter-spacing: -0.02em;
}

.field__input:focus {
  border-color: rgba(96, 165, 250, 0.9);
}

.field__hint {
  font-size: 12px;
  color: var(--theme-text-soft);
}

.field__error {
  font-size: 12px;
  color: #ff7b7b;
  font-weight: 700;
}

.roleBadge {
  width: fit-content;
  padding: 6px 10px;
  border-radius: 999px;
  border: 1px solid rgba(96, 165, 250, 0.28);
  background: rgba(96, 165, 250, 0.1);
  color: var(--theme-text);
  font-size: 12px;
  font-weight: 700;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 18px;
  border-radius: 999px;
  border: 1px solid transparent;
  font-weight: 700;
  cursor: pointer;
}

.btn:disabled {
  opacity: 0.55;
  cursor: default;
}

.btn--save {
  border-color: rgba(76, 133, 245, 0.96);
  background: var(--theme-accent-bg);
  color: var(--theme-accent-text);
}

.btn--ghost {
  border-color: var(--theme-border-strong);
  background: var(--theme-surface);
  color: var(--theme-text);
}

.settingsIconAction {
  width: 42px;
  height: 42px;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 14px;
  border: 1px solid var(--theme-border-strong);
  background: var(--theme-surface);
  color: var(--theme-text);
  cursor: pointer;
}

.settingsIconAction:disabled {
  opacity: 0.5;
  cursor: default;
}

.settingsIconAction--solid {
  background: var(--theme-pill-bg);
}

.settingsModalOverlay {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: grid;
  place-items: center;
  padding: 24px;
  background: rgba(8, 11, 18, 0.54);
  backdrop-filter: blur(8px);
}

.settingsModalCard {
  width: min(100%, 520px);
  display: grid;
  gap: 16px;
  padding: 24px;
  border-radius: 24px;
  border: 1px solid var(--theme-border);
  background: var(--theme-surface);
}

.settingsModalCard__title {
  font-size: 22px;
  font-weight: 800;
  letter-spacing: -0.03em;
  color: var(--theme-text-strong);
}

.settingsModalCard__desc {
  color: var(--theme-text-muted);
  line-height: 1.6;
}

.settingsModalFields {
  display: grid;
  gap: 14px;
}

.settingsModalCard__actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  flex-wrap: wrap;
}

@media (max-width: 860px) {
  .settingsDeck {
    grid-template-columns: minmax(0, 1fr);
  }

  .settingsHero {
    grid-template-columns: minmax(0, 1fr);
  }

  .settingsAvatarColumn {
    justify-items: start;
  }
}

@media (max-width: 640px) {
  .settingsThemeCard {
    padding: 18px;
    border-radius: 20px;
  }

  .settingsCompactRow {
    flex-direction: column;
    align-items: flex-start;
  }

  .settingsModalOverlay {
    padding: 16px;
  }

  .settingsModalCard {
    padding: 20px;
    border-radius: 20px;
  }
}
</style>
