/* widget_dailycal - 오늘의 대사 플로팅 위젯
   ── 색 ──
   위젯의 색은 모두 --dcw-* 변수로 정한다(아래 #dcw-root·#dcw-panel의 기본값). 기본값은 사이트 테마 색이고,
   위젯 설정에서 지정한 색은 서버가 `body #dcw-panel { --dcw-…: … }` 규칙으로 덮어쓴다(widget.php, settings.lib.php의 dcw_colors_css).
   설정 화면의 미리보기(settings_preview.php)도 같은 변수를 바꿔서 보여준다. 색을 새로 추가하면 settings.lib.php의 dcw_color_fields()에도 넣을 것. */
#dcw-root { display: contents; }
/* 위젯 열기 버튼(패널 밖)의 색 */
#dcw-root {
  --dcw-fab-bg: var(--btn-primary-bg, #64748b);
  --dcw-fab-text: var(--btn-primary-text, #fff);
}

/* 왼쪽 아래 통합 위젯 툴바(.widget-toolbar, left:1%/bottom:4%, 접힌 상태 폭 35px)
   바로 옆에 딱 붙이고, 버튼 모양도 widget-toolbar-toggle과 동일하게
   (35x35, radius 8px, 사각형) 맞춘다. 간격(10px)은 툴바 내부 gap 값과 동일. */
#dcw-fab {
  position: fixed;
  left: var(--dcw-left, calc(1% + 45px)); /* 통합 툴바가 보이지 않으면 JS가 1%로 바꿔 그 자리로 당긴다 */
  bottom: 4%;
  width: 35px;
  height: 35px;
  border: none;
  border-radius: 8px;
  background: var(--dcw-fab-bg);
  color: var(--dcw-fab-text);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: calc(var(--content-font-size, 15px) * 1.2);
  cursor: pointer;
  z-index: 99999;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
  /* left(위치)는 전환하지 않는다 — 툴바 유무에 따라 위치가 바뀔 때 미끄러지지 않고 처음부터 그 자리에 있던 것처럼 보이게 */
  transition: transform .2s, filter .2s, background-color .2s, box-shadow .2s, opacity .2s;
  visibility: hidden; /* 위치 계산이 끝나기 전에는 숨겨 둔다(JS가 dcw-ready를 붙이면 보임) */
}
#dcw-root.dcw-ready #dcw-fab { visibility: visible; }
#dcw-fab:hover { transform: scale(1.05); filter: brightness(1.1); }
/* 패널이 열리면 버튼 자리를 그대로 덮어버리므로 버튼은 숨긴다 */
#dcw-fab.dcw-fab-hidden { display: none; }

/* 패널이 열릴 땐 옆에 붙은 통합 위젯 툴바(.widget-toolbar, left:1%)까지 같이
   덮도록 왼쪽 시작점을 툴바와 맞춘다 — 패널의 z-index(99998)가 툴바(99990)보다
   높아서 그 위에 그대로 겹쳐 가려진다. */
