/*
 * DIVEORY design system
 *
 * Order: tokens -> reset/base -> layout -> components -> utilities -> a11y.
 * Breakpoints are mobile-first: sm 40rem, md 48rem, lg 64rem, xl 80rem.
 * Shared components use Bootstrap-familiar names (.btn, .card, .alert,
 * .badge, .form-*, .table). Page-only hooks use area-page__element.
 * JavaScript behavior must use data-* hooks, never styling classes.
 * Page- or domain-specific rules do not belong in this file.
 */

:root {
    color-scheme: light;

    /* Typography */
    --font-sans: "Pretendard", "Noto Sans KR", "Inter", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    /* 계기판 숫자(다이브 컴퓨터처럼 좁은 글꼴, x-head-fonts가 불러온다): 수심·시간·D-day·개수 같은 숫자에만 쓴다(.gauge-num). */
    --font-gauge: "Barlow Condensed", var(--font-sans);
    /* 물결 밑줄(docs/ui/design-style.md 01): 현재 탭·헤더 현재 메뉴. mask로 써서 색은 background-color가 정한다. */
    --wave-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 44 6'%3E%3Cpath d='M1 3c3.5-3 7-3 10.5 0s7 3 10.5 0 7-3 10.5 0 7 3 10.5 0' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E");
    /* 글자 폭만큼 늘어나는 물결 밑줄: 한 주기짜리 완만한 물결(이음매가 매끄럽다)을 칸 크기에 꽉 채워(preserveAspectRatio none) 가로로 이어 붙인다.
       round라 칸 수가 정수로 맞춰져 양 끝이 잘리지 않는다. */
    --wave-line: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 6' preserveAspectRatio='none'%3E%3Cpath d='M0 3c4-2 12-2 16 0s12 2 16 0' fill='none' stroke='%23000' stroke-width='2'/%3E%3C/svg%3E") left center / 1.5rem .3125rem round no-repeat;
    /* 글자를 세로 가운데에 둔 탭·메뉴에서 물결을 글자 바로 아래에 붙이는 top 값(칸 높이와 무관). */
    --wave-line-top: calc(50% + .8em);
    /* 나침반 바늘(02): 여러 개 중 지금 고른 것. 위 흰색·아래 SMB 홍시, 청록으로 채운 칸 위에 둔다. */
    --compass-needle: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 18'%3E%3Cpath d='M5 0 9.5 9H.5z' fill='%23fff'/%3E%3Cpath d='M5 18 .5 9h9z' fill='%23e4572e'/%3E%3C/svg%3E");
    --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
    --font-size-xs: .75rem;
    --font-size-sm: .875rem;
    --font-size-base: 1rem;
    --font-size-lg: 1.125rem;
    --font-size-xl: 1.25rem;
    --font-size-2xl: clamp(1.5rem, 1.35rem + .5vw, 1.875rem);
    --font-size-3xl: clamp(1.875rem, 1.6rem + 1vw, 2.5rem);
    --font-size-display: clamp(2.25rem, 1.75rem + 2vw, 3.5rem);
    --letter-spacing-tightest: -.035em;
    --letter-spacing-tighter: -.03em;
    --letter-spacing-tight: -.025em;
    --letter-spacing-snug: -.02em;
    --letter-spacing-relaxed: .025em;
    --letter-spacing-wide: .12em;
    --letter-spacing-wider: .14em;
    --letter-spacing-widest: .16em;
    --line-height-tight: 1.25;
    --line-height-guide: 1.5;
    --line-height-body: 1.6;
    --line-height-loose: 1.75;
    --font-weight-regular: 400;
    --font-weight-medium: 500;
    --font-weight-semibold: 600;
    --font-weight-bold: 700;

    /* Spacing: .25rem base, with deliberate larger page intervals. */
    --space-0: 0;
    --space-1: .25rem;
    --space-2: .5rem;
    --space-3: .75rem;
    --space-4: 1rem;
    --space-5: 1.25rem;
    --space-6: 1.5rem;
    --space-7: 1.75rem;
    --space-8: 2rem;
    --space-10: 2.5rem;
    --space-12: 3rem;
    --space-16: 4rem;
    --space-20: 5rem;
    --space-24: 6rem;

    /* Semantic color system */
    --color-app: #fbfaf6;
    --color-surface: #fff;
    --color-surface-soft: #f5faf9;
    --color-text: #17282d;
    --color-text-secondary: #5b6c70;
    --color-text-muted: #66777b;
    --color-border: #dfe6e7;
    --color-border-strong: #cbd7d9;
    --color-brand: #0f4c5c;
    --color-brand-hover: #0b3b46;
    --color-brand-soft: #eaf5f4;
    --color-brand-mid: #43a3ad;
    --color-brand-light: #a7d7da;
    /* 시그니처 스크롤바 색(html scrollbar-color·::-webkit-scrollbar가 쓴다). 막대는 진한 청록, 길은 흰색이다. */
    --scrollbar-thumb: var(--color-brand-mid);
    --scrollbar-thumb-hover: var(--color-brand);
    --scrollbar-track: var(--color-surface);
    --color-sky: #f3f9fc;
    --color-depth-surface: #edf8f8;
    --color-depth-shallow: #e5f3f4;
    --color-depth-coastal: #ddeef1;
    --color-depth-deep: #d4e7ec;
    --color-sand-light: #f6f0e3;
    --color-sand: #eadcc5;
    --color-coral-green: #6fae8a;
    --color-coral-purple: #9b7ebd;
    --color-coral-yellow: #e1b94f;
    --color-success: #3f6658;
    --color-success-soft: #edf3ee;
    --color-memory: #a95547;
    --color-memory-soft: #f8e9e4;
    --color-danger: #a84037;
    --color-danger-hover: #8d342d;
    --color-danger-soft: #faece9;
    --color-warning: #8a6418;
    --color-warning-soft: #fbf3df;
    --color-focus: #19778c;
    /* 장비 색(docs/ui/design-style.md 1절): 넓은 면에 칠하지 않고 점·바늘·막대·형광펜 줄에만 쓴다.
       SMB 홍시 = 지금·새 소식·D-day(글자·흰 글자 바탕은 -deep), SMB 형광 = 오늘(위 글자는 짙은색), 드라이 장갑 파랑 = 완료·진행. */
    --color-smb: #e4572e;
    --color-smb-deep: #c2401a;
    --color-smb-soft: #fceee9;
    --color-neon: #ddf247;
    --color-glove: #1f5fbf;
    --color-sand-text: #6e5524;
    /* 슬레이트 글자(연필색). */
    --color-pencil: #22302f;
    --color-overlay: rgb(23 40 45 / .52);

    /* Compatibility aliases used by existing area styles. */
    --color-primary: var(--color-text);
    --color-secondary: var(--color-text-secondary);
    --color-muted: var(--color-text-muted);
    --color-default: var(--color-border);
    --color-soft: var(--color-surface-soft);

    /* Shape, elevation, controls */
    --border-width: max(1px, .0625rem);
    --border-width-accent: calc(2 * var(--border-width));
    --radius-sm: .375rem;
    --check-box-size: 1.125rem;
    --radius-md: .5rem;
    --radius-lg: .75rem;
    --radius-xl: 1rem;
    --radius-card: 1.125rem;
    --radius-pill: 999rem;
    --shadow-sm: 0 .0625rem .125rem rgb(15 76 92 / .06);
    --shadow-md: 0 .75rem 2rem rgb(15 76 92 / .09);
    /* 머리글 드롭다운: 테두리 없이 그림자만으로 사진·바다 배경에서 떠 보인다. */
    --shadow-dropdown: 0 .0625rem .1875rem rgb(31 120 136 / .08), 0 1.25rem 2.75rem -.75rem rgb(15 76 92 / .28);
    /* 스크롤해 콘텐츠 위에 떠 있는 상단 헤더 아래 경계. */
    /* 스크롤한 헤더(MY·로그인·공개 화면 공통): 옅은 흰빛 + 약한 blur, 시그니처 청록빛으로 넓고 옅게 퍼지는 그림자. */
    --shadow-header-scrolled: 0 .125rem .5rem -.25rem rgb(31 120 136 / .12), 0 .75rem 2rem -1.25rem rgb(31 120 136 / .3);
    --header-glass-background: rgb(255 255 255 / .68);
    --header-glass-blur: blur(.5625rem);
    /* 물속 그림자(docs/ui/design-style.md 09): 바다 배경 위 큰 패널. 검은빛이 아니라 밝은 물빛 청록이 넓게 번진다. */
    --shadow-ambient: 0 .0625rem .1875rem rgb(31 120 136 / .06), 0 1.5rem 3.25rem -1.625rem rgb(31 120 136 / .3);
    /* 카드 안에 놓인 슬레이트(작은 판)의 같은 물빛 그림자. */
    --shadow-slate: 0 .0625rem .125rem rgb(31 120 136 / .06), 0 .75rem 1.625rem -1rem rgb(31 120 136 / .26);
    /* 화면 위에 잠깐 떠 있는 toast. 헤더 그림자와 같은 청록빛으로 조금 더 짙고 넓게 퍼진다. */
    --shadow-toast: 0 .125rem .375rem -.125rem rgb(31 120 136 / .16), 0 1rem 2.5rem -1rem rgb(31 120 136 / .34);
    --control-height-xs: 2rem;
    --control-height-sm: 2.5rem;
    --control-height-md: 3rem;
    --control-height: var(--control-height-md);
    --control-height-lg: 3.5rem;
    --control-height-xl: 4rem;
    /* 공통 헤더(공개·로그인·MY) 한 줄 높이. 헤더 아래 sticky 요소의 top, 드롭다운 최대 높이, 푸터 아래 여백이 이 값을 따른다. */
    --header-height: calc(var(--control-height-lg) + var(--space-4));
    /* 공개 장 목록(.public-chapters) 탭 줄 높이. 그 아래 붙는 sticky 요소(.learn-compare__head)의 top도 이 값을 따른다. */
    --chapters-height: var(--control-height-lg);
    /* 폼 안에서 세로로 쌓는 필드·체크·버튼 사이 간격. 테두리 상자끼리 붙어 보이지 않게 form-grid 열 간격(--space-5)과 같게 둔다(form-section 본문·form-grid 줄·모달·로그인 모달). */
    --form-stack-gap: var(--space-5);

    /* Layout */
    --container-sm: 32rem;
    --container-md: 48rem;
    --container-lg: 72rem;
    --container-xl: 80rem;
    /* Narrow navigation and supporting panels beside a reading column. */
    --panel-width-sm: 18rem;
    --panel-width-md: 22rem;
    /* Dialog widths; a dialog picks one by setting --dialog-width on itself. */
    --dialog-width-sm: 26rem;
    --dialog-width-md: 36rem;
    --dialog-width-lg: 44rem;
    /* 화면 좌우 여백. 휴대폰 24px → PC 32px. 폰 MY 시트는 이 안에서 --my-sheet-inset만큼 띄워 본문 왼쪽 선이 헤더 로고와 맞는다. */
    --gutter: clamp(1.5rem, 4vw, 2rem);
    --page-block: clamp(2.5rem, 5vw, 4.5rem);
    /* 끝 시그니처(나침반 바늘) 위아래 간격. 바늘 상자 자체가 40px라 휴대폰 20px → PC 32px로 둔다. */
    --section-ending-gap: clamp(var(--space-5), 3vw, var(--space-8));
    /* 안내 상자(.alert·.form-alert) 간격. 상자 다음 내용까지 / 상자끼리 연속. 놓인 자리마다 따로 맞추지 않는다(docs/ui/page-layout-and-buttons.md 1장). */
    --alert-gap: var(--space-6);
    --alert-stack-gap: var(--space-4);

    /* Layer system */
    --z-base: 0;
    --z-sticky: 20;
    --z-dropdown: 40;
    --z-overlay: 60;
    --z-modal: 70;
    --z-toast: 80;
    --z-skip-link: 100;

    /* Motion */
    --duration-fast: 120ms;
    --duration-base: 180ms;
    --duration-slow: 280ms;
    --ease-standard: cubic-bezier(.2, 0, 0, 1);
    --ease-spring: cubic-bezier(.34, 1.4, .64, 1);
}

/* 휴대폰은 위에 붙어 따라오는 헤더·장 목록을 한 단계 낮춰 읽는 높이를 넓힌다(헤더 72→56px, 장 목록 56→48px). */
@media (max-width: 39.999rem) {
    :root {
        --header-height: var(--control-height-lg);
        --chapters-height: var(--control-height-md);
    }
}

*,
*::before,
*::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

html {
    /* Keep the complete rem-based UI proportional from FHD through 8K. */
    font-size: clamp(1rem, 1.4815vmin, 4rem);
    scroll-behavior: smooth;
    -webkit-text-size-adjust: 100%;
    /* 시그니처 스크롤바: 홈페이지·MY·공유 화면 모든 스크롤(페이지·메뉴·목록)이 같은 막대다(색은 --scrollbar-* 토큰).
       길(track)을 흰색으로 둬야 하늘색 바다 배경 위 페이지 스크롤바도 흰 메뉴 안 스크롤바와 같은 모양으로 보인다. scrollbar-color는 상속되므로 여기 한 곳에 둔다. */
    scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
}
/* scrollbar-width는 상속되지 않아 모든 요소에 둔다(:where라 화면별 scrollbar-width: none이 이긴다). */
:where(*) { scrollbar-width: thin; }
/* scrollbar-color를 모르는 브라우저(Safari, Chrome 120 이하)는 ::-webkit-scrollbar로 같은 모양을 그린다.
   scrollbar-color를 아는 Chrome·Edge·Firefox에서는 이 규칙을 쓰지 않는다(둘이 섞이면 Chrome은 ::-webkit-scrollbar를 따른다). */
@supports not (scrollbar-color: auto) {
    ::-webkit-scrollbar { width: .5rem; height: .5rem; background: var(--scrollbar-track); }
    ::-webkit-scrollbar-thumb { border: .125rem solid transparent; border-radius: var(--radius-pill); background: var(--scrollbar-thumb) padding-box; }
    ::-webkit-scrollbar-thumb:hover { background-color: var(--scrollbar-thumb-hover); }
    ::-webkit-scrollbar-corner { background: transparent; }
}

body {
    min-width: 0;
    min-height: 100dvh;
    margin: 0;
    background: var(--color-app);
    color: var(--color-text);
    font-family: var(--font-sans);
    font-size: var(--font-size-base);
    line-height: var(--line-height-body);
    word-break: keep-all;
    overflow-wrap: anywhere;
    text-rendering: optimizeLegibility;
    -webkit-font-smoothing: antialiased;
}