#dcw-panel {
  position: fixed;
  left: var(--dcw-base, 1%);
  bottom: 4%;
  width: 380px;
  height: min(540px, calc(100vh - 80px)); /* 높이는 고정 — 대사가 짧아도 길어도 창 크기는 그대로고, 넘치면 안에서 스크롤된다 */
  background: var(--dcw-panel-bg);
  border: 1px solid var(--dcw-border);
  border-radius: 22px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.35);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  z-index: 99998;
  transform-origin: bottom left;
  transition: transform .22s ease, opacity .22s ease, visibility 0s;
  font-family: var(--content-font-family, 'Pretendard', sans-serif);
}
/* 닫힌 패널은 키보드로도 닿지 않도록 visibility까지 숨기되, 닫히는 애니메이션이 끝난 뒤에 적용한다. */
#dcw-panel.dcw-closed {
  transform: scale(.92) translateY(8px);
  opacity: 0;
  pointer-events: none;
  visibility: hidden;
  transition: transform .22s ease, opacity .22s ease, visibility 0s linear .22s;
}
/* 패널 안에서 쓰는 색의 기본값 — 사이트 테마 색. 위젯 설정에서 지정한 색은 `body #dcw-panel` 규칙이 이 값들을 덮어쓴다. */
#dcw-panel {
  --dcw-panel-bg: var(--card-bg-color, #111111);          /* 패널 배경 */
  --dcw-panel-text: var(--content-font-color, #f4f4f4);   /* 패널 글자(날짜·목록·버튼 아이콘 등) */
  --dcw-accent: var(--accent-color, #00d643);             /* 강조색 — 아래 챕터명·나레이션·이름·핸드아웃 제목·점의 기본값 */
  --dcw-border: var(--card-border-color, #2e2e2e);        /* 패널 테두리·목록 구분선·입력창 테두리 */
  --dcw-a-bg: var(--btn-primary-bg, #232323);             /* 왼쪽 말풍선(캐릭터 A) */
  --dcw-a-text: var(--btn-primary-text, #f4f4f4);
  --dcw-b-bg: var(--btn-accent-bg, #123a22);              /* 오른쪽 말풍선(캐릭터 B) */
  --dcw-b-text: var(--btn-accent-text, #f4f4f4);
  --dcw-temp-text: var(--dcw-panel-text);                 /* 추가 캐릭터 말풍선 글자 */
  --dcw-handout-text: var(--dcw-panel-text);              /* 핸드아웃 본문 */
  --dcw-handout-title: var(--dcw-accent);                 /* 핸드아웃 제목 */
  --dcw-narr-text: var(--dcw-accent);                     /* 나레이션 */
  --dcw-name-text: var(--dcw-accent);                     /* 캐릭터 이름 */
  --dcw-chip-text: var(--dcw-accent);                     /* 챕터 알약 글자 */
  --dcw-input-text: var(--dcw-panel-text);                /* 하단 입력창 글자 */
  --dcw-send-bg: var(--btn-accent-bg, #002b0f);           /* 입력창 안의 화살표 원 */
  --dcw-send-text: var(--btn-accent-text, #00d643);
  --dcw-dot: var(--dcw-accent);                           /* 오늘의 대사 점 */
}
/* 버튼·알약 같은 "유리" 조각의 바탕색 — 카드 배경 위에서 살짝 구분되는 정도 */
#dcw-panel { --dcw-glass: var(--form-bg-color, #1a1a1a); }
@supports (background: color-mix(in srgb, red 10%, blue)) {
  #dcw-panel { --dcw-glass: color-mix(in srgb, var(--dcw-panel-text) 9%, var(--dcw-panel-bg)); }
}
/* 핸드아웃과 추가 캐릭터 말풍선이 같이 쓰는 반투명 상자 바탕색 — a_devlog의 "정보" 칸처럼 바탕이 비치는 옅은 색(글자색을 5%만 섞은 색) */
#dcw-panel { --dcw-box: rgba(255, 255, 255, 0.04); --dcw-box-solid: var(--form-bg-color, #1a1a1a); }
@supports (background: color-mix(in srgb, red 10%, blue)) {
  #dcw-panel {
    --dcw-box: color-mix(in srgb, var(--dcw-panel-text) 5%, transparent);
    /* 같은 색을 카드 배경(패널 바탕) 위에 얹은 불투명한 색 — 말풍선 꼬리는 말풍선 바탕과 겹쳐 그려지므로, 반투명 색을 그대로 쓰면 겹친 곳만 진하게 보인다 */
    --dcw-box-solid: color-mix(in srgb, var(--dcw-panel-text) 5%, var(--dcw-panel-bg));
  }
}
/* 위 "유리"·"상자" 색에서 나오는 기본값(설정에서 색을 지정하면 그 색이 이긴다) */
#dcw-panel {
  --dcw-chip-bg: var(--dcw-glass);                        /* 챕터 알약·거르기·전체 버튼 바탕 */
  --dcw-temp-bg: var(--dcw-box-solid);                    /* 추가 캐릭터 말풍선 바탕 */
  --dcw-handout-bg: var(--dcw-box);                       /* 핸드아웃 바탕 */
  --dcw-input-bg: var(--dcw-glass);                       /* 하단 입력창 바탕 */
  --dcw-input-bg-hover: var(--dcw-glass);                 /* 하단 입력창 바탕(마우스를 올렸을 때) */
}
@supports (background: color-mix(in srgb, red 10%, blue)) {
  #dcw-panel {
    /* 입력창은 평소에는 살짝 밝은 반투명, 마우스를 올리면 원래의 "유리" 색이 된다 */
    --dcw-input-bg: color-mix(in srgb, color-mix(in srgb, var(--dcw-glass) 94%, #fff) 55%, transparent);
    --dcw-input-bg-hover: color-mix(in srgb, var(--dcw-glass) 55%, transparent);
  }
}

/* 상단: 대사창 위에 떠 있는 헤더. 왼쪽 접기 버튼, 가운데 참여 캐릭터 사진과 그 위에 겹친 챕터명 알약.
   배경 막대와 아래 선은 없고, 위쪽에만 연한 그라데이션을 깔아서 그 밑을 지나는 대사가 흐려 보이게 한다. */
#dcw-head {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 3;
  display: grid;
  grid-template-columns: 52px 1fr 52px;
  align-items: start;
  padding: 10px 10px 22px;
  border: 0;
  border-radius: 21px 21px 0 0; /* 패널 모서리(22px − 테두리 1px)와 같게 — 패널의 둥근 잘라내기가 안 먹는 브라우저에서도 헤더 바탕이 모서리 밖으로 삐져나오지 않게 */
  background: linear-gradient(to bottom, var(--dcw-panel-bg) 0, transparent 100%);
  pointer-events: none;
}
@supports (background: color-mix(in srgb, red 10%, blue)) {
  #dcw-head { background: linear-gradient(to bottom, color-mix(in srgb, var(--dcw-panel-bg) 72%, transparent) 0, transparent 100%); }
}
#dcw-head > * { pointer-events: auto; grid-row: 1; }
#dcw-close { grid-column: 1; }
#dcw-head > span { grid-column: 3; display: flex; justify-content: flex-end; }
#dcw-contact, #dcw-list-title { grid-column: 2; min-width: 0; }
/* 대사 목록 화면의 제목 — 채팅 화면의 캐릭터 사진·챕터명 자리에 대신 나온다(한 챕터만 모아 볼 때는 그 챕터명) */
#dcw-list-title {
  display: none;
  height: 46px;
  padding: 0 4px;
  overflow: hidden;
  text-overflow: ellipsis; /* 긴 챕터명은 한 줄로 줄인다 */
  white-space: nowrap;
  text-align: center;
  line-height: 46px;
  font-size: 17px;
  font-weight: 700;
  color: var(--dcw-panel-text);
}
/* 한 챕터만 모아 볼 때 오른쪽에 나오는, 전체 목록으로 돌아가는 알약 버튼 */
#dcw-list-all {
  display: none;
  height: 32px;
  margin-top: 7px;
  padding: 0 14px;
  border: 0;
  border-radius: 999px;
  background: var(--dcw-chip-bg);
  color: var(--dcw-chip-text);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.18);
}
#dcw-panel.dcw-view-list.dcw-list-filtered #dcw-list-all { display: inline-flex; align-items: center; }

/* 오른쪽 위 거르기 버튼(목록 화면에서만, 한 챕터만 모아 볼 때는 "전체"가 대신 나온다)과 태그 메뉴.
   태그로 거르는 중이면 버튼이 강조색이 되고 제목 자리에 그 태그가 나온다. */
#dcw-filter {
  display: none;
  width: 42px;
  height: 42px;
  margin-top: 2px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--dcw-chip-bg);
  color: var(--dcw-panel-text);
  font-size: 15px;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.18);
}
#dcw-panel.dcw-view-list:not(.dcw-list-filtered) #dcw-filter { display: flex; }
#dcw-filter:hover { filter: brightness(1.06); }
#dcw-panel.dcw-tag-on #dcw-filter { color: var(--dcw-accent); }
#dcw-filter-menu {
  position: absolute;
  top: 56px;
  right: 10px;
  z-index: 6;
  min-width: 170px;
  max-width: 250px;
  max-height: 270px;
  overflow-y: auto;
  padding: 6px;
  border: 1px solid var(--dcw-border);
  border-radius: 16px;
  background: var(--dcw-panel-bg);
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.35);
  scrollbar-width: thin;
}
#dcw-filter-menu[hidden] { display: none; }
.dcw-fm-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 9px 10px;
  border: 0;
  border-radius: 10px;
  background: none;
  color: var(--dcw-panel-text);
  font: inherit;
  font-size: 14px;
  text-align: left;
  cursor: pointer;
}
.dcw-fm-item:hover, .dcw-fm-item:focus-visible { background: var(--dcw-glass); }
.dcw-fm-check { flex: none; width: 14px; font-size: 12px; color: var(--dcw-accent); visibility: hidden; }
.dcw-fm-item[aria-checked="true"] .dcw-fm-check { visibility: visible; }
.dcw-fm-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dcw-fm-count { flex: none; font-size: 12.5px; opacity: .55; }
.dcw-fm-empty { padding: 12px 10px; font-size: 13px; opacity: .6; text-align: center; }
/* 목록 화면에서는 줄 글씨가 제목·버튼 밑으로 비쳐 보이지 않도록 헤더 뒤를 거의 막아 두고 아래쪽만 흐려지게 한다 */
#dcw-panel.dcw-view-list #dcw-head {
  background: linear-gradient(to bottom, var(--dcw-panel-bg) 0, var(--dcw-panel-bg) 66%, transparent 100%);
}
#dcw-panel.dcw-view-list #dcw-contact { display: none; }
#dcw-panel.dcw-view-list #dcw-list-title { display: block; }
#dcw-close {
  width: 42px;
  height: 42px;
  margin-top: 2px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none; /* 배경과 그림자는 없다 — 마우스를 올리거나 눌러도 마찬가지 */
  color: var(--dcw-panel-text);
  font-size: 17px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: none;
}
#dcw-close:hover, #dcw-close:active, #dcw-close:focus {
  background: none;
  box-shadow: none;
  filter: none;
}
#dcw-contact { display: flex; flex-direction: column; align-items: center; min-width: 0; }
/* 사진은 아래 챕터명 알약보다 위에 올라온다(z-index) — 알약은 사진 아래쪽에 살짝 겹쳐 놓인다 */
#dcw-avatars { position: relative; z-index: 1; display: flex; align-items: center; justify-content: center; }
/* 테두리는 없다(border:0). 챕터명 알약과 같은 그림자만 둔다.
   ⚠ 예전에 있던 테두리 규칙을 지우기만 하면 안 된다 — 이 위젯은 코어가 붙이는 버전 없는 style.css와 우리가 붙이는 버전 붙은 style.css가
   함께 로드되는데, 브라우저에 옛날 버전 없는 파일이 캐시돼 있으면 거기 남은 옛 테두리 규칙이 계속 적용된다. 그래서 0으로 덮어쓴다. */