button,
input,
select,
textarea {
    font: inherit;
}

button,
input,
select,
textarea,
fieldset {
    border: 0;
    background: transparent;
}

button,
[role="button"] {
    touch-action: manipulation;
}

img,
svg,
video {
    display: block;
    max-width: 100%;
}

img,
video {
    height: auto;
}

/* Shared reflection effect; consumers define their own reserved dimensions. */
.generated-image__skeleton {
    display: none;
}

img[data-image-state="loading"]:not(.generated-image > img),
.generated-image:has(> img[data-image-state="loading"]) > .generated-image__skeleton,
[data-image-background][data-image-state="loading"]::after {
    background-color: var(--color-surface-soft);
    background-image: linear-gradient(110deg, transparent 30%, rgb(255 255 255 / .4) 50%, transparent 70%), linear-gradient(135deg, var(--color-surface-soft), var(--color-depth-coastal));
    background-size: 250% 100%, 100% 100%;
    background-repeat: no-repeat;
    animation: skeleton-reflection 3.2s ease-in-out infinite;
}

.generated-image:has(> img[data-image-state="loading"]) > .generated-image__skeleton,
[data-image-background][data-image-state="loading"]::after {
    display: block;
    position: absolute;
    z-index: 1;
    inset: 0;
    content: '';
    pointer-events: none;
}

@keyframes skeleton-reflection {
    0% { background-position: 200% 0, 0 0; }
    80%, 100% { background-position: -100% 0, 0 0; }
}

fieldset {
    min-width: 0;
}

h1,
h2,
h3,
h4,
h5,
h6 { font: inherit; }

ol,
ul { list-style: none; }

textarea {
    resize: vertical;
}

a {
    color: inherit;
    text-decoration: none;
}

::selection {
    background: var(--color-brand-light);
    color: var(--color-brand-hover);
}

/* Layout primitives */
.container,
.container-lg {
    width: 100%;
    margin-inline: auto;
    padding-inline: var(--gutter);
}
.container-lg { max-width: var(--container-lg); }

.stack,
.stack-sm,
.stack-lg {
    display: flex;
    flex-direction: column;
}
.stack { gap: var(--space-5); }
.stack-sm { gap: var(--space-3); }
.stack-lg { gap: var(--space-8); }

.cluster,
.toolbar {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
}

.cluster { align-items: center; }
.toolbar { align-items: center; justify-content: space-between; }

.grid {
    display: grid;
    gap: var(--space-5);
}
.grid > *,
.form-grid > * { min-width: 0; }

.section {
    padding-block: var(--space-8);
}

.section + .section {
    border-top: var(--border-width) solid var(--color-border);
}

/* Shared shell and navigation */
.app-shell,
.site-shell {
    min-height: 100dvh;
}

/* 바다 배경(전체 화면 사진 메인을 뺀 모든 화면, 2026-10-16 사용자 확정): body에 두어 헤더 뒤부터 푸터 뒤까지 한 장으로 이어지고 문서와 함께 스크롤된다.
   시선은 앞을 보는 다이버라 수면(위)과 모래(아래)가 위아래 대칭이다: 위는 헤더 뒤의 큰 수면 빛 그물이 아래로, 아래는 푸터 뒤의 큰 모래 빛 그물이
   위로 같은 원근으로 멀어지며 물빛에 바랜다(두 이미지는 규격·원근·무늬 크기가 같고 색만 다르다). 위에는 오른쪽 위에서 빛 커튼이 내려온다.
   물빛은 맑은 물(위) → 5~10m 수심 물빛(콘텐츠) → 맑은 청록 물(모래 위)이다. 바다 느낌은 위아래 가장자리에서만, 콘텐츠를 방해하지 않게 옅게 낸다.
   어떤 기기에서도 같은 느낌이 나도록 크기는 화면 폭을 따르지 않는다: 수면·모래 높이 11rem(가로 2880 CSS px, 비율 유지·가운데를 잘라 씀),
   맑은 물 겹은 고정 높이(한 장의 100% 그라데이션은 짧은 페이지에서 색 지점이 몰려 가로 경계가 생긴다), 빛 커튼은 120rem 폭(그보다 넓은 화면에서만 폭에 맞춘다).
   이미지는 scripts/generate-my-ocean-background.php로 만든다. 아래 맑은 물 끝색(#d6f1f0)은 생성기의 모래 먼 쪽 안개색과 가까워야 한다.
   기본: 모래 바닥 + 아래 맑은 물. --surface: 수면광·빛 커튼·위 맑은 물(MY·로그인·사진 없는 공개 화면).
   --light: 사진 히어로가 위를 맡는 공개 화면. 같은 수면광·빛 커튼을 히어로 높이(public-hero.css :root --hero-height)만큼 내린
   --ocean-top에서 시작해 히어로 바로 아래부터 비치게 한다(히어로가 글 때문에 더 길어지면 수면광 윗부분이 히어로 뒤로 숨을 뿐 끊기지 않는다).
   긴 글을 읽는 본문이라 위 맑은 물은 한 단계 옅은 물빛으로 둔다. */
.ocean-backdrop {
    --ocean-top: 0rem;
    --ocean-surface: none;
    --ocean-rays: none;
    --ocean-clear-top: none;
    --ocean-floor: image-set(url("../images/background/my-ocean-sand-2880.webp") 1x, url("../images/background/my-ocean-sand.webp") 2x);
    --ocean-clear-bottom: linear-gradient(180deg, rgb(214 241 240 / 0) 0, rgb(210 239 241 / .7) 50%, #d6f1f0 100%);
    background-color: #c4e6f2;
    background-image: var(--ocean-floor), var(--ocean-surface), var(--ocean-rays), var(--ocean-clear-top), var(--ocean-clear-bottom);
    background-position: center bottom, center var(--ocean-top), center var(--ocean-top), center var(--ocean-top), center bottom;
    background-repeat: no-repeat;
    background-size: auto 11rem, auto 11rem, max(100%, 120rem) auto, 100% 40rem, 100% 28rem;
}
/* 수심 눈금(docs/ui/design-style.md 08, app.js가 길이·숫자를 놓는다): 위 수면광(11rem)과 아래 모래 사이 오른쪽 가장자리.
   배경의 일부라 거의 보일락 말락 하게 두고, 콘텐츠 뒤(z-index -1)에 깔아 겹쳐도 글을 가리지 않는다. 넓은 화면에서만 보인다.
   물빛을 아래로 갈수록 짙게 하면 밝은 모래와 부딪혀 얕아 보이므로 깊이는 색 대신 눈금으로 말한다. */
.depth-ruler {
    position: absolute;
    z-index: -1;
    top: 11rem;
    right: .75rem;
    display: none;
    width: 1.875rem;
    pointer-events: none;
    background:
        repeating-linear-gradient(180deg, rgb(15 76 92 / .09) 0 1px, transparent 1px 2rem) right top / .3125rem 100% no-repeat,
        repeating-linear-gradient(180deg, rgb(15 76 92 / .16) 0 1px, transparent 1px 10rem) right top / .625rem 100% no-repeat,
        linear-gradient(rgb(15 76 92 / .07), rgb(15 76 92 / .07)) right top / 1px 100% no-repeat;
}
.depth-ruler > span { position: absolute; right: .875rem; color: rgb(15 76 92 / .28); font-family: var(--font-gauge); font-size: .6875rem; font-weight: var(--font-weight-medium); line-height: 1; transform: translateY(-50%); }
@media (min-width: 64rem) {
    .depth-ruler { display: block; }
}
.ocean-backdrop--surface,
.ocean-backdrop--light {
    --ocean-surface: image-set(url("../images/background/my-ocean-light-2880.webp") 1x, url("../images/background/my-ocean-light.webp") 2x);
    --ocean-rays: url("../images/background/my-ocean-rays.webp");
}
.ocean-backdrop--surface {
    --ocean-clear-top: linear-gradient(180deg, #dcf3fa 0, #d3eff8 12rem, #c9e9f4 28rem, rgb(196 230 242 / 0) 40rem);
}
.ocean-backdrop--light {
    --ocean-top: var(--hero-height, 0rem);
    --ocean-clear-top: linear-gradient(180deg, var(--color-depth-surface) 0, var(--color-depth-shallow) 20rem, var(--color-depth-coastal) 40rem);
    background-color: var(--color-depth-coastal);
}

.public-header {
    border-bottom: var(--border-width) solid var(--color-border);
    background: var(--color-sky);
}

.public-header .brand-mark__icon { filter: drop-shadow(0 .125rem .35rem color-mix(in srgb, var(--color-sky) 75%, transparent)) drop-shadow(0 0 .0625rem var(--color-sky)); }

.public-header {
    position: sticky;
    top: 0;
    z-index: var(--z-sticky);
    -webkit-backdrop-filter: blur(.75rem);
    backdrop-filter: blur(.75rem);
}

.public-header__inner {
    display: flex;
    width: 100%;
    min-height: var(--header-height);
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    margin-inline: auto;
    padding: 0 var(--gutter);
}
.public-header__inner { max-width: var(--container-lg); }

/* 바다 배경 위 헤더(MY·로그인·사진 없는 공개 화면): 맨 위(스크롤 0)에서는 배경 없이 완전히 투명해 수면광이 그대로 보이고, 스크롤을 시작하면
   (app.js가 .ocean-header--scrolled를 붙인다) 옅은 흰빛·약한 blur·청록 그림자가 나타난다. 배경은 ::before에만 둬서 opacity로 전환한다.
   나타날 때는 짧게(휠 한 번에 콘텐츠가 크게 움직여도 투명한 헤더 아래로 글자가 지나가 보이지 않게), 맨 위로 돌아와 사라질 때는 천천히.
   사진 히어로 위 공개 헤더(.public-header--overlay.public-header--scrolled, app.js, 같은 스크롤 기준)도 같은 ::before를 써서 유리 배경 높이(아래 1px 테두리 제외)·그림자 위치가 똑같다. */
.ocean-header { border-bottom-color: transparent; background: transparent; -webkit-backdrop-filter: none; backdrop-filter: none; }
.ocean-header::before,
.public-header--overlay::before {
    position: absolute;
    z-index: -1;
    inset: 0;
    background: var(--header-glass-background);
    box-shadow: var(--shadow-header-scrolled);
    content: "";
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--duration-slow) var(--ease-standard);
    -webkit-backdrop-filter: var(--header-glass-blur);
    backdrop-filter: var(--header-glass-blur);
}
.ocean-header--scrolled::before,
.public-header--overlay.public-header--scrolled::before { opacity: 1; transition-duration: var(--duration-fast); }

.auth-main {
    width: 100%;
    margin-inline: auto;
    padding: var(--page-block) var(--gutter);
}
.auth-main { max-width: var(--container-lg); }

/* 공통 푸터(공개·로그인·MY). 늘 바다 배경(.ocean-backdrop)의 모래 바닥 위에 얹혀 자기 배경·윗선이 없다.
   마지막 줄은 헤더와 위아래 대칭이다: 줄 높이를 헤더 안 요소(--control-height)와 같게 하고, 화면 아래 끝까지의 여백을 헤더 위 여백
   ((헤더 높이 - 요소 높이) / 2, 헤더 높이는 --header-height)과 같게 둔다. 콘텐츠와의 간격은 위 여백이 맡는다. 홈 바가 있는 폰은 그만큼 더 띄운다.
   줄 안의 산호·문구는 높이를 정수 px(36·24)로 둬서 위치가 소수점이 되지 않게 한다. 소수점이면 페이지마다 다른 전체 높이의 소수점과 더해져
   반올림되는 픽셀 줄이 화면마다 1px씩 달라진다(이메일은 처음부터 정수라 같았다). */
.public-footer__inner { display: grid; width: 100%; max-width: var(--container-lg); gap: var(--space-5); margin-inline: auto; padding: var(--space-12) var(--gutter) calc((var(--header-height) - var(--control-height)) / 2 + env(safe-area-inset-bottom, 0px)); }
.public-footer__copy { display: flex; max-width: var(--container-sm); min-height: var(--control-height); align-items: center; gap: var(--space-3); color: var(--color-text-secondary); font-size: var(--font-size-sm); line-height: var(--space-6); }
.public-footer__copy > span { min-width: 0; }
.public-footer__coral { width: var(--control-height-sm); height: 2.25rem; flex: 0 0 auto; }
.public-footer__contact { justify-self: end; }
.public-footer__email { display: inline-flex; min-height: var(--control-height); align-items: center; gap: var(--space-2); padding: var(--space-2) 0; }

.coral-mark__green { color: var(--color-coral-green); }
.coral-mark__purple { color: var(--color-coral-purple); }
.coral-mark__yellow { color: var(--color-coral-yellow); }
.coral-mark__base { color: var(--color-coral-purple); }

@media (min-width: 40rem) {
    .public-footer__inner { display: flex; align-items: center; justify-content: space-between; gap: var(--space-5); }
}

.public-navigation {
    display: flex;
    min-width: 0;
    align-items: center;
    gap: var(--space-1);
}

.public-home-link,
.my-header__home { display: inline-flex; width: fit-content; min-height: var(--control-height); align-items: center; justify-content: center; }
.public-home-link { flex: 0 0 auto; border-radius: var(--radius-lg); }

/* 헤더 메뉴 링크(공개 .public-navigation · MY .my-nav 공통). 현재 메뉴는 굵은 청록 글자와 메뉴명 아래 짧은 밑줄로 표시한다.
   사진 위 헤더는 --header-nav-color·--header-nav-current-color·--header-nav-hover-color로 색만 바꾼다(public.css .public-header--overlay). */
.header-nav-link { position: relative; display: inline-flex; flex: 0 0 auto; min-height: var(--control-height); align-items: center; gap: var(--space-1); border-radius: var(--radius-md); list-style: none; padding: 0 var(--space-3); color: var(--header-nav-color, var(--color-text-secondary)); font-size: var(--font-size-base); font-weight: var(--font-weight-medium); text-decoration: none; white-space: nowrap; transition: color var(--duration-fast) var(--ease-standard), background-color var(--duration-fast) var(--ease-standard); }
.header-nav-link::-webkit-details-marker { display: none; }
.header-nav-link.is-current { color: var(--header-nav-current-color, var(--color-brand)); font-weight: var(--font-weight-bold); }
/* 굵어져도 옆 메뉴가 밀리지 않게, 보이지 않는 굵은 글자로 폭을 미리 잡아 둔다. */
.header-nav-link__text { display: inline-grid; }
.header-nav-link__text::after { height: 0; overflow: hidden; visibility: hidden; content: attr(data-label); font-weight: var(--font-weight-bold); }
.header-nav-link.is-current::after { position: absolute; top: var(--wave-line-top); right: calc(var(--space-3) + .875rem + var(--space-1)); left: var(--space-3); height: .3125rem; background: var(--header-nav-current-color, var(--color-brand-mid)); content: ""; -webkit-mask: var(--wave-line); mask: var(--wave-line); }

@media (hover: hover) {
    .header-nav-link:hover { color: var(--header-nav-hover-color, var(--color-brand)); }
}

/* 머리글 메뉴 드롭다운(.header-nav-item > .header-nav-link + .header-nav-dropdown): 공개 헤더 여행·준비, MY 헤더 TOUR·MY TRAVEL·PRESET이 같이 쓴다.
   마우스를 올리면(hover 기기) 또는 키보드 초점이 들어오면 메뉴 바로 아래 가운데에 펼친다. 메뉴와 목록 사이에 틈이 없어 내려가는 동안 닫히지 않는다. */
.header-nav-item { position: relative; }
.header-nav-dropdown { position: absolute; z-index: var(--z-dropdown); top: 100%; left: 50%; display: grid; width: max-content; min-width: 11rem; max-width: min(20rem, calc(100vw - var(--gutter) - var(--gutter))); max-height: min(34rem, 75vh); gap: .125rem; overflow-y: auto; overscroll-behavior: contain; visibility: hidden; border-radius: var(--radius-card); background: var(--color-surface); padding: var(--space-3); box-shadow: var(--shadow-dropdown); opacity: 0; pointer-events: none; transform: translate(-50%, .5rem); transition: opacity 140ms ease, transform 140ms ease, visibility 0s linear 140ms; }
.header-nav-dropdown a { display: flex; min-width: 0; min-height: 2.375rem; align-items: center; border-radius: var(--radius-md); padding: .4375rem var(--space-3); color: var(--color-text); font-size: var(--font-size-sm); font-weight: var(--font-weight-medium); text-decoration: none; transition: background-color 140ms ease, color 140ms ease; }
.header-nav-dropdown a > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 현재 항목은 헤더 현재 메뉴와 같은 물결 밑줄(글자 폭). 말줄임을 위해 span이 overflow: hidden이라 밑줄 자리를 span 안쪽 아래 여백으로 잡는다. */
.header-nav-dropdown a[aria-current="page"] { color: var(--color-brand); font-weight: var(--font-weight-semibold); }
.header-nav-dropdown a[aria-current="page"] > span { position: relative; margin-bottom: -.5rem; padding-bottom: .5rem; }
.header-nav-dropdown a[aria-current="page"] > span::after { position: absolute; right: 0; bottom: 0; left: 0; height: .3125rem; background: var(--color-brand-mid); content: ""; -webkit-mask: var(--wave-line); mask: var(--wave-line); }
.header-nav-item:focus-within > .header-nav-dropdown { visibility: visible; opacity: 1; pointer-events: auto; transform: translate(-50%, 0); transition-delay: 0s; }
@media (hover: hover) {
    .header-nav-item:hover > .header-nav-dropdown { visibility: visible; opacity: 1; pointer-events: auto; transform: translate(-50%, 0); transition-delay: 0s; }
    .header-nav-dropdown a:hover { background: var(--color-brand-soft); color: var(--color-brand); }
}

/* 머리글 드롭다운 메뉴(.header-menu): MY 햄버거 메뉴·공개 홈페이지 햄버거·공유 화면 햄버거가 같이 쓴다.
   위 .header-menu__body(그룹 .header-menu__group, 제목 .header-menu__heading)는 넘치면 스크롤하고, 아래 .header-menu__footer(MY·로그아웃)는 고정이다.
   여는 쪽(details)은 position: relative를 둔다. */
.header-menu { position: absolute; top: calc(100% + var(--space-3)); right: 0; z-index: var(--z-dropdown); display: flex; width: min(var(--panel-width-sm), calc(100vw - var(--gutter) - var(--gutter))); max-height: calc(100dvh - var(--header-height) - var(--space-6)); flex-direction: column; overflow: hidden; border: var(--border-width) solid var(--color-border); border-radius: var(--radius-card); background: var(--color-surface); box-shadow: var(--shadow-md); }
/* 행 높이는 공개 헤더 메뉴(2.5rem)와 같다. 화면 높이까지 쓰고 넘치면 스크롤한다.
   스크롤 그림자(background-attachment local/scroll)는 항목이 더 있는 쪽 가장자리에 시그니처 청록(brand-mid)으로 옅게 번진다.
   검게 뭉치지 않도록 넓은 선형 그라데이션을 쓰고, 끝에 닿으면 local 덮개(그림자보다 높이가 크다)가 그림자를 가린다. 스크롤바는 공통 시그니처 스크롤바(html)다. */
.header-menu__body {
    min-height: 0; flex: 1 1 auto; overflow-y: auto; overscroll-behavior: contain; padding: var(--space-2);
    background:
        linear-gradient(var(--color-surface) 50%, transparent) center top / 100% var(--space-10) no-repeat local,
        linear-gradient(transparent, var(--color-surface) 50%) center bottom / 100% var(--space-10) no-repeat local,
        linear-gradient(color-mix(in srgb, var(--color-brand-mid) 22%, transparent), color-mix(in srgb, var(--color-brand-mid) 8%, transparent) 40%, transparent) center top / 100% var(--space-5) no-repeat scroll,
        linear-gradient(transparent, color-mix(in srgb, var(--color-brand-mid) 8%, transparent) 60%, color-mix(in srgb, var(--color-brand-mid) 22%, transparent)) center bottom / 100% var(--space-5) no-repeat scroll,
        var(--color-surface);
}
.header-menu__group + .header-menu__group { position: relative; margin-top: var(--space-2); padding-top: var(--space-2); }
.header-menu__group + .header-menu__group::before { position: absolute; inset-inline: var(--space-3); top: 0; border-top: var(--border-width) solid var(--color-border); content: ""; }
/* 그룹 제목은 링크가 아니라 라벨로 읽히게 작고 자간 넓은 청록 굵은 글자로 둔다. */
.header-menu__heading { padding: var(--space-2) var(--space-3); color: var(--color-brand); font-size: var(--font-size-xs); font-weight: var(--font-weight-semibold); letter-spacing: var(--letter-spacing-wide); text-transform: uppercase; }
.header-menu__group > a + a { margin-top: var(--border-width-accent); }
.header-menu a,
.header-menu button { display: flex; width: 100%; min-height: var(--control-height-sm); align-items: center; gap: var(--space-3); border-radius: var(--radius-md); padding: var(--space-2) var(--space-3); color: var(--color-text); font-size: var(--font-size-sm); text-align: left; text-decoration: none; }
.header-menu a[aria-current="page"] { background: var(--color-brand-soft); color: var(--color-brand); font-weight: var(--font-weight-semibold); }
.header-menu a[aria-current="page"] { position: relative; }
.header-menu a[aria-current="page"]::before {
    content: "";
    position: absolute;
    inset-inline-start: calc(-1 * var(--space-2));
    top: 50%;
    width: var(--space-3);
    height: var(--space-2);
    background: linear-gradient(to bottom, var(--color-brand) 50%, color-mix(in srgb, var(--color-brand) 94%, var(--color-surface)) 50%);
    clip-path: polygon(0 50%, 20% 0, 100% 50%, 20% 100%);
    transform: translateY(-50%);
    pointer-events: none;
}
.header-menu__footer { position: relative; z-index: 1; flex: 0 0 auto; border-top: var(--border-width) solid var(--color-border); background: var(--color-surface); padding: var(--space-2); }
.header-menu__footer > * + * { margin-top: var(--border-width-accent); }
/* 위 메뉴 없이 계정 줄만 있으면(공유 화면 비로그인·다른 사람의 공유) 위 구분선을 두지 않는다. */
.header-menu__footer:first-child { border-top: 0; }

@media (hover: hover) {
    .header-menu a:hover,
    .header-menu button:hover { background: var(--color-brand-soft); color: var(--color-brand); }
}

/* Brand and icon system */
.brand-mark {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
}

.brand-mark__symbol {
    display: grid;
    width: 2.25rem;
    height: 2.25rem;
    flex: 0 0 auto;
    place-items: center;
}

.brand-mark__icon { display: block; width: 100%; height: 100%; object-fit: contain; }
.brand-mark__name { color: var(--color-text); font-size: 1.05rem; font-weight: var(--font-weight-semibold); letter-spacing: var(--letter-spacing-snug); line-height: 1; }
@supports (text-box-trim: trim-both) {
    .brand-mark__name { text-box-trim: trim-both; text-box-edge: cap alphabetic; }
}

.icon {
    width: 1.25rem;
    height: 1.25rem;
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1.125rem;
}

.icon-sm { width: 1rem; height: 1rem; font-size: .875rem; }
.icon-xs { width: .875rem; height: .875rem; font-size: .75rem; }
.icon-lg { width: 1.5rem; height: 1.5rem; font-size: 1.375rem; }
.navigation-arrow { width: 1.125rem; height: 1.125rem; vertical-align: middle; }
.navigation-arrow--back { transform: scaleX(-1); }

/* One interaction contract for public, MY, and shared surfaces. */
.cursor-pointer,
.btn,
.button,
.pointer-scope :where(
    a[href],
    button:not(:disabled),
    summary,
    label[for],
    label:has(:is(input, select, textarea)),
    select:not(:disabled),
    input:is([type="button"], [type="submit"], [type="reset"], [type="checkbox"], [type="radio"]):not(:disabled),
    [role="button"]:not([aria-disabled="true"]),
    [role="tab"]:not([aria-disabled="true"]),
    [role="option"]:not([aria-disabled="true"])
) { cursor: pointer; }

.pointer-scope :where(
    button:disabled,
    select:disabled,
    input:is([type="button"], [type="submit"], [type="reset"], [type="checkbox"], [type="radio"]):disabled,
    label:has(:disabled),
    [aria-disabled="true"]
) { cursor: not-allowed; }

/* Buttons: Bootstrap-familiar names, with old names kept as aliases. */
.btn,
.button {
    --button-height: var(--control-height-md);
    --button-padding-y: .6875rem;
    --button-padding-x: 1.125rem;
    --button-font-size: var(--font-size-sm);
    display: inline-flex;
    min-height: var(--button-height);
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    border: var(--border-width) solid transparent;
    border-radius: var(--radius-lg);
    padding: var(--button-padding-y) var(--button-padding-x);
    font-size: var(--button-font-size);
    font-weight: var(--font-weight-semibold);
    line-height: 1.25rem;
    text-align: center;
    text-decoration: none;
    transition: background-color var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard), transform var(--duration-fast) var(--ease-standard);
}

.btn:where(:not(.btn-icon)),
.button:where(:not(.btn-icon)) { width: fit-content; justify-self: start; }

/* 버튼 글자 앞 보조 문구(meta prop)와 둘을 나누는 작은 세로선. 확인 단계의 "… | 예"도 같은 선을 쓴다. */
.btn-meta { font-weight: var(--font-weight-medium); opacity: .85; }
.btn-divider { width: 1px; height: .875em; flex: none; background: currentColor; opacity: .4; }

.btn-primary,
.button--primary { background: var(--color-brand); color: var(--color-surface); }
.btn-secondary,
.button--secondary { border-color: var(--color-border); background: var(--color-surface); color: var(--color-brand); }
.btn-ghost,
.button--ghost { background: transparent; color: var(--color-brand); }
.btn-danger,
.button--danger { background: var(--color-danger); color: var(--color-surface); }

@media (hover: hover) {
    .btn-primary:hover,
    .button--primary:hover { background: var(--color-brand-hover); }
    .btn-secondary:hover,
    .button--secondary:hover { border-color: var(--color-brand-light); background: var(--color-brand-soft); }
    .btn-ghost:hover,
    .button--ghost:hover { background: var(--color-brand-soft); }
    .btn-danger:hover,
    .button--danger:hover { background: var(--color-danger-hover); }
}

.btn:disabled,
.button:disabled,
.btn.disabled,
.button.disabled {
    cursor: not-allowed;
    opacity: .55;
    transform: none;
}

.btn-xs { --button-height: var(--control-height-xs); --button-padding-y: .3125rem; --button-padding-x: .625rem; --button-font-size: var(--font-size-xs); }
.btn-sm { --button-height: var(--control-height-sm); --button-padding-y: .5rem; --button-padding-x: .875rem; }
.btn-md { --button-height: var(--control-height-md); --button-padding-y: .6875rem; --button-padding-x: 1.125rem; }
.btn-lg { --button-height: var(--control-height-lg); --button-padding-y: .875rem; --button-padding-x: 1.375rem; --button-font-size: var(--font-size-base); }
.btn-xl { --button-height: var(--control-height-xl); --button-padding-y: 1.125rem; --button-padding-x: 1.625rem; --button-font-size: var(--font-size-lg); }
.btn-icon,
.form-action--icon-only { width: var(--button-height); min-width: var(--button-height); }
.btn.btn-icon,
.button.btn-icon,
.form-action--icon-only { padding: 0; }
.btn-block { width: 100%; }

/* Cards, panels and repeated page patterns */
.card {
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-card);
    background: var(--color-surface);
    box-shadow: var(--shadow-sm);
}

.card { padding: var(--space-5); }

.card-surface,
.card--surface { border-color: var(--color-border); background: var(--color-surface); }
.card-soft,
.card--soft { border-color: var(--color-brand-light); background: var(--color-surface-soft); }
.card-memory,
.card--memory { border-color: var(--color-memory-soft); background: var(--color-memory-soft); }

.empty-state {
    padding: clamp(1.5rem, 4vw, 2.5rem);
    border: var(--border-width) solid var(--color-brand-light);
    border-radius: var(--radius-card);
    background: var(--color-surface-soft);
}
.empty-state__text { color: var(--color-text-secondary); }
/* x-ui.empty-state with an icon: a centered guide card with start actions. */
.empty-state--guide { display: grid; justify-items: center; gap: var(--space-3); border-style: dashed; text-align: center; }
.empty-state__icon { display: inline-flex; width: var(--control-height-lg); height: var(--control-height-lg); align-items: center; justify-content: center; border-radius: var(--radius-pill); background: var(--color-surface); color: var(--color-brand); box-shadow: var(--shadow-sm); }
.empty-state--guide .empty-state__title { font-size: var(--font-size-lg); }
.empty-state--guide .empty-state__text { max-width: 32rem; font-size: var(--font-size-sm); line-height: var(--line-height-body); }
.empty-state__actions { justify-content: center; margin-top: var(--space-2); }