#dcw-avatars .dcw-avatar { border: 0; box-shadow: 0 1px 6px rgba(0, 0, 0, 0.18); }
#dcw-avatars .dcw-avatar + .dcw-avatar { margin-left: -14px; }
.dcw-avatar-more { font-size: 13px; font-weight: 700; color: var(--dcw-a-text); } /* 사진이 많을 때 마지막 칸의 "+N" */
#dcw-contact-name {
  position: relative;
  margin-top: -2px;
  max-width: 100%;
  padding: 3px 12px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  border: 0;
  border-radius: 999px;
  background: var(--dcw-chip-bg);
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.18);
  font-family: var(--content-font-family, 'Pretendard', sans-serif);
  font-size: var(--dcw-title-size, 14px);
  font-weight: 600;
  line-height: 1.35;
  text-decoration: none;
  cursor: pointer;
  color: var(--dcw-chip-text);
}
#dcw-contact-name i { margin-left: 4px; font-size: .6em; vertical-align: middle; opacity: .6; }
#dcw-body {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  border-radius: 21px; /* 위 헤더와 같은 이유 — 스포일러 블러 같은 바탕이 아래쪽 모서리 밖으로 삐져나오지 않게 */
  /* 위·아래는 떠 있는 헤더와 입력창이 가리는 높이만큼 비워 둔다 */
  padding: 90px 16px 72px;
  scrollbar-width: none; /* 아이폰 메시지처럼 스크롤바는 보이지 않게 */
}
#dcw-body::-webkit-scrollbar { display: none; }
/* 채팅 화면과 대사 목록 화면은 옆으로 살짝 밀리며 서로 교체된다. 안 보이는 쪽은 visibility로 키보드·스크린리더에서도 숨긴다. */
#dcw-body, #dcw-foot { transition: opacity .22s ease, transform .22s ease, visibility 0s; }
#dcw-panel.dcw-view-list #dcw-body {
  opacity: 0;
  visibility: hidden;
  transform: translateX(18px);
  transition: opacity .22s ease, transform .22s ease, visibility 0s linear .22s;
}
#dcw-panel.dcw-view-list #dcw-foot {
  opacity: 0;
  visibility: hidden;
  transform: translateY(10px);
  transition: opacity .22s ease, transform .22s ease, visibility 0s linear .22s;
}