/* Headings and text roles */
.page-header { max-width: 42rem; }
.page-header__eyebrow,
.page-header-eyebrow,
.section-eyebrow-caps {
    color: var(--color-brand);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    letter-spacing: var(--letter-spacing-wider);
    line-height: 1.5;
    text-transform: uppercase;
}

.page-header__eyebrow,
.page-header-eyebrow { margin-bottom: var(--space-3); }

.page-header__title,
.page-header-title {
    color: var(--color-text);
    font-size: var(--font-size-3xl);
    font-weight: var(--font-weight-semibold);
    letter-spacing: var(--letter-spacing-tightest);
    line-height: var(--line-height-tight);
    overflow-wrap: anywhere;
}

.page-header__description,
.page-header-description {
    max-width: 42rem;
    margin-top: var(--space-4);
    color: var(--color-text-secondary);
    line-height: var(--line-height-body);
}

.card-heading {
    color: var(--color-text);
    font-weight: var(--font-weight-semibold);
    line-height: var(--line-height-tight);
}

.card-heading { font-size: var(--font-size-lg); }

/* Short title accents distinguish section headings from field labels. */
.card-heading.heading-accent { font-size: var(--font-size-xl); }
.heading-accent::after { display: block; width: 2em; margin-top: var(--space-2); border-bottom: var(--border-width-accent) solid var(--color-brand); content: ''; }

/* Forms share section hierarchy and edit states across public and account pages. */
.form-section { display: grid; min-width: 0; gap: var(--space-3); }
.form-section__heading, .form-section__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.form-section__heading { justify-content: space-between; }
.form-section__body { display: grid; min-width: 0; gap: var(--form-stack-gap); }
.form-section__read { display: grid; gap: var(--space-3); }
.form-section__read > div { min-width: 0; padding: var(--space-2); border-bottom: var(--border-width) solid var(--color-border-strong); }
.form-section__read dt { color: var(--color-text-secondary); font-size: var(--font-size-xs); }
.form-section__read dd { margin-top: var(--space-2); white-space: pre-wrap; overflow-wrap: anywhere; }
.form-section > .action-group { justify-content: flex-end; }
.form-section .form-field__message:empty { min-height: 0; margin-top: 0; }

.text-secondary { color: var(--color-text-secondary); font-size: var(--font-size-sm); line-height: var(--line-height-body); }

.text-muted { color: var(--color-text-muted); }
.text-sm { font-size: var(--font-size-sm); }
.text-xs,
.fine-print { color: var(--color-text-muted); font-size: var(--font-size-xs); line-height: 1.5; }
.pre-wrap { white-space: pre-wrap; }

.text-link {
    color: var(--color-brand);
    font-weight: var(--font-weight-semibold);
    text-decoration: underline;
    text-decoration-color: transparent;
    text-underline-offset: .2em;
    transition: color var(--duration-fast) var(--ease-standard), text-decoration-color var(--duration-fast) var(--ease-standard);
}

@media (hover: hover) {
    .text-link:hover { color: var(--color-brand-hover); text-decoration-color: currentColor; }
}

/* 출처 확인일(x-ui.source-date): 시계 아이콘 + 날짜. 날짜 중간에서 줄이 바뀌지 않고, 자리 폭이 같은 숫자로 맞춘다. */
.source-date { display: inline-flex; align-items: baseline; gap: .3em; color: var(--color-text-muted); font-weight: var(--font-weight-regular); font-variant-numeric: tabular-nums; white-space: nowrap; }
.source-date > .icon { font-size: .9em; }

/* 이메일 표시(x-ui.email): "@" 앞 <wbr>에서 먼저 줄이 바뀌고, 그래도 넘치면 아무 곳에서 끊는다. 값이 없을 때의 대체 문구는 흐리게. */
.email-text { overflow-wrap: anywhere; }
.email-text--empty { color: var(--color-text-muted); }

/* Badges and status */
.badge {
    display: inline-flex;
    min-height: 1.75rem;
    align-items: center;
    gap: var(--space-1);
    border-radius: var(--radius-pill);
    background: color-mix(in srgb, var(--color-border) 60%, var(--color-surface));
    padding: .25rem .75rem;
    color: var(--color-text-secondary);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    line-height: 1.25rem;
}
/* 상태 아이콘(x-ui.badge icon)이 있으면 왼쪽 여백을 줄여 글자와 균형을 맞춘다. */
.badge:has(> .icon) { padding-left: .625rem; align-items: baseline; }
/* 아이콘 상자를 가운데 두면 글자 위치가 폰트(Pretendard·맑은 고딕 등)마다 달라 어긋난다.
   상자 높이를 글리프에 맞추고 글자 baseline에 붙인 뒤, 한글 글자 몸통 가운데로 조금 올린다. */
.badge > .icon { position: relative; top: -.05em; height: auto; flex: 0 0 auto; font-size: .875em; line-height: 1; }

/* 이름 옆 짧은 표시용 작은 배지(x-ui.badge size="sm"). 제목 글자 높이 안에 들어오게 줄인다. */
.badge-sm { min-height: 1.125rem; padding: 0 .4375rem; font-size: .6875rem; line-height: 1.125rem; vertical-align: middle; }

.badge-brand { background: var(--color-brand-soft); color: var(--color-brand); }
/* 슬레이트(docs/ui/design-style.md 05): 그 대상의 핵심 요약 한 판(공유 화면 내 슬레이트, 정산 요약, 여행 로그 요약). 화면에 하나만 둔다.
   흰 판 + 아래 두께 그림자 + 왼쪽 위 끈 구멍(오른쪽 위는 "···" 메뉴 자리). 표면 질감은 추후 공통으로 정한다. */
.slate {
    --slate-inset: var(--space-3);
    --slate-hole: var(--space-3);
    position: relative;
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-xl);
    background: #fbfcfb;
    padding: calc(var(--slate-inset) * 2 + var(--slate-hole)) var(--space-5) var(--space-5);
    color: var(--color-pencil);
    box-shadow: inset 0 -.1875rem 0 rgb(34 48 47 / .04), var(--shadow-slate);
}
.slate::before { position: absolute; top: var(--slate-inset); left: var(--slate-inset); width: var(--slate-hole); height: var(--slate-hole); border-radius: var(--radius-pill); background: var(--color-depth-shallow); box-shadow: inset 0 .0625rem .125rem rgb(23 40 45 / .35); content: ""; }
/* 요약 숫자 판(x-ui.slate-metrics): 이름은 작게, 값은 계기판 숫자 + 작은 단위. */
.slate-metrics { display: grid; grid-template-columns: repeat(auto-fit, minmax(5rem, 1fr)); gap: var(--space-4); margin: 0; }
.slate-metrics > div { display: grid; min-width: 0; align-content: start; gap: var(--space-2); }
.slate-metrics dt { color: var(--color-text-secondary); font-size: var(--font-size-xs); }
.slate-metrics dd { margin: 0; overflow-wrap: anywhere; }
.slate-metrics__value { font-family: var(--font-gauge); font-size: var(--font-size-3xl); font-weight: var(--font-weight-semibold); line-height: 1; font-variant-numeric: tabular-nums; }
.slate-metrics__unit { margin-left: .2em; color: var(--color-text-secondary); font-size: var(--font-size-sm); }

/* 진행 중(다이버 깃발)·끝난 것(모래). docs/ui/design-style.md 06 */
.badge-live { background: var(--color-smb-soft); color: #b33b17; }
.badge-sand { background: var(--color-sand-light); color: var(--color-sand-text); }
/* 다이버 깃발(x-ui.icon dive-flag): 빨강 바탕 흰 사선, "지금 물속에 다이버가 있다"는 국제 신호. 색이 정해진 그림이라 글자색을 따르지 않는다. */
.icon-dive-flag { width: 1.25em; height: auto; flex: none; vertical-align: -.1em; }
.badge > .icon-dive-flag { top: .05em; }
.badge-success { background: var(--color-success-soft); color: var(--color-success); }
.badge-warning { background: var(--color-warning-soft); color: var(--color-warning); }
.badge-danger { background: var(--color-danger-soft); color: var(--color-danger); }

/* Alerts */
.alert {
    margin-top: var(--space-5);
    border: var(--border-width) solid;
    border-radius: var(--radius-lg);
    padding: var(--space-3) var(--space-4);
    font-size: var(--font-size-sm);
    line-height: var(--line-height-body);
}

.alert-success { border-color: color-mix(in srgb, var(--color-success) 24%, transparent); background: var(--color-success-soft); color: var(--color-success); }
.alert-danger { border-color: color-mix(in srgb, var(--color-danger) 28%, transparent); background: var(--color-danger-soft); color: var(--color-danger); }
/* 안내 문구: 왼쪽에 말풍선 아이콘(Font Awesome comment-dots, MY 레이아웃이 불러온다). */
.form-alert { position: relative; border: var(--border-width) solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface-soft); padding: var(--space-3) var(--space-4) var(--space-3) calc(var(--space-4) + 1rem + var(--space-2)); color: var(--color-text-secondary); font-size: var(--font-size-sm); }
.form-alert::before { position: absolute; top: var(--space-3); left: var(--space-4); color: var(--color-brand); font-family: "Font Awesome 6 Free"; font-weight: 900; line-height: inherit; content: "\f4ad"; }
.form-alert--notice::before { content: "\f0a1"; }
.form-alert__detail { display: block; margin-top: var(--space-1); }
/* 복사 버튼을 품은 URL 입력칸(x-ui.copy-url-field: MY 공유 창·투어 참가자 초대 창·공개 공유 페이지). */
.copy-url-field { display: grid; gap: var(--space-2); }
.copy-url-field label { color: var(--color-text-secondary); font-size: var(--font-size-xs); font-weight: var(--font-weight-semibold); }
.copy-url-field:focus-within label { color: var(--color-focus); }
/* 밑줄은 입력칸과 복사 버튼을 묶은 control에 그린다. */
.copy-url-field__control {
    display: flex;
    min-width: 0;
    align-items: center;
    gap: var(--space-1);
    border-bottom: var(--border-width) solid var(--color-border-strong);
}
.copy-url-field__control:focus-within { border-bottom-color: var(--color-focus); }
.copy-url-field__input {
    flex: 1 1 auto;
    width: 100%;
    min-width: 0;
    height: var(--control-height-md);
    border: 0;
    border-radius: 0;
    background: transparent;
    padding: 0 var(--space-1);
    color: var(--color-text-secondary);
    font: inherit;
    font-size: var(--font-size-sm);
    text-overflow: ellipsis;
}
.copy-url-field__input:focus-visible { outline: 0; }
.copy-url-field__copy { flex: 0 0 auto; }
/* 되돌릴 수 없는 행동의 위험 안내(x-my.confirm-panel tone="danger", 회원 탈퇴): 위험색 상자 + 경고 아이콘. */
.form-alert--danger { border-color: color-mix(in srgb, var(--color-danger) 28%, transparent); background: var(--color-danger-soft); color: var(--color-danger); }
.form-alert--danger::before { color: var(--color-danger); content: "\f071"; }
.form-alert__list { display: grid; gap: var(--space-1); margin: var(--space-2) 0 0; padding-left: 1.1em; list-style: disc; }
/* 문장 안 복사 버튼(x-ui.copy-text): 글자 + 복사 아이콘. */
.copy-text { display: inline-flex; align-items: center; gap: var(--space-1); vertical-align: middle; }
/* 상자를 담은 stack(gap --space-4)에서 상자 다음 내용은 --alert-gap만큼 띄운다. MY 화면의 다른 자리는 my.css "안내 상자 간격".
   다음이 입력칸(.form-field)이면 stack gap만 둔다. */
.tour-announcement-manager > :is(.alert, .form-alert) + :not(.alert, .form-alert, .form-field) { margin-top: calc(var(--alert-gap) - var(--space-4)); }

/* Toast: 화면 가운데 70% 높이에 잠깐 뜨는 알림(js/toast.js, DiveoryToast). popover로 띄워 열린 dialog 위에도 보인다.
   비 맞은 유리처럼: .toast 상자 전체가 뿌연 blur 패널이고(가장자리는 mask로 번지게 흐려진다), 그 안쪽 --toast-haze만큼 들어온 자리에
   또렷한 테두리 카드(::before, 작은 물방울)와 아이콘·문구·남은 시간 선(::after)을 그린다. 그래서 문구 뒤와 둘레는 뿌옇고 내용은 선명하다.
   패널 자리까지 .toast라 어디를 눌러도 닫힌다. 결과는 왼쪽 옅은 원 안의 의미 아이콘으로 보인다.
   아래 가는 물빛 선이 남은 시간만큼 줄어들고, 포인터를 올리면 선과 시간이 함께 멈춘다. 기포처럼 아래에서 떠올라 위로 흩어진다. */
.toast-region {
    --toast-haze: var(--space-6);
    position: fixed;
    z-index: var(--z-toast);
    inset: auto;
    top: 70%;
    left: 50%;
    display: grid;
    width: max-content;
    max-width: min(calc(100vw - var(--gutter) * 2 + var(--toast-haze) * 2), calc(var(--dialog-width-md) + var(--toast-haze) * 2));
    margin: 0;
    border: 0;
    background: transparent;
    padding: 0;
    overflow: visible;
    color: inherit;
    justify-items: center;
    pointer-events: none;
    transform: translate(-50%, -50%);
}
.toast-region[popover]:not(:popover-open) { display: none; }
/* 여러 개가 쌓이면 패널끼리 겹쳐 카드 사이만 --space-2로 둔다. */
.toast + .toast { margin-top: calc(var(--space-2) - var(--toast-haze) * 2); }
.toast {
    position: relative;
    display: flex;
    max-width: 100%;
    min-height: calc(var(--control-height-md) + var(--toast-haze) * 2);
    align-items: center;
    gap: var(--space-3);
    border-radius: calc(var(--radius-xl) + var(--toast-haze));
    background: radial-gradient(closest-side, rgb(255 255 255 / .5), rgb(240 248 250 / .38) 70%, rgb(240 248 250 / .2));
    padding: calc(var(--toast-haze) + var(--space-2)) calc(var(--toast-haze) + var(--space-5)) calc(var(--toast-haze) + var(--space-2)) calc(var(--toast-haze) + var(--space-2));
    color: var(--color-text);
    -webkit-backdrop-filter: blur(.875rem) saturate(1.3);
    backdrop-filter: blur(.875rem) saturate(1.3);
    --toast-feather: linear-gradient(to right, transparent, #000 var(--toast-haze), #000 calc(100% - var(--toast-haze)), transparent), linear-gradient(to bottom, transparent, #000 var(--toast-haze), #000 calc(100% - var(--toast-haze)), transparent);
    -webkit-mask-image: var(--toast-feather);
    -webkit-mask-composite: source-in;
    mask-image: var(--toast-feather);
    mask-composite: intersect;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    letter-spacing: var(--letter-spacing-snug);
    line-height: var(--line-height-guide);
    pointer-events: auto;
    cursor: default;
    animation: toast-enter var(--duration-slow) var(--ease-standard) both;
}
/* 또렷한 카드: 테두리·위 가장자리 빛·물빛 그림자와 유리에 맺힌 작은 물방울(위 왼쪽에 빛, 아래 가장자리가 물빛으로 진한 원). 바탕은 거의 비워 뒤의 뿌연 패널이 비친다. */
.toast::before {
    --toast-drop: radial-gradient(circle at 38% 32%, rgb(255 255 255 / .95) 0 14%, rgb(255 255 255 / .3) 34%, rgb(31 120 136 / .1) 58%, rgb(31 120 136 / .26) 68%, transparent 72%);
    position: absolute;
    inset: var(--toast-haze);
    border: var(--border-width) solid var(--toast-border);
    border-radius: var(--radius-xl);
    background:
        var(--toast-drop), var(--toast-drop), var(--toast-drop), var(--toast-drop), var(--toast-drop), var(--toast-drop),
        linear-gradient(to bottom, rgb(255 255 255 / .4), rgb(255 255 255 / .12) 50%);
    background-position: 1.4rem .3rem, 46% .2rem, 88% .35rem, 96% 72%, 64% 88%, .6rem 82%, 0 0;
    background-repeat: no-repeat;
    background-size: .4rem .45rem, .28rem .3rem, .5rem .55rem, .3rem .32rem, .36rem .4rem, .26rem .28rem, 100% 100%;
    box-shadow: inset 0 1px 0 rgb(255 255 255 / .9), var(--shadow-toast);
    content: "";
    pointer-events: none;
}
.toast__icon, .toast__message { position: relative; }
/* 남은 시간 선: JS가 --toast-duration을 넣는다. 카드 아래 테두리 안쪽에 둔다. */
.toast::after {
    position: absolute;
    inset: auto calc(var(--toast-haze) + var(--space-4)) calc(var(--toast-haze) + var(--border-width));
    height: var(--border-width-accent);
    border-radius: var(--radius-pill);
    background: color-mix(in srgb, var(--toast-color) 55%, transparent);
    content: "";
    transform-origin: left center;
    animation: toast-timer var(--toast-duration, 2500ms) linear both;
}
.toast:hover::after { animation-play-state: paused; }
.toast__icon {
    display: inline-flex;
    flex: 0 0 auto;
    width: var(--control-height-xs);
    height: var(--control-height-xs);
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-pill);
    background: var(--toast-soft);
    color: var(--toast-color);
}
/* 문장마다 한 줄(js가 나눈다). 한국어는 낱말 중간에서 끊지 않고, 넘치는 줄은 고르게 나눈다. */
.toast__message { min-width: 0; word-break: keep-all; overflow-wrap: anywhere; }
.toast__line { display: block; text-wrap: pretty; }
.toast[data-leaving] { animation: toast-exit var(--duration-base) var(--ease-standard) both; }
.toast--success { --toast-color: var(--color-success); --toast-soft: var(--color-success-soft); --toast-border: color-mix(in srgb, var(--color-success) 30%, rgb(255 255 255 / .85)); }
.toast--error { --toast-color: var(--color-danger); --toast-soft: var(--color-danger-soft); --toast-border: color-mix(in srgb, var(--color-danger) 34%, rgb(255 255 255 / .85)); }
.toast--warning { --toast-color: var(--color-warning); --toast-soft: var(--color-warning-soft); --toast-border: color-mix(in srgb, var(--color-warning) 34%, rgb(255 255 255 / .85)); }
.toast--info { --toast-color: var(--color-brand); --toast-soft: var(--color-brand-soft); --toast-border: color-mix(in srgb, var(--color-brand) 28%, rgb(255 255 255 / .85)); }