/* 대사 목록 — 아이메시지의 대화 목록처럼 한 줄에 사진·챕터명·날짜·미리보기. 헤더가 위에 떠 있으므로 위쪽을 비워 둔다. */
#dcw-list {
  position: absolute;
  inset: 0;
  z-index: 1;
  overflow-y: auto;
  border-radius: 21px;
  padding: 66px 0 14px;
  scrollbar-width: none;
  opacity: 0;
  visibility: hidden;
  transform: translateX(-18px);
  transition: opacity .22s ease, transform .22s ease, visibility 0s linear .22s;
}
#dcw-list::-webkit-scrollbar { display: none; }
#dcw-panel.dcw-view-list #dcw-list {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition: opacity .22s ease, transform .22s ease, visibility 0s;
}
/* 한 줄의 구성은 아이메시지 대화 목록과 같다: 사진은 세로 가운데, 글은 위쪽부터(제목 줄 오른쪽 끝에 날짜와 ">"),
   줄 사이 구분선은 사진 오른쪽(글 시작 위치)부터 이어진다. 한 줄 높이는 미리보기가 짧아도 같게 맞춘다. */
.dcw-li {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 76px;
  padding: 0 16px; /* 사진 왼쪽의 좁은 여백에 "오늘의 대사" 점이 들어간다 */
  border: 0;
  background: none;
  color: var(--dcw-panel-text);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background-color .15s ease;
}
.dcw-li + .dcw-li::before { /* 16(왼쪽 여백) + 42(사진) + 12(간격) = 70 */
  content: '';
  position: absolute;
  top: 0;
  left: 70px;
  right: 16px;
  height: 1px;
  background: var(--dcw-border);
}
.dcw-li:hover, .dcw-li:focus-visible { background: var(--dcw-glass); }
.dcw-li.dcw-li-loading { opacity: .6; pointer-events: none; }
/* 오늘의 대사 — 안 읽은 메시지의 파란 점처럼 사진 왼쪽에 테마의 강조색 점 */
.dcw-li-dot {
  position: absolute;
  left: 4px; /* 왼쪽 여백(16px) 가운데 */
  top: 50%;
  width: 8px;
  height: 8px;
  margin-top: -4px;
  border-radius: 50%;
  background: var(--dcw-dot);
}
.dcw-li-avatar { display: flex; flex: none; }
.dcw-li-avatar .dcw-avatar { width: 42px; height: 42px; }
.dcw-li-avatar .dcw-avatar-default i { font-size: 18px; }
.dcw-li-main { flex: 1; min-width: 0; align-self: stretch; display: flex; flex-direction: column; gap: 1px; padding: 12px 0; }
.dcw-li-top { display: flex; align-items: center; gap: 6px; }
.dcw-li-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 15px; font-weight: 600; line-height: 1.35; }
.dcw-li-current .dcw-li-title { color: var(--dcw-accent); }
.dcw-li-eye { flex: none; font-size: 11px; opacity: .55; }
.dcw-li-date { flex: none; font-size: 12.5px; opacity: .55; }
.dcw-li-chev { flex: none; font-size: 11px; opacity: .4; }
.dcw-li-preview {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  font-size: 13px;
  line-height: 1.35;
  word-break: break-word;
  opacity: .6;
}
/* 스포일러 글은 미리보기를 흐리게만 보여준다(서버가 본문 대신 안내 문구를 내보낸다) */
.dcw-li-spoiler .dcw-li-preview { filter: blur(5px); user-select: none; }
#dcw-list-more {
  display: block;
  margin: 10px auto 0;
  padding: 6px 18px;
  border: 0;
  border-radius: 999px;
  background: var(--dcw-chip-bg);
  color: var(--dcw-panel-text);
  font: inherit;
  font-size: 12.5px;
  cursor: pointer;
}
#dcw-list-more[hidden] { display: none; }
#dcw-list-more:disabled { opacity: .5; cursor: default; }
#dcw-list-more:focus-visible, .dcw-li:focus-visible { outline: 2px solid var(--dcw-accent); outline-offset: -2px; }
/* 대사는 채팅 영역 맨 위(날짜 줄)에서 시작해 아래로 차례로 쌓인다. 창을 넘치면 스크롤이 생기고 JS가 새 대사를 따라간다.
   대사가 짧아도 스포일러 블러가 창 아래끝까지 덮이도록 내용 영역과 그 안의 래퍼가 남는 높이를 채운다. */
#dcw-content { flex: 1 0 auto; display: flex; flex-direction: column; }
#dcw-content > .dcw-spoiler-wrap { flex: 1 0 auto; }

/* 하단 입력창 모양 알약(다른 대사 보기) — 배경 막대 없이 대사 위에 떠 있고, 대사는 그 밑으로 스크롤된다 */
#dcw-foot {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 3;
  padding: 0 12px 12px;
  border: 0;
  background: none;
  pointer-events: none;
}
#dcw-shuffle {
  width: 100%;
  height: 42px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 4px 6px 4px 18px;
  border: 1px solid var(--dcw-border);
  border-radius: 21px;
  background: var(--dcw-input-bg);
  opacity: 1;
  color: var(--dcw-input-text);
  font: inherit;
  font-size: 14px;
  cursor: pointer;
  pointer-events: auto;
  box-shadow: none;
  transition: background-color .15s ease, opacity .15s ease;
}
/* 평소 색(--dcw-input-bg)과 마우스를 올렸을 때의 색(--dcw-input-bg-hover)은 #dcw-panel의 기본값을 참고 — 기본은 평소에 살짝 밝은 반투명, 올리면 원래 "유리" 색 */
#dcw-shuffle:hover { background: var(--dcw-input-bg-hover); filter: none; box-shadow: none; }
/* 회색 바탕은 반투명 + 블러 — 알약 밑으로 스크롤돼 지나가는 대사가 흐릿하게 비친다 */
#dcw-shuffle { -webkit-backdrop-filter: blur(14px) saturate(1.15); backdrop-filter: blur(14px) saturate(1.15); }
/* 안내 글은 투명도(opacity)를 쓰지 않고 바탕과 섞은 색으로 흐리게 보이게 한다 */
#dcw-send-label { opacity: .55; }
@supports (background: color-mix(in srgb, red 10%, blue)) {
  #dcw-send-label { opacity: 1; color: color-mix(in srgb, var(--dcw-input-text) 55%, var(--dcw-glass)); }
}
#dcw-shuffle.dcw-spinning { opacity: .6; pointer-events: none; }
.dcw-arrow {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--dcw-send-bg);
  color: var(--dcw-send-text);
  font-size: 13px;
  transition: transform .12s ease;
}
#dcw-shuffle:active .dcw-arrow { transform: scale(.88); }