@keyframes toast-enter {
    from { opacity: 0; transform: translateY(var(--space-3)) scale(.96); }
    to { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes toast-exit {
    from { opacity: 1; transform: translateY(0) scale(1); }
    to { opacity: 0; transform: translateY(calc(0rem - var(--space-2))) scale(.98); }
}

@keyframes toast-timer {
    from { transform: scaleX(1); }
    to { transform: scaleX(0); }
}

/* Forms */
.form-interaction-blocker {
    position: fixed;
    inset: 0;
    z-index: var(--z-toast);
    background: transparent;
    cursor: progress;
    touch-action: none;
}

.form-action { position: relative; }
.form-action__view { display: none; align-items: center; justify-content: center; gap: var(--space-2); }
.form-action[data-action-state="idle"] [data-action-view="idle"],
.form-action[data-action-state="confirm"] [data-action-view="confirm"],
.form-action[data-action-state="loading"] [data-action-view="loading"],
.form-action[data-action-state="success"] [data-action-view="success"],
.form-action[data-action-state="error"] [data-action-view="error"] { display: inline-flex; }
.form-action--icon-only[data-action-state="confirm"] { width: fit-content; padding: var(--button-padding-y) var(--button-padding-x); }
.form-action__confirm-accept { font-weight: var(--font-weight-semibold); }
.form-action__countdown { position: relative; display: inline-grid; width: var(--space-4); height: var(--space-4); flex: 0 0 var(--space-4); place-items: center; font-size: .625rem; font-weight: var(--font-weight-semibold); font-variant-numeric: tabular-nums; line-height: 1; vertical-align: middle; }
.form-action__countdown svg { position: absolute; inset: 0; width: 100%; height: 100%; fill: none; stroke: currentColor; stroke-width: 2; }
.form-action__countdown [data-action-countdown] { position: absolute; inset: 0; display: grid; place-items: center; line-height: 1; }
.form-action__countdown-track { opacity: .3; }
.form-action__countdown-progress { stroke-dasharray: 62.83; stroke-dashoffset: 0; stroke-linecap: round; transform: rotate(-90deg); transform-origin: 50% 50%; transition: stroke-dashoffset .1s linear; }
.form-action--confirm-danger[data-action-state="confirm"],
.form-action--confirm-danger[data-action-state="loading"] { border-color: var(--color-danger); background: var(--color-danger); color: var(--color-surface); }
.form-action:not(.form-action--plain)[data-action-state="success"] { background: var(--color-success); border-color: var(--color-success); }
.form-action:not(.form-action--plain)[data-action-state="error"] { background: var(--color-danger); border-color: var(--color-danger); }
/* 글자만 있는 저장(ghost)은 배경 없이 글자 색으로 결과를 보인다. */
.form-action.btn-ghost[data-action-state="success"] { background: transparent; border-color: transparent; color: var(--color-success); }
.form-action.btn-ghost[data-action-state="error"] { background: transparent; border-color: transparent; color: var(--color-danger); }
.form-action--plain { gap: var(--space-2); }
.form-action--plain .form-action__view { gap: inherit; }
/* 입력칸 옆 완료 표시: 비활성 버튼처럼 흐리게 하지 않고 성공 색으로 보여 준다. */
.btn.form-action-done:disabled { border-color: var(--color-success-soft); background: var(--color-success-soft); color: var(--color-success); opacity: 1; cursor: default; }

@media (hover: hover) {
    .form-action--confirm-danger[data-action-state="confirm"]:hover { border-color: var(--color-danger-hover); background: var(--color-danger-hover); }
}

/* 필드 안내 슬롯(x-form.guide). 모든 폼이 같은 리듬을 쓴다: 빈 슬롯은 자리를 차지하지 않고 필드 사이는 --form-stack-gap만 띄운다.
   포커스 안내는 잠깐 뜨는 글이라 흐름 밖(absolute)에서 다음 필드 라벨 위에 겹쳐 보이고, 오류·상태는 흐름 안에 남는다.
   필드 뒤가 필드가 아니면(버튼·체크·다음 그룹 제목) 포커스 안내도 흐름 안에 두어 그 요소를 덮지 않는다. */
.form-field__guide-slot {
    position: relative;
    height: 0;
    margin: 0;
    font-size: var(--font-size-sm);
    line-height: var(--line-height-guide);
}
.form-field__guide-slot > .form-field__message {
    min-height: 0;
    margin: 0;
    font-size: inherit;
    line-height: inherit;
    overflow-wrap: anywhere;
}
.form-field__guide-slot [data-field-guide-icon] { margin-inline-end: var(--space-1); }
.form-field__guide-slot > .form-field__message[data-guide-state="none"] { display: none; }
.form-field__guide-slot > .form-field__message[data-guide-state="focus"] {
    position: absolute;
    z-index: 2;
    inset: var(--space-1) 0 auto;
    display: block;
    max-width: 100%;
    color: var(--color-text-muted);
    pointer-events: none;
}
.form-field__guide-slot > .form-field__message[data-guide-state="status"] { color: var(--color-text-muted); }
.form-field__guide-slot:has(> .form-field__message:is([data-guide-state="error"], [data-guide-state="status"])),
:not(.form-grid) > .form-field:is(:last-child, :has(+ :not(.form-field, .form-grid))) .form-field__guide-slot:has(> .form-field__message[data-guide-state="focus"]),
.form-section__body > :last-child > .form-field:nth-last-child(-n+2 of .form-field) .form-field__guide-slot:has(> .form-field__message[data-guide-state="focus"]),
.form-grid--guide-flow > .form-field .form-field__guide-slot:has(> .form-field__message[data-guide-state="focus"]) {
    height: auto;
    margin-top: var(--space-1);
}
:not(.form-grid) > .form-field:is(:last-child, :has(+ :not(.form-field, .form-grid))) .form-field__guide-slot > .form-field__message[data-guide-state="focus"],
.form-section__body > :last-child > .form-field:nth-last-child(-n+2 of .form-field) .form-field__guide-slot > .form-field__message[data-guide-state="focus"],
.form-grid--guide-flow > .form-field .form-field__guide-slot > .form-field__message[data-guide-state="focus"] { position: static; }

/* 한 칸 인라인 수정(닉네임 등): 입력칸 옆에 저장 버튼 하나. 취소 버튼 대신 바깥을 누르거나 Esc로 닫는다(app.js data-inline-dismiss).
   필드를 펼쳐(display: contents) 버튼을 입력줄 아래쪽 선에 맞추고, 안내·오류는 다음 줄 전체 폭에 둔다. */
.inline-edit { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: end; column-gap: var(--space-2); }
.inline-edit[hidden] { display: none; }
.inline-edit > .form-field { display: contents; }
.inline-edit > .form-field > .form-field__guide-slot { grid-column: 1 / -1; }
.inline-edit > .btn { grid-row: 1; grid-column: 2; margin-bottom: var(--space-2); }
/* 작은 한 칸 수정(.inline-edit--compact): 플로팅 라벨 없이 그 줄 글자 크기의 입력칸과 글자만 있는 xs 저장(ghost)이 한 줄에 붙는다(투어 참가자 줄 닉네임).
   입력칸 폭은 값 길이를 따라가되(field-sizing) 남은 폭에서 줄어들고, 버튼은 늘 입력칸 옆에 한 줄로 둔다. 오류 안내는 그 아래 줄에 나온다.
   보기 줄과 바뀌어도 줄이 출렁이지 않게 입력칸·버튼은 위아래로 넘쳐 그리고, 폼이 차지하는 높이는 그 줄 한 줄(1lh)이다. */
.inline-edit--compact { grid-template-columns: minmax(0, max-content) auto; justify-content: start; align-items: center; column-gap: var(--space-1); }
.inline-edit--compact .form-field__label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.inline-edit--compact .form-field__input { border-width: 0 0 var(--border-width); border-radius: 0; box-shadow: none; width: auto; min-width: 4rem; max-width: 100%; min-height: var(--control-height-xs); field-sizing: content; padding: 0 var(--space-1); font-size: inherit; }
.inline-edit--compact .form-field__input:is(:focus, [aria-invalid="true"]) { box-shadow: none; }
.inline-edit--compact > .btn { --button-padding-x: var(--space-2); margin: 0; white-space: nowrap; }
.inline-edit--compact > .form-field > .form-field__control,
.inline-edit--compact > .btn { margin-block: calc((1lh - var(--control-height-xs)) / 2); }
/* 한 자리 전환(data-inline-swap, app.js swapInline): 보기 줄과 수정 폼이 같은 자리에서 바뀐다. 나가는 줄은 위에 겹친 채 사라지고 상자 높이만 이어서 바뀐다. */
[data-inline-swap] { position: relative; }
[data-inline-swap] > .is-leaving { position: absolute; inset: 0 0 auto; pointer-events: none; }
/* 보기 줄 끝의 연필 버튼(data-inline-toggle): 내 슬레이트 닉네임, 투어 참가자 줄 닉네임이 같이 쓴다.
   누를 칸이 글자 쪽으로 당겨져 있어 hover 배경은 두지 않고 아이콘 색만 바꾼다. */
.inline-edit-toggle { display: inline-flex; width: var(--control-height-xs); height: var(--control-height-xs); flex: 0 0 auto; align-items: center; justify-content: center; border-radius: var(--radius-sm); color: var(--color-text-muted); }
.inline-edit-toggle:focus-visible { outline: var(--border-width-accent) solid var(--color-focus); outline-offset: calc(var(--border-width) * -1); }
@media (hover: hover) {
    .inline-edit-toggle:hover { color: var(--color-brand); }
}

.form-loading {
    position: fixed;
    inset: 0;
    z-index: var(--z-toast);
    display: grid;
    place-items: center;
    padding: var(--gutter);
    background: color-mix(in srgb, var(--color-app) 16%, transparent);
    cursor: progress;
}

.form-loading__panel {
    width: min(100%, calc(var(--space-16) * 2));
    animation: form-loading-enter var(--duration-base) var(--ease-standard) both;
}

.form-loading__bubbles {
    position: relative;
    aspect-ratio: 1;
}

.form-loading__bubble {
    --bubble-size: var(--space-3);
    --bubble-drift: var(--space-2);
    position: absolute;
    bottom: var(--space-2);
    left: calc(50% - var(--bubble-size) / 2);
    width: var(--bubble-size);
    height: var(--bubble-size);
    border: var(--border-width) solid var(--color-brand-mid);
    border-radius: 50%;
    background: radial-gradient(circle at 30% 25%, color-mix(in srgb, var(--color-surface) 85%, transparent), transparent 55%), color-mix(in srgb, var(--color-brand-light) 18%, transparent);
    opacity: 0;
    animation: form-loading-bubble 3.2s linear infinite;
}

.form-loading__bubble::after {
    position: absolute;
    top: 18%;
    left: 22%;
    width: 25%;
    height: 18%;
    border-radius: var(--radius-pill);
    background: var(--color-surface);
    content: '';
}

.form-loading__bubble:nth-of-type(2) {
    --bubble-size: var(--space-5);
    --bubble-drift: calc(-1 * var(--space-6));
    animation-delay: -.18s;
}

.form-loading__bubble:nth-of-type(3) {
    --bubble-size: var(--space-2);
    --bubble-drift: var(--space-8);
    animation-delay: -.4s;
}

.form-loading__bubble:nth-of-type(4) {
    --bubble-size: var(--space-4);
    --bubble-drift: var(--space-4);
    animation-delay: -.62s;
}

.form-loading__bubble:nth-of-type(5) {
    --bubble-size: var(--space-1);
    --bubble-drift: calc(-1 * var(--space-10));
    animation-delay: -.85s;
}

.form-loading__bubble:nth-of-type(6) {
    --bubble-drift: calc(-1 * var(--space-3));
    animation-delay: -1.05s;
}

.form-loading__bubble:nth-of-type(7) {
    --bubble-size: var(--space-2);
    --bubble-drift: var(--space-10);
    animation-delay: -1.23s;
}

.form-loading__bubble:nth-of-type(8) {
    --bubble-size: var(--space-4);
    --bubble-drift: calc(-1 * var(--space-8));
    animation-delay: -1.4s;
}

.form-loading__track {
    position: absolute;
    inset: 0 0 auto;
    height: .1875rem;
    overflow: hidden;
    background: var(--color-brand-soft);
}

.form-loading__track > span {
    display: block;
    width: 35%;
    height: 100%;
    border-radius: var(--radius-pill);
    background: linear-gradient(90deg, var(--color-brand-mid), var(--color-brand));
    animation: form-loading-progress 1.6s ease-in-out infinite;
}

@keyframes form-loading-progress {
    from { transform: translateX(-100%); }
    to { transform: translateX(300%); }
}

@keyframes form-loading-enter {
    from { opacity: 0; transform: translateY(var(--space-2)); }
    to { opacity: 1; transform: translateY(0); }
}

@keyframes form-loading-bubble {
    0% { opacity: 0; transform: translate(0, 0) scale(.4); }
    12% { opacity: .9; }
    40% {
        opacity: .8;
        border-radius: 44% 56% 50% 50% / 50% 46% 54% 50%;
        transform: translate(calc(var(--bubble-drift) * .35), calc(-1 * var(--space-10))) scale(.9, 1.05);
    }
    70% { opacity: .5; }
    100% {
        opacity: 0;
        transform: translate(var(--bubble-drift), calc(-1 * var(--space-24))) scale(1.2, 1.05);
    }
}

.form-label {
    display: block;
    margin-bottom: var(--space-2);
    color: var(--color-text);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
}

.form-control {
    width: 100%;
    min-height: var(--control-height);
    border: var(--border-width) solid var(--color-border-strong);
    border-radius: var(--radius-lg);
    background: var(--color-surface);
    color: var(--color-text);
    padding: .6875rem .9375rem;
    font-size: var(--font-size-base);
    line-height: 1.5;
    outline: none;
    transition: border-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard), background-color var(--duration-fast) var(--ease-standard);
}

.form-control::placeholder { color: var(--color-text-muted); opacity: .8; }
.form-control:focus { border-color: var(--color-brand); box-shadow: 0 0 0 .1875rem color-mix(in srgb, var(--color-brand-light) 72%, transparent); }
.form-control[readonly] { background: var(--color-surface-soft); color: var(--color-text-secondary); }
.form-control:disabled { cursor: not-allowed; background-color: #eef2f2; color: var(--color-text-muted); opacity: 1; }
.form-control[aria-invalid="true"] { border-color: var(--color-danger); }

.form-error:empty { display: none; }
.form-error {
    margin-top: var(--space-2);
    color: var(--color-danger);
    font-size: var(--font-size-sm);
    line-height: 1.5;
}

/* Standard label-first text fields share one floating label motion. */
.form-floating { position: relative; }
.form-floating > .form-label {
    position: absolute;
    z-index: 1;
    top: 1.5rem;
    left: 1rem;
    max-width: calc(100% - 2rem);
    margin: 0;
    overflow: hidden;
    color: var(--color-text);
    text-overflow: ellipsis;
    white-space: nowrap;
    transform: translateY(-50%) scale(1);
    transform-origin: left center;
    pointer-events: none;
    transition: transform 220ms var(--ease-standard), color 220ms var(--ease-standard);
}
.form-floating > .form-control { padding-top: 1.35rem; padding-bottom: .35rem; }
.form-floating > .form-control::placeholder { opacity: 0; }
.form-floating > .form-control:focus::placeholder { opacity: .8; }
.form-floating > .form-label:has(+ .form-control:focus),
.form-floating--filled > .form-label {
    transform: translateY(-1.3rem) scale(.85);
}
.form-floating > .form-label:has(+ .form-control:focus) { color: var(--color-brand); }
.form-floating:has(> .form-control[aria-invalid="true"]) > .form-label { color: var(--color-danger); }

/* 입력칸: 테두리 상자 + 노치 플로팅 라벨(docs/ui/design-style.md 3절). 올라간 라벨은 테두리에 걸쳐 선을 끊고, 상자 안에는 값만 둔다.
   포커스는 테두리를 브랜드색 두 겹(안쪽 그림자)으로, 오류는 포커스와 상관없이 위험색 두 겹으로 보인다. 바깥 포커스 그림자는 두지 않는다.
   읽기 전용 값(자물쇠, 날짜 선택 등)도 같은 상자이고, 막힌 칸(disabled)만 옅은 바탕이다. 표 안 작은 입력(.inline-edit--compact)은 밑줄을 유지한다. */
/* 끊긴 자리는 라벨 바탕이 가린다. 위 절반은 칸이 놓인 면, 아래 절반은 칸 안 색이다. 흰색이 아닌 면은 그 면에서 --form-field-notch-bg만 바꾼다.
   .form-field에서 다시 선언하면 면에서 바꾼 값이 가려지므로 :root에만 둔다. */
:root { --form-field-notch-bg: var(--color-surface); }
/* 입력칸 치수 토큰. :root에도 두어 입력칸 옆 버튼(.my-input-group 등)이 같은 줄에 맞춘다.
   .form-field에서 다시 선언하므로 화면별로 바꾼 --form-field-padding-block이 높이·rest-line에도 반영된다. */
:root,
.form-field {
    /* 상자 안에는 값만 있어 위·아래 여백이 같다. */
    --form-field-padding-block: .8125rem;
    --form-field-padding-inline: var(--space-5);
    /* 올라간 라벨 양옆으로 테두리가 비는 폭. */
    --form-field-notch-gap: var(--space-2);
    --form-field-notch-inner: var(--color-surface);
    /* 한 줄 입력칸 전체 높이. 글자 크기가 작은 버튼에서도 같은 값이 되도록 em 대신 --font-size-base로 계산한다. */
    --form-field-height: calc(var(--form-field-padding-block) * 2 + var(--font-size-base) * 1.5 + var(--border-width) * 2);
    /* 값·내려와 있는 라벨·검색 아이콘·select 화살표·입력칸 옆 버튼이 함께 맞추는 줄 = 상자 높이의 가운데. */
    --form-field-rest-line: calc(var(--form-field-height) / 2);
}
.form-field { min-width: 0; }
.form-field__control { position: relative; }
.form-field__input {
    display: block;
    width: 100%;
    min-width: 0;
    min-height: var(--form-field-height);
    border: var(--border-width) solid var(--color-border-strong);
    border-radius: var(--radius-lg);
    background: var(--color-surface);
    color: var(--color-text);
    padding: var(--form-field-padding-block) var(--form-field-padding-inline);
    font: inherit;
    line-height: 1.5;
    outline: none;
    transition: border-color 200ms var(--ease-standard), box-shadow 200ms var(--ease-standard);
}
.form-field__input:focus-visible { outline: none; }
.form-field__input:focus:where(:not([readonly])) { box-shadow: inset 0 0 0 var(--border-width) var(--color-brand); }
/* 숨겨 둔 안내 문구가 드래그 선택 때 라벨 밑에서 드러나지 않도록 placeholder는 선택 대상에서 뺀다. */
.form-field__input::placeholder { color: transparent; font-size: var(--font-size-sm); text-overflow: ellipsis; opacity: 1; -webkit-user-select: none; user-select: none; transition: color 200ms var(--ease-standard); }
/* Focus guidance appears as the placeholder once the floating label has risen. */
.form-field__input:focus:not([readonly])::placeholder { color: var(--color-text-muted); transition-delay: 120ms; }
select.form-control,
.form-field__input--select {
    appearance: none;
    padding-right: 2.75rem;
    background-image: linear-gradient(45deg, transparent 50%, var(--color-text-secondary) 50%), linear-gradient(135deg, var(--color-text-secondary) 50%, transparent 50%);
    background-position: calc(100% - 1.15rem) calc(50% - .1rem), calc(100% - .8rem) calc(50% - .1rem);
    background-repeat: no-repeat;
    background-size: .4rem .4rem, .4rem .4rem;
}
.form-field__label {
    position: absolute;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    /* 내려와 있는 라벨은 select 화살표·검색 아이콘과 같은 rest-line(상자 가운데)에 둔다. */
    top: var(--form-field-rest-line);
    left: var(--form-field-padding-inline);
    max-width: calc(100% - var(--form-field-padding-inline) - var(--form-field-padding-inline));
    overflow: hidden;
    color: var(--color-text);
    font-weight: var(--font-weight-medium);
    text-overflow: ellipsis;
    white-space: nowrap;
    transform: translateY(-50%);
    transform-origin: left center;
    pointer-events: none;
    transition: top 200ms var(--ease-standard), left 200ms var(--ease-standard), padding 200ms var(--ease-standard), font-size 200ms var(--ease-standard), color 200ms var(--ease-standard);
}
.form-field__label-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.form-field__readonly { display: none; position: absolute; z-index: 1; top: calc(var(--form-field-rest-line) - var(--space-4) / 2); left: var(--form-field-padding-inline); width: var(--space-4); height: var(--space-4); align-items: center; justify-content: center; color: var(--color-text-secondary); pointer-events: none; }
.form-field__input[readonly] ~ .form-field__readonly { display: flex; }
.form-field__input--select + .form-field__label { max-width: calc(100% - var(--form-field-padding-inline) - var(--space-10)); }
/* form-select.js: the field opens the shared result panel instead of the native popup. */
.form-field__input--select { background-position: calc(100% - 1.15rem) calc(var(--form-field-rest-line) - .2rem), calc(100% - .8rem) calc(var(--form-field-rest-line) - .2rem); }
.form-field__input--select[aria-expanded="true"] { background-image: linear-gradient(135deg, transparent 50%, var(--color-brand) 50%), linear-gradient(45deg, var(--color-brand) 50%, transparent 50%); }
.form-field__input--select[data-form-select-ready] { pointer-events: none; }
.form-field__control:has(> .form-field__input--select[data-form-select-ready]:not(:disabled)) { cursor: pointer; }
.form-field__control:has(> .form-field__input--select[data-form-select-ready]) .form-search__option:not([aria-disabled="true"]) { cursor: pointer; }
.form-field__input:focus + .form-field__label,
.form-field__input:not(:placeholder-shown) + .form-field__label,
.form-field__input[readonly] + .form-field__label,
.form-field__input--raised-label + .form-field__label,
.form-field__control:has(> .form-field__info:is(:focus-within, [open])) > .form-field__label {
    top: calc(var(--border-width) / 2);
    left: calc(var(--form-field-padding-inline) - var(--form-field-notch-gap));
    max-width: calc(100% - (var(--form-field-padding-inline) - var(--form-field-notch-gap)) * 2);
    padding-inline: var(--form-field-notch-gap);
    background: linear-gradient(var(--form-field-notch-bg) 50%, var(--form-field-notch-inner) 50%);
    color: var(--color-text-secondary);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    line-height: 1;
}
.form-field__input:focus:where(:not([readonly])) { border-color: var(--color-brand); }
.form-field__input:focus:where(:not([readonly])) + .form-field__label { color: var(--color-brand); }
/* 오류는 포커스 중에도 위험색 두 겹이다(포커스 규칙보다 뒤에 둔다). */
.form-field__input[aria-invalid="true"] { border-color: var(--color-danger); box-shadow: inset 0 0 0 var(--border-width) var(--color-danger); }
.form-field__input[aria-invalid="true"] + .form-field__label { color: var(--color-danger); }
.form-field__input[readonly] { padding-left: calc(var(--form-field-padding-inline) + var(--space-6)); }
.form-field--plain-readonly .form-field__input[readonly] { padding-left: var(--form-field-padding-inline); }
/* 도움말(?): 테두리에 걸친 라벨 바로 오른쪽에 작게 둔다. 라벨이 입력칸 안에 내려와 있을 때는 숨긴다.
   summary::before에 같은 글꼴의 라벨 문구를 보이지 않게 넣어 라벨 너비만큼 띄우고, 아이콘만 누를 수 있다.
   ?를 누르는 동안 입력칸 포커스가 유지되도록 forms.js가 mousedown을 막고, 키보드로 ?에 오면 라벨을 올린 채 둔다. */
.form-field--info .form-field__label { max-width: calc(100% - var(--form-field-padding-inline) * 2 - var(--space-5)); }
.form-field--info .form-field__input:focus + .form-field__label,
.form-field--info .form-field__input:not(:placeholder-shown) + .form-field__label,
.form-field--info .form-field__input[readonly] + .form-field__label,
.form-field--info .form-field__input--raised-label + .form-field__label { max-width: calc(100% - var(--form-field-padding-inline) * 2 - var(--space-3)); }
.form-field__info { position: absolute; z-index: 2; top: calc(var(--border-width) / 2); left: var(--form-field-padding-inline); max-width: calc(100% - var(--form-field-padding-inline) * 2); color: var(--color-text-secondary); font-size: var(--font-size-xs); font-weight: var(--font-weight-semibold); line-height: 1; pointer-events: none; transform: translateY(-50%); }
/* 숨김 → 표시: 플로팅 라벨(200ms)이 거의 올라간 뒤 나타나고, 표시 → 숨김: 라벨이 내려가기 시작할 때 먼저 빠르게 사라진다.
   visibility도 함께 바꿔 숨은 동안에는 포커스·클릭되지 않는다. */
.form-field__info > summary { display: flex; align-items: center; gap: var(--space-1); list-style: none; cursor: default; visibility: hidden; opacity: 0; transition: opacity 120ms var(--ease-standard), visibility 0s linear 120ms; }
.form-field__input:focus ~ .form-field__info > summary,
.form-field__input:not(:placeholder-shown) ~ .form-field__info > summary,
.form-field__input[readonly] ~ .form-field__info > summary,
.form-field__input--raised-label ~ .form-field__info > summary,
.form-field__info:is(:focus-within, [open]) > summary { visibility: visible; opacity: 1; transition: opacity 180ms var(--ease-standard) 140ms, visibility 0s linear 140ms; }
.form-field__info > summary::before { content: attr(data-label); min-width: 0; overflow: hidden; visibility: hidden; white-space: nowrap; }
.form-field__info > summary::-webkit-details-marker { display: none; }
/* ? 표시: 브랜드 톤의 작은 원. 나타날 때 살짝 커지며 자리 잡고, 누르거나 열려 있으면 채워진다. */
.form-field__info-mark { display: inline-flex; flex: none; width: 1rem; height: 1rem; align-items: center; justify-content: center; border: var(--border-width) solid var(--color-brand-light); border-radius: var(--radius-pill); background: var(--color-brand-soft); color: var(--color-brand); font-size: .625rem; font-weight: var(--font-weight-semibold); line-height: 1; pointer-events: auto; cursor: pointer; box-shadow: 0 0 0 var(--space-1) var(--form-field-notch-bg); transform: scale(.6); transition: transform 120ms var(--ease-standard), background-color var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard); }
.form-field__input:focus ~ .form-field__info .form-field__info-mark,
.form-field__input:not(:placeholder-shown) ~ .form-field__info .form-field__info-mark,
.form-field__input[readonly] ~ .form-field__info .form-field__info-mark,
.form-field__input--raised-label ~ .form-field__info .form-field__info-mark,
.form-field__info:is(:focus-within, [open]) .form-field__info-mark { transform: none; transition: transform 220ms cubic-bezier(.34, 1.56, .64, 1) 140ms, background-color var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard); }
/* 키보드 포커스 링은 보이지 않는 라벨 자리까지 감싸지 않고 ? 원에만 둔다. */
.form-field__info > summary:focus-visible { outline: none; }
.form-field__info > summary:focus-visible .form-field__info-mark { outline: .1875rem solid var(--color-focus); outline-offset: .125rem; }
.form-field__info[open] .form-field__info-mark { border-color: var(--color-brand); background: var(--color-brand); color: var(--color-surface); }
@media (hover: hover) {
    .form-field__info-mark:hover { border-color: var(--color-brand); background: var(--color-brand); color: var(--color-surface); }
}
.form-field__tooltip { position: absolute; z-index: var(--z-dropdown); top: calc(100% + var(--space-1)); left: 0; font-weight: var(--font-weight-medium); line-height: var(--line-height-body); width: max-content; max-width: min(var(--panel-width-sm), calc(100vw - var(--space-12))); padding: var(--space-3); border: var(--border-width) solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface); box-shadow: var(--shadow-md); font-size: var(--font-size-sm); overflow-wrap: anywhere; }
.form-field__input[readonly]:focus-visible + .form-field__label,
.form-field__input[readonly]:focus-visible ~ .form-field__readonly { color: var(--color-focus); }
.form-field__input[readonly]:focus-visible + .form-field__label .form-field__label-text { text-decoration: underline; text-underline-offset: var(--space-1); }
.form-field__input:disabled { cursor: not-allowed; background-color: var(--color-surface-soft); color: var(--color-text-muted); }
.form-field__input:disabled + .form-field__label { --form-field-notch-inner: var(--color-surface-soft); color: var(--color-text-muted); }
.form-field__input--search { padding-right: var(--space-10); }
.form-field__input--search + .form-field__label { max-width: calc(100% - var(--form-field-padding-inline) - var(--space-10)); }
/* align="center": 값·플로팅 라벨·안내가 칸의 가운데 축을 함께 쓴다. */
.form-field--center .form-field__input { text-align: center; text-align-last: center; }
.form-field--center .form-field__input[readonly] { padding-inline: calc(var(--form-field-padding-inline) + var(--space-6)); }
.form-field--center.form-field--plain-readonly .form-field__input[readonly] { padding-inline: var(--form-field-padding-inline); }
/* 가운데 정렬: 왼쪽에 아이콘만큼 빈 자리를 두어 보이지 않는 라벨 자리가 실제 라벨과 같은 가운데에 오게 한다. */
.form-field--center .form-field__info { left: 50%; transform: translate(-50%, -50%); }
.form-field--center .form-field__info > summary { padding-left: calc(1rem + var(--space-1)); }
.form-field--center .form-field__label { left: 50%; transform: translate(-50%, -50%); transform-origin: center; }
.form-field--center .form-field__input:focus + .form-field__label,
.form-field--center .form-field__input:not(:placeholder-shown) + .form-field__label,
.form-field--center .form-field__input[readonly] + .form-field__label,
.form-field--center .form-field__input--raised-label + .form-field__label { left: 50%; }
.form-field--center .form-field__message { text-align: center; }
/* 아이콘은 플로팅 라벨 줄이 아니라 내려와 있는 라벨과 같은 rest-line에 둔다. */
.form-field__search-icon { position: absolute; top: calc(var(--form-field-rest-line) - var(--space-6) / 2); right: var(--form-field-padding-inline); display: flex; align-items: center; justify-content: center; width: var(--space-6); height: var(--space-6); color: var(--color-text-muted); pointer-events: none; }
.form-field__input--search:focus ~ .form-field__search-icon { color: var(--color-brand); }
.form-field__input--search::-webkit-calendar-picker-indicator,
.form-field__input--search::-webkit-search-cancel-button { display: none; }
.form-search { position: absolute; z-index: var(--z-dropdown); top: calc(100% + var(--space-2)); right: 0; left: 0; overflow: hidden; border: var(--border-width) solid var(--color-border); border-radius: var(--radius-lg); background: var(--color-surface); color: var(--color-text); box-shadow: var(--shadow-md); }
.form-search--above { top: auto; bottom: calc(100% + var(--space-2)); }
.form-search__options { position: relative; max-height: min(20rem, 40vh, var(--form-search-available-height, 20rem)); overflow-y: auto; overscroll-behavior: contain; padding: var(--space-2); }
.form-search__options:empty { display: none; }
.form-search__option { display: flex; align-items: center; min-height: var(--control-height); border-radius: var(--radius-md); padding: var(--space-3); font-size: var(--font-size-sm); line-height: var(--line-height-body); overflow-wrap: anywhere; }
.form-search__option + .form-search__option { margin-top: var(--space-1); }
.form-search__option:hover,
.form-search__option.is-active,
.form-search__option[aria-selected="true"] { background: var(--color-brand-soft); color: var(--color-brand); }
.form-search__option[aria-disabled="true"] { background: transparent; color: var(--color-text-muted); cursor: not-allowed; }
/* form-select.js: label + detail rows (e.g. "JPY 일본 엔"). The panel may grow past a narrow field up to the screen;
   positionPanel aligns it to the field's end edge when the start side has no room. The code never breaks. */