#dcw-fab:focus-visible, #dcw-contact-name:focus-visible, #dcw-close:focus-visible, #dcw-list-all:focus-visible, #dcw-filter:focus-visible, #dcw-shuffle:focus-visible {
  outline: 2px solid var(--dcw-accent, var(--accent-color, #00d643)); /* #dcw-fab은 패널 밖이라 --dcw-accent가 없으면 테마 강조색 */
  outline-offset: 2px;
}
/* 대사창 맨 위의 오늘 날짜 — 대사와 같은 글꼴, 캐릭터 이름(.dcw-name)과 같은 크기의 회색 글씨 */
.dcw-date {
  margin-bottom: 10px;
  text-align: center;
  font-family: var(--content-font-family, 'Pretendard', sans-serif);
  font-size: var(--dcw-name-size, 10px);
  font-weight: 500;
  color: var(--dcw-panel-text);
  opacity: .55;
}
.dcw-empty { text-align: center; color: var(--gray-400, #a5a5a5); font-size: 13px; padding: 24px 8px; }

/* ── 스포일러 블러 ──
   대사 전체를 한꺼번에 흐리지 않고, 블록(말풍선·나레이션·핸드아웃·사진·이미지) 하나하나의 "안의 내용"만 흐린다.
   블록의 모양(말풍선 바탕과 꼬리·핸드아웃 상자)은 그대로 또렷하다.
   · 글: 글자를 투명하게 하고 같은 색의 번지는 그림자(text-shadow)만 남겨서 글자만 뭉개 보이게 한다. 그림자 색은 --dcw-ink(원래 글자색)이다.
   · 사진·이미지: 자기 테두리 안에서만 흐려지도록 상자(overflow:hidden)에 가두고 살짝 키워서, 가장자리가 번지거나 투명해지지 않게 한다.
   · "입력 중" 말풍선(.dcw-typing)은 흐리지 않는다 — 점이 그대로 보이고, 메시지로 바뀌는 순간부터 흐려진다.
   · 풀리는 것: 블록 중 어느 하나에 마우스를 올리면(또는 누르면 — .dcw-spoiler-open) 그 글의 블록 전체가 한꺼번에 풀린다.
     블록 밖의 빈 공간(패널 여백·말풍선 옆 빈 곳)에 올려서는 풀리지 않는다 — 블록 자신의 :hover만 본다.
   캐릭터 이름 줄은 흐리지 않는다. 가운데에 띄우던 "스포일러" 표시는 없다. */
.dcw-spoiler-wrap { position: relative; }
/* 예전에는 래퍼를 패널 가장자리까지 넓혀서(마이너스 margin·padding) 빈 공간에 올려도 풀리게 했고 대사 전체(.dcw-script)에 블러를 걸었다 —
   브라우저에 옛 CSS가 남아 있어도 그 규칙들이 적용되지 않도록 값을 0·none으로 덮어쓴다 */
.dcw-spoiler-wrap.dcw-blur { cursor: auto; margin: 0; padding: 0; }
.dcw-spoiler-wrap.dcw-blur .dcw-script { filter: none; user-select: auto; }
.dcw-spoiler-wrap.dcw-blur :is(.dcw-bubble, .dcw-line-narr, .dcw-handout, .dcw-photo, .dcw-line-image) { cursor: pointer; user-select: none; }
.dcw-bubble { --dcw-ink: var(--dcw-a-text); }
.dcw-line-right .dcw-bubble { --dcw-ink: var(--dcw-b-text); }
.dcw-line-narr { --dcw-ink: var(--dcw-narr-text); }
.dcw-handout-title { --dcw-ink: var(--dcw-handout-title); }
.dcw-line-temp .dcw-bubble { --dcw-ink: var(--dcw-temp-text); }
.dcw-handout-body { --dcw-ink: var(--dcw-handout-text); }
.dcw-spoiler-wrap.dcw-blur:not(.dcw-spoiler-open):not(:has(:is(.dcw-bubble, .dcw-line-narr, .dcw-handout, .dcw-photo, .dcw-line-image):hover)) :is(.dcw-bubble:not(.dcw-typing), .dcw-line-narr, .dcw-handout-title, .dcw-handout-body) {
  color: transparent;
  text-shadow: 0 0 7px var(--dcw-ink), 0 0 7px var(--dcw-ink);
}
/* 풀릴 때만 서서히(흐려질 때는 전환 없이 바로 — 입력 중 → 메시지로 바뀌는 순간에 글자가 잠깐 비치지 않게) */
.dcw-spoiler-wrap.dcw-blur.dcw-spoiler-open :is(.dcw-bubble, .dcw-line-narr, .dcw-handout-title, .dcw-handout-body),
.dcw-spoiler-wrap.dcw-blur:has(:is(.dcw-bubble, .dcw-line-narr, .dcw-handout, .dcw-photo, .dcw-line-image):hover) :is(.dcw-bubble, .dcw-line-narr, .dcw-handout-title, .dcw-handout-body) { transition: color .5s, text-shadow .5s; }
/* 나레이션은 줄 전체 폭이 아니라 글자 폭만큼만 자리를 차지하게 해서, 글자 옆 빈 공간에 마우스를 올려도 풀리지 않게 한다 */
.dcw-spoiler-wrap.dcw-blur .dcw-line-narr { width: fit-content; max-width: 100%; }
.dcw-spoiler-wrap.dcw-blur .dcw-line-narr.dcw-align-left { align-self: flex-start; }
.dcw-spoiler-wrap.dcw-blur .dcw-line-narr.dcw-align-center { align-self: center; }
.dcw-spoiler-wrap.dcw-blur .dcw-line-narr.dcw-align-right { align-self: flex-end; }
.dcw-spoiler-wrap.dcw-blur:not(.dcw-spoiler-open):not(:has(:is(.dcw-bubble, .dcw-line-narr, .dcw-handout, .dcw-photo, .dcw-line-image):hover)) :is(.dcw-photo, .dcw-line-image) img {
  filter: blur(12px);
  transform: scale(1.12);
}
.dcw-spoiler-wrap.dcw-blur.dcw-spoiler-open :is(.dcw-photo, .dcw-line-image) img,
.dcw-spoiler-wrap.dcw-blur:has(:is(.dcw-bubble, .dcw-line-narr, .dcw-handout, .dcw-photo, .dcw-line-image):hover) :is(.dcw-photo, .dcw-line-image) img { transition: filter .5s, transform .5s; }
.dcw-spoiler-wrap.dcw-blur .dcw-line-image { align-self: center; width: fit-content; max-width: 100%; overflow: hidden; border-radius: 20px; }

.dcw-script { display: flex; flex-direction: column; }
.dcw-script > * { margin-top: 10px; }
.dcw-script > *:first-child { margin-top: 0; }
.dcw-script > .dcw-grouped { margin-top: 4px; }
/* 패널을 열 때 대사가 실시간으로 오는 것처럼 한 줄씩 순서대로 나타난다(JS가 제어).
   아직 나오지 않은 줄은 display:none으로 완전히 감춰서 공간 자체를 차지하지
   않게 한다(opacity만 0으로 두면 레이아웃 공간이 남아 아래에 여백이 생김).
   "보여지기 시작"(dcw-shown, display만 담당)과 "서서히 나타나기"(dcw-revealed,
   opacity·transform 담당)를 서로 다른 클래스로 나눈 것이 핵심 — 같은 순간에
   display:none을 풀면서 동시에 opacity를 1로 올리면 브라우저가 전환 효과를
   건너뛰고 바로 마지막 모습으로 "뚝" 나타나 버리기 때문에, JS가 먼저
   dcw-shown만 붙여서 "보이지만 아직 투명한" 상태를 한 프레임 확정시킨 뒤에
   dcw-revealed를 붙여야 페이드인이 실제로 부드럽게 재생된다. */
.dcw-script > *:not(.dcw-shown) {
  display: none;
}
.dcw-script > * {
  opacity: 0;
  transform: translateY(6px);
  transition: opacity .35s ease, transform .35s ease;
}
/* 새 줄이 나타날 때 높이·위 간격이 0에서 자라난다(JS가 height/margin-top을 바꿈) */
.dcw-script > *.dcw-grow {
  transition: opacity .35s ease, transform .35s ease, height .28s cubic-bezier(.22, .8, .3, 1), margin-top .28s cubic-bezier(.22, .8, .3, 1);
}
.dcw-script > *.dcw-revealed {
  opacity: 1;
  transform: translateY(0);
}
.dcw-line-narr { font-style: italic; color: var(--dcw-narr-text); font-size: 12.5px; }
.dcw-line-narr.dcw-align-left { text-align: left; }
.dcw-line-narr.dcw-align-center { text-align: center; }
.dcw-line-narr.dcw-align-right { text-align: right; }
.dcw-line-left, .dcw-line-right, .dcw-line-temp {
  display: flex;
  align-items: flex-start;
  max-width: 80%; /* 말풍선은 대사창 가로의 80%까지만 넓어지고 그 이상은 줄바꿈된다 */
}
.dcw-line-right { flex-direction: row-reverse; margin-left: auto; }
/* 프로필 사진은 상단 중앙(#dcw-avatars)에만 쓴다. 사진이 없으면 버튼 색 바탕에 사람 아이콘. */
.dcw-avatar {
  width: 46px;
  height: 46px;
  border-radius: 50%;
  overflow: hidden;
  flex-shrink: 0;
  background: var(--dcw-a-bg);
  display: flex;
  align-items: center;
  justify-content: center;
}
.dcw-avatar img { width: 100%; height: 100%; object-fit: cover; }
.dcw-avatar-default i { color: var(--dcw-a-text); opacity: .8; font-size: 19px; }
.dcw-bubble-col { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.dcw-line-right .dcw-bubble-col { align-items: flex-end; }
.dcw-name { font-size: var(--dcw-name-size, 10px); color: var(--dcw-name-text); padding: 0 3px; }
.dcw-bubble {
  --dcw-b: var(--dcw-a-bg); /* 말풍선 색 — 꼬리도 같은 색을 쓴다 */
  position: relative;
  isolation: isolate; /* 꼬리(::before, z-index:-1)가 말풍선 안에 갇혀서 글자 뒤로 깔리게 한다 */
  background: var(--dcw-b);
  color: var(--dcw-a-text);
  padding: 8px 14px;
  border-radius: 20px;
  font-size: 14px;
  line-height: 1.5;
  word-break: break-word;
}

/* "입력 중" 점 말풍선이 메시지 크기로 늘어나는 전환(JS가 폭·높이를 점 크기에서 최종 크기로 바꾼다). */
.dcw-bubble { box-sizing: border-box; }
.dcw-bubble.dcw-morph { transition: width .26s cubic-bezier(.22, .8, .3, 1), height .26s cubic-bezier(.22, .8, .3, 1), transform .26s ease, background-color .22s ease, border-radius .22s ease; }
/* 커지는 동안 글자는 말풍선 크기만큼만 보이는 상자 안에 있다(두 줄 이상일 때 아래쪽 줄이 밖으로 삐져나오지 않게).
   말풍선 자체를 잘라내면 아래로 튀어나온 꼬리까지 잘리므로 글자 쪽만 자른다. */
.dcw-bt-clip { position: absolute; inset: 0; overflow: hidden; border-radius: inherit; }

/* "입력 중" 말풍선 — 알약 모양 말풍선에 점 3개가 차례로 깜빡이고, 말풍선 전체가 살짝 부풀었다 줄어든다.
   색은 원래 말풍선 색(--dcw-b)과 글자색을 그대로 쓴다. 왼쪽 아래 모서리의 꼬리는 크고 작은 동그라미 두 개로
   만든다(오른쪽 말풍선은 좌우 반대). JS가 점을 보여주는 동안에만 말풍선에 dcw-typing 클래스를 붙인다. */
.dcw-dots { display: flex; align-items: center; height: 10px; }
.dcw-dots i {
  display: block;
  width: 10px;
  height: 10px;
  margin: 0 1px;
  border-radius: 50%;
  background: var(--dcw-ink, currentColor); /* 말풍선 글자색(스포일러 글은 글자를 투명하게 해도 점은 그대로 보이게 --dcw-ink를 쓴다) */
  opacity: .4;
  animation: dcw-blink 1s infinite;
}
.dcw-dots i:nth-child(1) { animation-delay: .3333s; }
.dcw-dots i:nth-child(2) { animation-delay: .6667s; }
.dcw-dots i:nth-child(3) { animation-delay: 1s; }
@keyframes dcw-blink { 50% { opacity: 1; } }
@keyframes dcw-bulge { 50% { transform: scale(1.05); } }

.dcw-bubble.dcw-typing {
  border-radius: 50px;
  padding: 13px 14px;
  will-change: transform;
  animation: dcw-bulge 2s infinite ease-out;
}
.dcw-line-right .dcw-bubble {
  --dcw-b: var(--dcw-b-bg);
  color: var(--dcw-b-text);
}

/* 말풍선 꼬리는 두 겹이며 서로 교차하며 바뀐다. 평소에는 투명한 "입력 중" 동그라미 꼬리(::before)가 숨어 있다가
   dcw-typing일 때 나타나고, 아이메시지식 뾰족한 꼬리(::after)는 반대로 dcw-typing이 빠질 때 나타난다.
   두 꼬리 모두 글자 뒤(z-index:-1)에 깔리며, 꼬리 조각이 말풍선 안쪽 모서리까지 걸치므로 글자 위로 올라오면 첫 글자를 가린다.
   가운데 정렬 추가 캐릭터(temp) 말풍선에는 꼬리를 붙이지 않는다. */
.dcw-line-left .dcw-bubble::before,
.dcw-line-right .dcw-bubble::before {
  content: '';
  position: absolute;
  z-index: -1;
  bottom: -7px;
  width: 20px;
  height: 20px;
  background:
    radial-gradient(circle at 12.5px 7.5px, var(--dcw-b) 0 6.5px, transparent 7px),
    radial-gradient(circle at 4.5px 15.5px, var(--dcw-b) 0 3.5px, transparent 4px);
  opacity: 0;
  transition: opacity .22s ease;
  pointer-events: none;
}
.dcw-line-left .dcw-bubble::before { left: -7px; }
.dcw-line-right .dcw-bubble::before { right: -7px; transform: scaleX(-1); }
.dcw-line-left .dcw-bubble.dcw-typing::before,
.dcw-line-right .dcw-bubble.dcw-typing::before { opacity: 1; }

/* 뾰족한 꼬리 — 같은 사람이 연달아 말할 때는 지금까지 완성되어 나온 마지막 말풍선에만 붙는다.
   말풍선의 아래 바깥쪽 모서리 밑으로 작게 삐져나온 갈고리 모양이며, 모양(SVG)을 마스크로 쓰고
   말풍선과 같은 색을 채워서 어떤 배경 위에서도 가장자리에 줄이 비치지 않는다. 왼쪽 말풍선은 좌우를 뒤집어 쓴다.
   꼬리는 모든 말풍선에 달아 두고, 바로 다음 줄이 이어서 말하는 줄(.dcw-grouped)이면서 이미 화면에 나왔고 "입력 중"도
   아닐 때(= 메시지가 완성됐을 때)만 서서히 숨긴다. 뒤에 대사가 더 있어도 아직 안 나왔거나 입력 중이면 꼬리가 남는다. */
.dcw-line-left .dcw-bubble::after,
.dcw-line-right .dcw-bubble::after {
  content: '';
  position: absolute;
  z-index: -1;
  bottom: -7px;
  width: 24px;
  height: 27px;
  background: var(--dcw-b);
  transition: opacity .22s ease;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 27'%3E%3Cpath d='M4 3L24 3L24 4.3C24 10 21 14.5 14.2 20C14.2 22.5 15.2 25 15.8 26.2Q16.2 27 15.3 26.8L4.6 20.3L4 18Z'/%3E%3C/svg%3E") no-repeat 0 0 / 100% 100%;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 27'%3E%3Cpath d='M4 3L24 3L24 4.3C24 10 21 14.5 14.2 20C14.2 22.5 15.2 25 15.8 26.2Q16.2 27 15.3 26.8L4.6 20.3L4 18Z'/%3E%3C/svg%3E") no-repeat 0 0 / 100% 100%;
}
.dcw-line-left .dcw-bubble::after { left: 0; transform: scaleX(-1); }
.dcw-line-right .dcw-bubble::after { right: 0; }
.dcw-line-left .dcw-bubble.dcw-typing::after,
.dcw-line-right .dcw-bubble.dcw-typing::after { opacity: 0; }
/* :has()를 못 쓰는 브라우저는 이 규칙들을 통째로 무시하므로 위 규칙과 같은 묶음에 넣지 않는다(꼬리가 전부 사라지지 않게). */
.dcw-line-left:has(+ .dcw-grouped.dcw-shown:not(.dcw-line-typing)) .dcw-bubble::after { opacity: 0; }
.dcw-line-right:has(+ .dcw-grouped.dcw-shown:not(.dcw-line-typing)) .dcw-bubble::after { opacity: 0; }
/* 추가 캐릭터 말풍선 — 왼쪽·오른쪽에 붙는 것은 캐릭터 A·B처럼 보낸 쪽 클래스(.dcw-line-left/right)가 달려 있어서 꼬리도 같은 규칙으로 붙는다.
   (같은 사람이 연달아 말하면 마지막 말풍선에만, 말하는 사람이 바뀌면 그 사람의 마지막 말풍선에 따로.) 꼬리는 말풍선 바탕색(--dcw-b)을 따라가므로 여기서 바탕색을 그 변수로 둔다. */
/* 바탕·글자는 핸드아웃과 똑같이 보인다(핸드아웃의 반투명 색을 패널 바탕 위에 얹은 색 --dcw-temp-bg, 본문 글자색). 테두리는 없다(border:0 —
   옛 CSS가 브라우저에 남아 있어도 테두리가 안 생기도록 0으로 덮어쓴다). 색은 위젯 설정에서 지정할 수 있다. */
.dcw-line-temp .dcw-bubble { --dcw-b: var(--dcw-temp-bg); background: var(--dcw-b); color: var(--dcw-temp-text); border: 0; }
.dcw-line-temp.dcw-temp-right { flex-direction: row-reverse; margin-left: auto; }
.dcw-line-temp.dcw-temp-right .dcw-bubble-col { align-items: flex-end; }
.dcw-line-temp.dcw-temp-center { max-width: 100%; justify-content: center; }
.dcw-line-temp.dcw-temp-center .dcw-bubble-col { align-items: center; }
.dcw-line-image { display: flex; justify-content: center; }
.dcw-line-image img { max-width: 100%; border-radius: 20px; } /* 말풍선(20px)과 같은 둥글기 */
/* 캐릭터가 보낸 사진 — 말풍선처럼 보낸 쪽에 붙고, 큼직한 둥근 모서리에 꼬리는 없다 */
.dcw-photo { width: 230px; max-width: 100%; border-radius: 20px; overflow: hidden; background: var(--dcw-glass); }
.dcw-photo img { display: block; width: 100%; height: auto; max-height: 340px; object-fit: cover; }
.dcw-line-handout { width: 100%; }
/* 핸드아웃 — a_devlog의 "정보" 칸처럼 바탕이 비치는 반투명(글자색을 5%만 섞은 옅은 색) 상자 */
.dcw-handout {
  width: 100%;
  background: var(--dcw-handout-bg);
  border: 0; /* 테두리 없음 — 옛 CSS가 브라우저에 남아 있어도 테두리가 안 생기도록 0으로 덮어쓴다(왼쪽 굵은 테두리 포함) */
  border-radius: 10px;
  padding: 10px 12px 11px;
}
.dcw-handout-title { font-size: 11px; font-weight: 700; color: var(--dcw-handout-title); margin-bottom: 5px; }
.dcw-handout-body { font-size: 12.5px; line-height: 1.5; color: var(--dcw-handout-text); word-break: break-word; }

@media (max-width: 480px) {
  /* 모바일에서도 좌우·아래 여백을 통합 툴바(left/right 기준값, bottom 4%)와 맞춘다 */
  #dcw-panel { right: var(--dcw-base, 1%); left: var(--dcw-base, 1%); width: auto; bottom: 4%; }
}

/* 시스템에서 "움직임 줄이기"를 켠 사용자에게는 애니메이션·전환 효과를 쓰지 않는다. */
@media (prefers-reduced-motion: reduce) {
  #dcw-root *, #dcw-root *::before, #dcw-root *::after { animation: none !important; transition: none !important; }
}