.form-search--wide { right: auto; width: max-content; min-width: 100%; max-width: min(20rem, calc(100vw - 2 * var(--space-4))); }
.form-search--wide.form-search--end { right: 0; left: auto; }
.form-search__option-label { flex: 0 0 auto; white-space: nowrap; }
.form-search__option-detail { min-width: 0; margin-left: var(--space-2); color: var(--color-text-secondary); font-size: var(--font-size-xs); overflow-wrap: normal; word-break: keep-all; }
.form-search__option mark {background: transparent; color: var(--color-brand); font-weight: var(--font-weight-semibold); }
.form-search__empty { margin: 0; padding: var(--space-4); color: var(--color-text-muted); font-size: var(--font-size-sm); }
.form-field__message { min-height: 1lh; margin-top: var(--space-1); color: var(--color-text-muted); font-size: var(--font-size-sm); line-height: var(--line-height-guide); overflow-wrap: anywhere; }
.form-field__message[role="alert"] { color: var(--color-danger); }
.form-field__message[role="status"] { color: var(--color-success); }

@media (forced-colors: active) {
    .form-field__input { border-color: CanvasText; }
    .form-field__input:focus:where(:not([readonly])),
    .form-field__input:where(:not([data-form-filled]):not(:placeholder-shown), [data-form-filled="true"]):where(:not([readonly])) { border-color: Highlight; }
    .form-field__input[aria-invalid="true"] { border-color: Mark; }
    .form-field__input[readonly]:focus-visible + .form-field__label,
    .form-field__input[readonly]:focus-visible ~ .form-field__readonly { color: Highlight; }
}

.form-grid {
    display: grid;
    gap: var(--form-stack-gap) var(--space-5);
}

/* 로그인·가입 페이지 폼: 필드 묶음(form-section)과 제출 버튼 사이. */
.auth-form { display: flex; flex-direction: column; gap: var(--space-6); margin-top: var(--space-6); }

.action-group {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
}

/* 가운데 나침반 바늘. 뒤따르는 저장 버튼이 있으면 JS가 그쪽으로 돌린다. 위아래 간격은 --section-ending-gap. */
.section-ending-signature {
    display: block;
    width: var(--space-6);
    height: var(--space-10);
    margin-inline: auto;
    color: var(--color-brand);
    transform: rotate(var(--section-ending-angle, 0deg));
}
[data-section-ending] .section-ending-signature { visibility: hidden; }
[data-section-ending][data-section-ending-aimed] .section-ending-signature { visibility: visible; }

.form-check {
    display: flex;
    min-height: var(--control-height);
    align-items: center;
    gap: var(--space-3);
    border: 0;
    background: transparent;
    padding: var(--space-2) 0;
}

/* 체크박스 한 가지 모양: 기본 input과 버튼형 체크(.check-box, 예: 투어 공유 체크리스트)가 같은 네모와 같은 배경 SVG 체크 표시를 쓴다.
   누를 수 없는 그림(체크리스트 미리보기)의 체크된 모양은 .check-box--checked.
   .check-box는 빈 span이다(안쪽 아이콘을 넣으면 .icon 크기를 받아 네모를 넘친다). 라디오는 브라우저 기본을 둔다. */
input[type="checkbox"],
.check-box {
    display: inline-block;
    width: var(--check-box-size);
    height: var(--check-box-size);
    flex: 0 0 auto;
    margin: 0;
    border: var(--border-width-accent) solid var(--color-border-strong);
    border-radius: var(--radius-sm);
    /* 체크 이미지는 안쪽 영역 전체에 깔고 여백은 SVG viewBox로 준다. 비율로 줄이면 위치가 소수점 픽셀이 되어 화면마다 치우쳐 보인다. */
    background: var(--color-surface) no-repeat 0 0 / 100% 100%;
    appearance: none;
    transition: background-color var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard);
}
input[type="checkbox"]:checked,
[aria-pressed="true"] > .check-box,
.check-box--checked {
    border-color: var(--color-brand);
    background-color: var(--color-brand);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-2 -2 20 20'%3E%3Cpath d='M3 7.75l3.25 3.25L13 4.25' fill='none' stroke='%23fff' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
input[type="checkbox"]:focus-visible {
    outline: var(--border-width-accent) solid var(--color-focus);
    outline-offset: var(--border-width);
}
input[type="checkbox"]:disabled { opacity: .55; }
@media (hover: hover) {
    input[type="checkbox"]:not(:disabled, :checked):hover,
    :where(label:hover) > input[type="checkbox"]:not(:disabled, :checked),
    :where(button:hover) > .check-box { border-color: var(--color-brand-mid); }
}

.form-check-input[type="radio"] {
    width: 1.25rem;
    height: 1.25rem;
    flex: 0 0 auto;
    accent-color: var(--color-brand);
}
.form-check:has(> input:disabled),
.form-check-input:disabled { cursor: not-allowed; }
.form-check > span { min-width: 0; }
/* Label + description (x-form.check): stacked, with the box level with the first line. */
.form-check:has(> span > small) { align-items: flex-start; }
.form-check:has(> span > small) > .form-check-input { margin-top: calc((var(--line-height-body) * 1rem - var(--check-box-size)) / 2); }
.form-check:has(> span > small) > .form-check-input[type="radio"] { margin-top: calc((var(--line-height-body) * 1rem - 1.25rem) / 2); }
.form-check > span > strong,
.form-check > span > small { display: block; }
.form-check > span > small { margin-top: var(--space-1); color: var(--color-text-secondary); font-size: var(--font-size-xs); }
.form-check:has(> input:disabled) > span { opacity: .55; }

/* Progress and checklist */
.progress {
    display: block;
    width: 100%;
    height: .5rem;
    overflow: hidden;
    border: 0;
    border-radius: var(--radius-pill);
    background: var(--color-border);
    color: var(--color-brand);
}
.progress::-webkit-progress-bar { background: var(--color-border); }
.progress::-webkit-progress-value { background: var(--color-brand); border-radius: inherit; }
.progress::-moz-progress-bar { background: var(--color-brand); border-radius: inherit; }

/* Tables and dialogs */
.table { width: 100%; border-collapse: collapse; font-size: var(--font-size-sm); }
.table th,
.table td { padding: var(--space-3) var(--space-4); border-bottom: var(--border-width) solid var(--color-border); text-align: left; vertical-align: top; }
.table th { color: var(--color-text-secondary); font-weight: var(--font-weight-semibold); }
/* 공통 모달(x-ui.modal, 공유 창 기준). 열고 닫기·애니메이션·닫을 때 폼 초기화는 app.js DiveoryDialog.
   size: --sm(로그인·참가처럼 입력 몇 개) · --lg(넓게). variant: --tall(높이 고정, .modal__scroll만 스크롤). */
.modal {
    --dialog-width: var(--dialog-width-md);
    z-index: var(--z-modal);
    width: min(var(--dialog-width), calc(100% - var(--gutter) - var(--gutter)));
    max-height: calc(100dvh - var(--gutter) - var(--gutter));
    overflow: hidden;
    overscroll-behavior: contain;
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-card);
    background: var(--color-surface);
    padding: 0;
    box-shadow: var(--shadow-md);
}
dialog.modal { position: fixed; inset: 0; margin: auto; }
.modal--sm { --dialog-width: var(--dialog-width-sm); }
.modal--lg { --dialog-width: var(--dialog-width-lg); }
.modal[open] {
    display: grid;
    /* 열을 모달 폭에 묶어 줄바꿈 없는 긴 제목이 닫기 버튼을 밖으로 밀지 않게 한다. */
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr);
    animation: modal-enter var(--duration-slow) var(--ease-standard) both;
}
.modal[data-closing] { animation: modal-exit var(--duration-base) var(--ease-standard) both; }
.modal::backdrop { background: var(--color-overlay); animation: modal-backdrop-enter var(--duration-slow) var(--ease-standard) both; }
.modal--blur::backdrop { -webkit-backdrop-filter: var(--header-glass-blur); backdrop-filter: var(--header-glass-blur); }
.modal[data-closing]::backdrop { animation: modal-backdrop-exit var(--duration-base) var(--ease-standard) both; }
.modal__header {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    border-bottom: var(--border-width) solid var(--color-brand-light);
    background: linear-gradient(135deg, var(--color-depth-surface), var(--color-surface));
    padding: var(--space-6);
}
.modal__mark {
    display: inline-flex;
    width: var(--control-height-sm);
    height: var(--control-height-sm);
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-pill);
    background: var(--color-brand);
    color: var(--color-surface);
}
.modal__heading { min-width: 0; flex: 1 1 auto; }
.modal__eyebrow { margin-bottom: var(--space-1); color: var(--color-brand); font-size: var(--font-size-xs); font-weight: var(--font-weight-semibold); letter-spacing: var(--letter-spacing-wide); }
.modal__heading h2 { font-size: var(--font-size-xl); line-height: var(--line-height-tight); }
/* 부제목은 말줄임 없이 어절 단위로 줄을 바꿔 끝까지 보인다. 한 줄보다 긴 링크·제목만 칸 안에서 끊는다. */
.modal__subtitle { margin-top: var(--space-2); color: var(--color-text-secondary); font-size: var(--font-size-sm); line-height: var(--line-height-guide); overflow-wrap: break-word; text-wrap: pretty; }
.modal__subtitle:empty { display: none; }
/* 닫기 버튼은 위아래를 같은 만큼 당겨 머리 높이를 늘리지 않는다(제목만 있을 때 아래 여백이 위보다 커지지 않게). */
.modal__close { flex: 0 0 auto; margin: calc(0rem - var(--space-2)) calc(0rem - var(--space-2)) calc(0rem - var(--space-2)) var(--space-1); }
.modal__body { display: grid; min-height: 0; align-content: start; gap: var(--form-stack-gap); overflow-y: auto; padding: var(--space-6); }
/* 모달 안 폼은 본문 간격(폼 공통 --form-stack-gap)을 그대로 쓴다. */
.modal__body > form { display: contents; }
.modal__body > form[hidden] { display: none; }
:is(.modal__body, .modal__body > form) > :is(.alert, .form-alert) + :not(.alert, .form-alert, .form-field) { margin-top: calc(var(--alert-gap) - var(--form-stack-gap)); }
.modal__notice {
    border-left: var(--border-width-accent) solid var(--color-brand-mid);
    background: var(--color-surface-soft);
    padding: var(--space-3) var(--space-4);
    color: var(--color-text-secondary);
    font-size: var(--font-size-sm);
    line-height: var(--line-height-guide);
}
.modal__actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--space-3); }
.modal__actions[hidden] { display: none; }
/* 높이 고정 모달: 탭·안내는 그대로 두고 목록(.modal__scroll)만 스크롤한다(프리셋 불러오기). */
.modal--tall { height: min(40rem, calc(100dvh - var(--gutter) - var(--gutter))); }
.modal--tall .modal__body { display: flex; flex-direction: column; overflow: hidden; }
.modal--tall .modal__body > * { flex: 0 0 auto; }
.modal--tall .modal__body > .modal__scroll { min-height: 0; flex: 1 1 auto; overflow-y: auto; overscroll-behavior: contain; }

@keyframes modal-enter {
    from { opacity: 0; transform: translateY(var(--space-4)) scale(.975); }
    to { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes modal-exit {
    from { opacity: 1; transform: translateY(0) scale(1); }
    to { opacity: 0; transform: translateY(var(--space-2)) scale(.985); }
}
@keyframes modal-backdrop-enter {
    from { opacity: 0; }
    to { opacity: 1; }
}
@keyframes modal-backdrop-exit {
    from { opacity: 1; }
    to { opacity: 0; }
}
@media (max-width: 39.999rem) {
    .modal__header,
    .modal__body { padding: var(--space-5); }
    /* 좁은 화면에서는 제목 앞 원형 표시를 숨기고 제목을 한 단계 줄인다. */
    .modal__mark { display: none; }
    .modal__heading h2 { font-size: var(--font-size-lg); }
    .modal__actions { flex-wrap: nowrap; }
    .modal__actions > .btn { flex: 1 1 auto; }
}

/* Amount list: title + meta on the left, amount on the right (tour share settlement, tour cost memos). */
.tour-personal-expenses { display: grid; gap: var(--space-2); margin: 0; padding: 0; list-style: none; }
.tour-personal-expenses li { display: flex; min-width: 0; align-items: center; justify-content: space-between; gap: var(--space-3); border-bottom: var(--border-width) solid var(--color-border); padding-block: var(--space-2); font-size: var(--font-size-sm); }
.tour-personal-expenses li > div { min-width: 0; }
.tour-personal-expenses strong,
.tour-personal-expenses small { display: block; }
.tour-personal-expenses small { color: var(--color-text-secondary); font-size: var(--font-size-xs); }
.tour-personal-expenses li > span { flex: 0 0 auto; font-weight: var(--font-weight-semibold); font-variant-numeric: tabular-nums; }

/* 투어 공지 관리(x-tour.announcement-manager, 기본 정보 탭). 공유 링크 공지 상자는 share.css "투어 공지". */
.tour-announcement-manager,
.tour-announcement-manager__form,
.tour-announcement-list { display: grid; min-width: 0; gap: var(--form-stack-gap); }
.tour-announcement { display: grid; min-width: 0; justify-items: start; gap: var(--space-2); }
.tour-announcement-history > summary { width: fit-content; cursor: pointer; font-size: var(--font-size-sm); }
.tour-announcement-history[open] > summary { margin-bottom: var(--space-4); }

/* 아코디언(details) 접힘 애니메이션(app.js): 닫는 동안은 open이 남아 있어, 화면별 [open] 화살표 회전을 먼저 되돌린다. */
details[data-accordion-closing] > summary .icon { transform: none !important; }

/* 로그인 모달(x-auth.login-modal)·로그인 화면·투어 게스트 로그인이 같은 옵션 줄(로그인 유지·이메일 기억·비밀번호 찾기)과 가입 안내 줄을 쓴다.
   로그인 모달은 로그인 화면(__view)과 회원가입 화면이 한 묶음(__views) 안에서 바뀐다. */
.auth-options { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3) var(--space-4); color: var(--color-text-secondary); font-size: var(--font-size-sm); }
.auth-options > .text-link { display: inline-flex; min-height: var(--control-height-sm); align-items: center; }
.auth-switch { margin-top: var(--space-6); border-top: var(--border-width) solid var(--color-border); padding-top: var(--space-5); color: var(--color-text-secondary); font-size: var(--font-size-sm); text-align: center; }
.login-modal__views,
.login-modal__view,
.login-modal__panel,
.login-modal__form { display: grid; gap: var(--form-stack-gap); }
.login-modal__panel > p { color: var(--color-text-secondary); font-size: var(--font-size-sm); }
.login-modal__panel .auth-switch { margin-top: var(--space-2); }

/* 더보기 메뉴(x-ui.item-menu): "···" 버튼 아래로 여는 행동 목록. MY 아이템 행동, 투어 상태 드롭다운, 공유 화면 내 슬레이트가 같이 쓴다. */
.item-menu { position: relative; }
.item-menu > summary { color: var(--color-text-muted); font-size: var(--font-size-lg); letter-spacing: .08em; list-style: none; }
.item-menu > summary::-webkit-details-marker { display: none; }
.item-menu__panel { position: absolute; z-index: var(--z-dropdown); top: calc(100% + var(--space-1)); right: 0; display: grid; width: calc(var(--space-20) + var(--space-20)); max-width: calc(100vw - var(--gutter) - var(--gutter)); gap: var(--space-1); border: var(--border-width) solid var(--color-border); border-radius: var(--radius-lg); background: var(--color-surface); padding: var(--space-2); box-shadow: var(--shadow-md); }
.item-menu__panel:has(.form-action[data-action-state="confirm"]) { width: max-content; min-width: calc(var(--space-20) + var(--space-20)); max-width: min(var(--panel-width-sm), calc(100vw - var(--gutter) - var(--gutter))); }
.item-menu__panel form { display: grid; }
.item-menu__item.btn { width: 100%; justify-content: flex-start; border-color: transparent; text-align: left; }
@media (hover: hover) {
    .item-menu > summary:hover { background: var(--color-brand-soft); color: var(--color-brand); }
}

/* Tab switch: one row of equal tabs that swaps the panel below (dialogs, tour share access). */
.tab-switch { display: grid; grid-auto-columns: minmax(max-content, 1fr); grid-auto-flow: column; border-bottom: var(--border-width) solid var(--color-border); }
.tab-switch > button { display: inline-flex; min-height: var(--control-height); align-items: center; justify-content: center; gap: var(--space-2); white-space: nowrap; border-bottom: var(--border-width-accent) solid transparent; padding: var(--space-3); color: var(--color-text-secondary); font-size: var(--font-size-sm); font-weight: var(--font-weight-semibold); transition: color var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard); }
@media (hover: hover) {
    .tab-switch > button[aria-selected="false"]:hover { color: var(--color-text); }
}
.tab-switch > button[aria-selected="true"] { border-bottom-color: var(--color-brand); color: var(--color-brand); }
/* Count after the tab name: a plain light number, not a badge, so the tab stays one calm line. */
.tab-switch__count { color: var(--color-text-muted); font-family: var(--font-gauge); font-size: 1.125em; font-weight: var(--font-weight-semibold); font-variant-numeric: tabular-nums; }
.tab-switch > button[aria-selected="true"] .tab-switch__count { color: var(--color-brand-mid); }

/* Pagination (x-ui.pagination): 이전 · 현재/전체 · 다음. 모든 폭에서 같은 모양이다. */
.pagination { display: flex; width: 100%; align-items: center; justify-content: center; gap: var(--space-2); margin-top: var(--space-8); }
.pagination__button { display: inline-flex; min-height: var(--control-height-sm); align-items: center; justify-content: center; border: var(--border-width) solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface); padding: var(--space-2) var(--space-4); color: var(--color-text-secondary); font-size: var(--font-size-sm); font-weight: var(--font-weight-medium); text-decoration: none; }
.pagination__button.is-disabled { cursor: not-allowed; color: var(--color-text-muted); }
.pagination__status { min-width: 4rem; color: var(--color-text-secondary); font-family: var(--font-gauge); font-size: var(--font-size-base); text-align: center; }

/* Accessibility and state */
.visually-hidden {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip-path: inset(50%) !important;
    white-space: nowrap !important;
    border: 0 !important;
}

.skip-link {
    position: fixed;
    top: var(--space-3);
    left: var(--space-3);
    z-index: var(--z-skip-link);
    transform: translateY(calc(-100% - var(--space-6)));
    border-radius: var(--radius-md);
    background: var(--color-brand);
    padding: var(--space-3) var(--space-4);
    color: var(--color-surface);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
    text-decoration: none;
}
.skip-link:focus { transform: translateY(0); }

:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
    outline: .1875rem solid var(--color-focus);
    outline-offset: .1875rem;
}

[hidden] { display: none !important; }

@media (min-width: 40rem) {
    .card { padding: var(--space-6); }
    .form-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    /* Tablet keeps --3 at two columns: an odd count of shown fields (a location datalist is not one)
       lets the first field (place, title) take the whole row, so no field is left alone at half width. */
    .form-grid--3 > :first-child:nth-last-child(odd of :not(datalist, template, [hidden])) { grid-column: 1 / -1; }
}

@media (min-width: 64rem) {
    /* Three short fields in one row on desktop; tablets keep the two-column .form-grid, phones one. */
    .form-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .form-grid--3 > :first-child:nth-last-child(odd of :not(datalist, template, [hidden])) { grid-column: auto; }
}

@media (forced-colors: active) {
    .btn,
    .button,
    .card,
    .form-control { border: 1px solid CanvasText; }
}

/* Shared select treatment: native keyboard/mobile semantics, one visual language. */
:where(.form-select, select.form-control, .form-field__input--select) {
    cursor: pointer;
    min-width: 0;
    border-bottom-color: var(--color-border-strong);
    background-color: transparent;
}
:where(.form-select, select.form-control, .form-field__input--select):focus-visible {
    border-bottom-color: var(--color-brand);
    outline: 2px solid transparent;
}
:where(.form-select, select.form-control, .form-field__input--select)[aria-invalid="true"] {
    border-bottom-color: var(--color-danger);
}
:where(.form-select, select.form-control, .form-field__input--select):disabled {
    cursor: not-allowed;
    opacity: .6;
}

/* 맨 위로(x-ui.scroll-top): 한 화면 넘게 내려가면(app.js가 .is-visible) 오른쪽 아래에 유리 원으로 떠오른다.
   위치는 화면마다 --scroll-top-right·--scroll-top-bottom으로 맞춘다(공유 화면은 share.css). 겹치는 푸터 내용에 닿으면
   app.js가 --scroll-top-lift만큼 translate로 밀어 올려 본문과 함께 올라간다. */
.scroll-top {
    position: fixed;
    z-index: var(--z-sticky);
    right: var(--scroll-top-right, var(--space-4));
    bottom: var(--scroll-top-bottom, calc(var(--space-4) + env(safe-area-inset-bottom)));
    display: grid;
    width: var(--control-height);
    height: var(--control-height);
    place-items: center;
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-pill);
    background: var(--header-glass-background);
    color: var(--color-brand);
    box-shadow: var(--shadow-header-scrolled);
    opacity: 0;
    pointer-events: none;
    transform: translateY(.75rem) scale(.85);
    translate: 0 calc(-1 * var(--scroll-top-lift, 0px));
    transition: opacity var(--duration-slow) var(--ease-standard), transform 420ms var(--ease-spring);
    -webkit-backdrop-filter: var(--header-glass-blur);
    backdrop-filter: var(--header-glass-blur);
}
.scroll-top.is-visible { opacity: 1; pointer-events: auto; transform: none; }
@media (hover: hover) {
    .scroll-top:hover { background: var(--color-surface); }
}

