/* Project stylesheet.
   Written once. The generator never rewrites this file, so edit it freely.

   This file loads after tokens.css, utilities.css, common.css and layout.css.
   Do not constrain or pad body here: sections own their backgrounds at full
   viewport width, then put their readable content in a child .inner.

   <section class="sub-section">
       <div class="inner">...</div>
   </section>
*/

/* A harmless baseline for project-owned navigation. The shared header's
   class-based rules remain the stronger, component-specific layer. */
   nav ul {
    display: flex;
    gap: var(--space-md);
    padding: 0;
    list-style: none;
}

a {
    color: var(--color-primary);
}

/* ============================================================================
   손가락이 닿을 자리 넓히기

   아이콘만 있는 버튼은 보이는 크기가 24px이라 손가락으로 누르기엔 좁다.
   그렇다고 패딩을 주면 옆 요소가 밀려 시안이 어긋난다. 그래서 눈에 안 보이는
   조각을 버튼 가운데에 겹쳐 깔아 누를 자리만 44px로 넓힌다. 이 조각은
   버튼의 일부라 여기를 눌러도 버튼이 눌린다. 자리는 차지하지 않는다.
   ========================================================================= */
.app-subheader__back,
.detail-favorite,
.collection-row__heart {
    position: relative;
}

.app-subheader__back::after,
.detail-favorite::after,
.collection-row__heart::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: var(--size-tap-min);
    height: var(--size-tap-min);
    transform: translate(-50%, -50%);
}

/* ============================================================================
   광고 자리 폭

   가로는 꽉 채우되 PC처럼 넓은 화면에서는 콘텐츠와 같은 폭에서 멈춘다.
   .inner 로 감싸면 좌우 패딩만큼 줄어들어 휴대폰에서 화면 끝까지 못 가므로,
   패딩 없이 최대 폭만 걸고 가운데 세운다. layout.css 가 준 세로 여백
   (margin: var(--space-lg) 0)은 그대로 두고 좌우만 auto 로 덮는다.
   ========================================================================= */
.ad-slot {
    max-width: var(--inner-max-width);
    margin-left: auto;
    margin-right: auto;
}

/* ============================================================================
   컨테이너 폭에서 멈추는 가로줄

   띠(배경)는 화면 끝까지 가도 줄은 콘텐츠와 같은 폭에서 끝나야 한다. PC처럼
   넓은 화면에서 줄만 좌우로 길게 삐져나가면 화면이 두 폭으로 읽힌다.

   줄을 긋던 요소들은 띠 전체 폭이라 border로는 이 일을 할 수 없다. 그래서
   border를 걷고, 콘텐츠 폭(= .inner와 같은 값)으로 가운데 선 1px 조각을
   아래에 깐다. 띠의 배경색은 그대로 끝까지 간다.
   ========================================================================= */
.site-header,
.app-subheader,
.search-controls,
.search-row,
.collection-count,
.collection-row {
    position: relative;
    border-bottom: 0;
}

.site-header::after,
.app-subheader::after,
.search-controls::after,
.search-row::after,
.collection-count::after,
.collection-row::after {
    content: "";
    position: absolute;
    right: 0;
    bottom: 0;
    left: 0;
    width: 100%;
    max-width: var(--inner-max-width);
    height: var(--size-hairline);
    margin: 0 auto;
    background-color: var(--color-line);
}

/* ============================================================================
   splash (index.php) — 진입 화면
   시안: 흰 배경 가운데 628px 주황 radial glow, 그 위에 164px 폭 두 줄 로고.
   shell(public/index.php)이 주는 #splash-entry 안에서만 동작하도록 묶는다.
   ========================================================================= */

#splash-entry {
    /* 시안의 Ellipse 2(628px)와 Frame 87(164px)을 393px 프레임 기준 비율로
       유지하고, 큰 화면에서는 시안 값에서 멈춘다. */
    --page-glow-size: min(62.8rem, 160vw);
    --page-logo-width: min(41.73vw, 16.4rem);

    flex-direction: column;
    background-color: var(--color-bg);
}

#splash-entry #splash-stage {
    display: flex;
    flex: 1 1 auto;
    align-items: center;
    justify-content: center;
    width: 100%;
    padding: 0;
    background-image: radial-gradient(circle closest-side,
        rgba(255, 109, 0, 0.2) 0%, rgba(255, 109, 0, 0) 100%);
    background-repeat: no-repeat;
    background-position: center center;
    background-size: var(--page-glow-size) var(--page-glow-size);
}

#splash-entry #splash-stage .inner {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    max-width: var(--inner-max-width);
    padding: 0;
    margin: 0 auto;
}

/* 로고만 들어가는 제목이라 글자 상자를 0으로 접어 이미지 높이만 남긴다. */
#splash-entry .splash-logo {
    margin: 0;
    font-size: 0;
    line-height: 0;
}

#splash-entry .splash-logo img {
    display: block;
    width: var(--page-logo-width);
    height: auto;
    filter: drop-shadow(0 4px 4px rgba(0, 0, 0, 0.25));
}

/* 스크립트가 꺼진 브라우저에서만 보이는 이동 링크.
   display는 건드리지 않는다. noscript에 display를 쓰면 스크립트가 켜진
   브라우저에서도 내용이 드러난다. */
#splash-entry noscript {
    padding: 0 var(--padding-md) var(--padding-lg);
    text-align: center;
}

#splash-entry noscript a {
    font-family: var(--font-ui);
    font-size: var(--fs-label);
    font-weight: var(--fw-bold);
    color: var(--color-primary);
}

/* ============================================================================
   home (home.php)
   시안 393x852 기준. 치수는 tokens.css 램프를 그대로 쓰므로 393px에서는
   시안보다 조금 좁고 760px에서 시안 값에 닿는다. 이 프로젝트의 공통 규칙이다.
   ========================================================================= */

/* 아래 탭바는 네이티브가 그린다. 웹에서 자리를 비워 두지 않는다.
   padding-top: 0 은 남긴다 — layout.css 의 .wrap 기본 위 패딩을 끄는 쪽이라,
   지우면 각 화면 첫 섹션이 들고 있는 위 여백과 겹쳐 두 겹이 된다.
   아래는 safe-bottom 만 남긴다. 아이폰 홈 인디케이터가 덮는 자리고,
   눈에 보이는 아래 여백은 각 화면 마지막 섹션이 이미 들고 있다
   (home-band--tail, detail-section--tail, search-results, collection-results). */
#home-wrap,
#certdetail-wrap,
#search-wrap,
#favorite-wrap,
#recent-wrap {
    padding-top: 0;
    padding-bottom: var(--safe-bottom);
}

/* 목록이 비었을 때 안내가 남은 영역의 한가운데에 서도록, 결과 영역이 높이를
   다 차지하게 한다. body(100vh) → main → 결과 영역 순으로 늘어난다. */
#search-wrap,
#favorite-wrap,
#recent-wrap {
    display: flex;
    flex-direction: column;
}

.search-results,
.collection-results {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
}

/* 헤더 로고. 시안은 27px Cafe24에 그림자 한 겹.
   그림자는 시안의 0.5px가 아니라 1px로 둔다. Figma는 벡터라 0.5px가
   깔끔하게 찍히지만 브라우저는 반픽셀을 그릴 수 없어 글자 테두리 전체에
   갈색 헤일로를 뿌리고, 그게 Cafe24 같은 둥근 글꼴에서 번지거나 보인다. */
.site-header__logo-text {
    font-size: var(--fs-logo);
    font-weight: var(--fw-bold);
    letter-spacing: var(--ls-tight);
    text-shadow: 1px 1px 0 var(--color-logo-shadow);
}

/* 로고는 글자 대신 에셋을 쓴다(theme.header.logoImage). 시안 로고 폭 102px.
   글자로 두면 Cafe24가 1배 해상도에서 거칠어지는데 이미지는 그 일이 없다. */
.site-header__logo-icon {
    width: 10.2rem;
    height: auto;
}

/* 링크가 inline-flex면 이미지 아래에 글꼴 디센더 자리가 따라붙어 박스가
   이미지보다 커지고, 그만큼 로고가 위로 치우친다(위 4px / 아래 13px).
   블록 레벨로 바꾸면 박스가 이미지 높이와 같아져 정확히 가운데에 선다. */
.site-header__logo-link {
    display: flex;
}

/* ---- 공통 밴드 ----------------------------------------------------------
   섹션끼리 간격 없이 배경색만 바뀌며 이어진다. */
.home-band {
    width: 100%;
    padding-top: var(--padding-lg);
    padding-bottom: var(--padding-lg);
    background-color: var(--color-bg);
}

.home-band--flush {
    padding-top: 0;
    padding-bottom: 0;
}

.home-band--flush > .inner {
    padding-left: 0;
    padding-right: 0;
}

.home-band--soft {
    background-color: var(--color-bg-soft);
}

.home-band--tail {
    padding-bottom: var(--padding-2xl);
}

.home-heading {
    margin: 0;
    font-family: var(--font-display);
    font-size: var(--fs-section-title);
    font-weight: var(--fw-bold);
    line-height: var(--lh-body);
    letter-spacing: var(--ls-tight);
    color: var(--color-text);
}

/* ---- 캐러셀 공통 --------------------------------------------------------- */
.home-hero,
.home-rail {
    position: relative;
    overflow: hidden;
    /* 세로 스크롤은 페이지에 넘기고 가로 제스처만 가져간다. */
    touch-action: pan-y;
    cursor: grab;
}

.home-hero.is-dragging,
.home-rail.is-dragging {
    cursor: grabbing;
}

/* will-change를 걸지 않는다. 걸어두면 트랙이 늘 별도 합성 레이어로 올라가
   서브픽셀 안티에일리어싱이 꺼지고, 카드 안 글자가 정지 상태에서도 번진다.
   애니메이션 동안의 레이어 승격은 브라우저가 알아서 한다. */
.home-hero__track,
.home-rail__track {
    display: flex;
    transition: transform var(--duration-base) var(--easing-standard);
}

.home-hero.is-dragging .home-hero__track,
.home-rail.is-dragging .home-rail__track {
    transition: none;
}

/* 끌어서 넘기는 중에 브라우저 기본 동작이 제스처를 가로채지 못하게 한다.
   이미지는 기본 드래그, 카드 이름과 태그는 텍스트 선택이 끼어든다. */
.home-hero,
.home-rail {
    -webkit-user-select: none;
    user-select: none;
}

.home-hero__image,
.home-card__thumb {
    -webkit-user-drag: none;
}

/* ---- 히어로 배너 --------------------------------------------------------- */
.home-hero__slide {
    flex: 0 0 100%;
    width: 100%;
}

/* 배너 전체가 분야 검색으로 가는 링크다. 끌어 넘기는 동작을 가리지 않게
   블록으로만 깔아 둔다. */
.home-hero__link {
    display: block;
}

.home-hero__image {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 393 / 200;
    object-fit: cover;
}

.home-hero__arrow {
    position: absolute;
    top: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    padding: 0;
    color: var(--color-text-invert);
    background-color: var(--color-overlay-dark);
    border: 0;
    border-radius: var(--radius-pill);
    transform: translateY(-50%);
    cursor: pointer;
}

.home-hero__arrow svg {
    width: auto;
    height: 1.2rem;
}

.home-hero__arrow--prev { left: var(--space-4); }
.home-hero__arrow--next { right: var(--space-4); }

.home-hero__counter {
    position: absolute;
    bottom: 1rem;
    left: 1rem;
    margin: 0;
    padding: var(--space-2) var(--space-md);
    font-family: var(--font-base);
    font-size: var(--fs-caption);
    font-weight: var(--fw-regular);
    line-height: var(--lh-body);
    color: var(--color-text-mute);
    background-color: var(--color-overlay-light);
    border-radius: var(--radius-md);
}

.home-hero__counter-slash {
    padding: 0 0.15em;
}

/* ---- 인기 자격증 --------------------------------------------------------- */
.home-popular__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-md);
    margin-bottom: var(--space-md);
}

.home-popular__asof {
    margin: 0;
    font-family: var(--font-base);
    font-size: var(--fs-body);
    font-weight: var(--fw-regular);
    line-height: var(--lh-body);
    color: var(--color-text-mute);
    white-space: nowrap;
}

.home-popular__list {
    display: grid;
    gap: var(--space-xs);
    margin: 0;
    padding: 0;
    list-style: none;
}

.home-popular__row {
    border-bottom: var(--size-hairline) solid var(--color-line);
}

/* 행 전체가 탭 영역이다. 상세가 없는 항목은 같은 모양의 div로 나온다.
   site.css 맨 위의 a 규칙이 글자를 주황으로 바꾸지 않도록 색을 되돌린다. */
.home-popular__link {
    display: flex;
    align-items: center;
    gap: var(--space-xs);
    min-height: 4rem;
    color: inherit;
    text-decoration: none;
}

/* 글자 상자는 정가운데인데 숫자가 2px쯤 위로 떠 보인다. Cafe24 서체가 아래에
   큰 디센더 공간을 잡아 두어, 상자를 가운데 맞추면 획은 그만큼 위로 올라간다.
   위쪽에만 패딩을 주면 가운데 맞춤 기준선이 패딩의 절반만큼 내려와 획이
   사각형 한가운데에 선다(0.2em → 약 2px). 사각형 크기는 그대로다. */
.home-popular__rank {
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 4rem;
    height: 4rem;
    padding-top: 0.2em;
    font-family: var(--font-display);
    font-size: var(--fs-section-title);
    font-weight: var(--fw-bold);
    line-height: var(--lh-body);
    letter-spacing: var(--ls-tight);
    color: var(--color-text);
}

.home-popular__rank--1 { background-color: var(--color-primary-accent); }
.home-popular__rank--2 { background-color: var(--color-primary-light); }
.home-popular__rank--3 { background-color: var(--color-primary-muted); }

.home-popular__name {
    flex: 1 1 auto;
    min-width: 0;
    font-family: var(--font-base);
    font-size: var(--fs-label);
    font-weight: var(--fw-bold);
    line-height: var(--lh-body);
    color: var(--color-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.home-popular__move {
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    gap: var(--space-4);
    padding: var(--space-xs) var(--space-sm);
    font-family: var(--font-ui);
    font-size: var(--fs-body);
    font-weight: var(--fw-bold);
    line-height: var(--lh-body);
    letter-spacing: var(--ls-tight);
}

.home-popular__move--same { color: var(--color-text); }
.home-popular__move--up { color: var(--color-danger); }
.home-popular__move--down { color: var(--color-success); }

/* 어제까지 조회가 없다가 올라온 것. 화살표가 없는 자리라 글자만으로는
   가벼워 보여서, 상승과 같은 계열 색에 옅은 바탕을 깔아 배지로 세운다.
   숫자보다 폭이 넓으므로 글자 크기를 한 단 낮춰 줄 높이를 지킨다. */
.home-popular__move--new {
    color: var(--color-primary);
    border-radius: var(--radius-xs);
    font-size: var(--fs-label);
    letter-spacing: 0;
}

.home-popular__arrow {
    width: var(--size-icon-md);
    height: var(--size-icon-md);
}

/* ---- 추천 자격증 레일 ----------------------------------------------------
   오른쪽만 섹션 가장자리까지 늘려 다음 카드가 비어져 나가 보이게 한다.
   왼쪽을 같이 늘리면 왼편 카드(복제본)의 그림자가 여백에 묻어나므로, 왼쪽은
   읽기 여백 자리에서 바로 자른다. 시안에도 왼쪽엔 아무것도 걸치지 않는다.

   세로로는 클립 상자를 조금 넓혀 카드 그림자가 잘리지 않게 하고, 넓힌 만큼
   음수 마진으로 당겨 자리는 그대로 둔다. (그림자가 1px 내려가고 blur 5라
   아래로 약 3.5px 번진다.) */
.home-rail {
    --page-rail-bleed: 0.8rem;

    margin-top: calc(var(--space-md) - var(--page-rail-bleed));
    margin-bottom: calc(-1 * var(--page-rail-bleed));
    margin-right: calc(-1 * (var(--inner-padding-x) + var(--safe-right)));
    padding-top: var(--page-rail-bleed);
    padding-bottom: var(--page-rail-bleed);
    padding-right: calc(var(--inner-padding-x) + var(--safe-right));
}

/* 간격을 유동 토큰(393px에서 8.27px)으로 두면 카드가 소수점 x좌표에 앜는다.
   카드 폭 18.2rem과 같은 정수 값으로 묶어 한 칸 이동량을 198px 정수로 만든다.
   시안 Figma 값도 16px라 정확도가 오히려 올라간다. */
.home-rail__track {
    gap: 1.6rem;
}

/* 카드 전체가 상세로 가는 링크다. site.css 맨 위의 a 규칙이 글자를
   주황으로 바꾸지 않도록 색을 되돌린다. */
.home-card {
    display: flex;
    color: inherit;
    text-decoration: none;
    flex: 0 0 18.2rem;
    flex-direction: column;
    align-items: center;
    gap: var(--space-sm);
    width: 18.2rem;
    padding: var(--padding-md);
    background-color: var(--color-bg-card);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
}

.home-card__thumb {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 3 / 2;
    object-fit: cover;
    border-radius: var(--radius-xs);
}

.home-card__name {
    margin: 0;
    font-family: var(--font-base);
    font-size: var(--fs-label);
    font-weight: var(--fw-bold);
    line-height: var(--lh-body);
    text-align: center;
    color: var(--color-text);
}

.home-card__tags {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--space-4);
    margin: 0;
}

.home-tag {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 2rem;
    padding: 0 var(--space-md);
    font-family: var(--font-base);
    font-size: var(--fs-caption);
    font-weight: var(--fw-extrabold);
    line-height: var(--lh-body);
    color: var(--color-primary-accent);
    background-color: var(--color-bg-soft);
    border: var(--size-hairline) solid var(--color-primary-accent);
    border-radius: var(--radius-pill);
    white-space: nowrap;
}

/* ---- 기간별 맞춤 자격증 --------------------------------------------------- */
.home-periods__head {
    display: grid;
    gap: var(--space-4);
    margin-bottom: var(--space-lg);
}

.home-periods__note {
    margin: 0;
    font-family: var(--font-base);
    font-size: var(--fs-body);
    font-weight: var(--fw-regular);
    line-height: var(--lh-body);
    color: var(--color-text-mute);
}

.home-periods__list {
    display: flex;
    align-items: stretch;
    gap: var(--space-lg);
    margin: 0;
    padding: 0;
    list-style: none;
}

/* 카드 하나하나가 그 교육기간으로 걸린 검색 화면으로 가는 링크다.
   li가 자리를 나눠 갖고 그 안의 <a>가 자리를 다 채운다. */
.home-periods__item {
    display: flex;
    flex: 1 1 0;
    min-width: 0;
}

/* 시안의 카드는 폭과 높이가 거의 같다. 폭은 셋으로 나눠 가지므로 높이를
   폭에 맞춰 정사각형으로 두되, 좁은 화면에서 글자가 넘치지 않게 최소 높이를,
   넓은 화면에서 지나치게 커지지 않게 최대 높이를 둔다. */
.home-period {
    display: flex;
    flex: 1 1 auto;
    color: inherit;
    text-decoration: none;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-width: 0;
    aspect-ratio: 1;
    min-height: 10rem;
    max-height: 16rem;
    padding: var(--padding-md);
    border-radius: var(--radius-md);
}

/* 기간이 길수록 색이 진해지고 카드도 조금 높아진다. */
.home-period--4w { gap: var(--space-xs); background-color: var(--color-period-4w); }
.home-period--5w { gap: var(--space-sm); background-color: var(--color-period-5w); }
.home-period--6w { gap: var(--space-sm); background-color: var(--color-period-6w); }

.home-period__badge {
    /* 시안은 42px이지만 작아 보여 키웠다. 카드 폭을 따라가되 양끝에서 멈춘다. */
    --page-period-badge: clamp(4.4rem, 14vw, 5.6rem);

    display: flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: var(--page-period-badge);
    height: var(--page-period-badge);
    background-color: var(--color-bg);
    border-radius: var(--radius-pill);
}

.home-period__badge img {
    display: block;
    width: 90%;
    height: auto;
}

.home-period__label {
    font-family: var(--font-base);
    font-size: var(--fs-label);
    font-weight: var(--fw-bold);
    line-height: var(--lh-body);
    text-align: center;
    color: var(--color-text);
    white-space: nowrap;
}

/* ============================================================================
   certdetail (certificate.php) — 자격증 상세
   시안의 상단바는 뒤로가기 하나뿐이라 headerType을 custom으로 두고
   App_CustomHeader에서 그린다. .custom-header는 템플릿이 주는 바깥 띠다.
   ========================================================================= */

.app-subheader {
    padding-top: var(--safe-top);
}

.app-subheader > .inner {
    display: flex;
    align-items: center;
    min-height: var(--header-height);
}

.app-subheader__back {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--size-icon-md);
    height: var(--size-icon-md);
    margin-left: calc(-1 * var(--space-xs));
    text-decoration: none;
}

.app-subheader__back img {
    display: block;
    width: 100%;
    height: auto;
}

/* ---- 배너 + 이름 + 한 줄 소개 ---------------------------------------------- */
.detail-hero {
    width: 100%;
    padding-top: var(--padding-lg);
    padding-bottom: var(--padding-lg);
    background-color: var(--color-bg-soft);
}

.detail-hero > .inner {
    display: grid;
    gap: var(--space-lg);
}

.detail-hero__banner {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 786 / 400;
    object-fit: cover;
    border-radius: var(--radius-md);
}

.detail-hero__body {
    display: grid;
    gap: var(--space-xs);
}

.detail-hero__head {
    display: flex;
    align-items: center;
    gap: var(--space-xs);
}

/* 시안은 18px이지만 Cafe24는 1배 해상도에서 20px 아래가 뭉개진다.
   섹션 제목(--fs-section-title)보다 한 단 위를 유지하면서 그 선을 넘긴다. */
.detail-hero__name {
    flex: 1 1 auto;
    min-width: 0;
    margin: 0;
    font-family: var(--font-display);
    font-size: clamp(22px, calc(21.0196px + 0.3922vw), 24px);
    font-weight: var(--fw-bold);
    line-height: var(--lh-body);
    letter-spacing: var(--ls-tight);
    color: var(--color-text);
}

.detail-favorite {
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: var(--size-icon-md);
    height: var(--size-icon-md);
    padding: 0;
    background: none;
    border: 0;
    cursor: pointer;
}

.detail-favorite img {
    width: 100%;
    height: auto;
}

/* 눌림 상태는 aria-pressed 하나로 끝낸다. 보이는 하트와 보조 기술이 읽는
   상태가 갈라지지 않는다. 선택자 무게를 위 img 규칙보다 무겁게 둬야
   display가 밀리지 않는다. */
.detail-favorite .detail-favorite__off { display: block; }
.detail-favorite .detail-favorite__on { display: none; }
.detail-favorite[aria-pressed="true"] .detail-favorite__off { display: none; }
.detail-favorite[aria-pressed="true"] .detail-favorite__on { display: block; }

.detail-hero__summary {
    margin: 0;
    font-family: var(--font-base);
    font-size: var(--fs-label);
    font-weight: var(--fw-bold);
    line-height: var(--lh-body);
    color: var(--color-text-sub);
}

/* ---- 본문 섹션 ------------------------------------------------------------ */
.detail-section {
    width: 100%;
    padding-top: var(--padding-lg);
    padding-bottom: var(--padding-lg);
    background-color: var(--color-bg);
}

.detail-section--tail {
    padding-bottom: var(--padding-2xl);
}

.detail-section > .inner {
    display: grid;
    gap: var(--space-md);
}

.detail-section__title {
    display: flex;
    align-items: center;
    gap: var(--space-xs);
    margin: 0;
    font-family: var(--font-display);
    font-size: var(--fs-section-title);
    font-weight: var(--fw-bold);
    line-height: var(--lh-body);
    letter-spacing: var(--ls-tight);
    color: var(--color-text);
}

/* 박스는 정확히 가운데 정렬돼 있지만, Cafe24는 디센더가 커서 글자 잉크가
   줄 상자 중심보다 위에 찍힌다(20.5px 기준 약 2.9px). 그래서 아이콘만 처져
   보인다. 글자 크기에 따라 같이 움직이도록 em으로 끌어올린다. */
.detail-section__icon {
    display: block;
    flex: 0 0 auto;
    width: var(--size-icon-sm);
    height: var(--size-icon-sm);
    transform: translateY(-0.12em);
}

.detail-list {
    display: grid;
    gap: var(--space-xs);
    margin: 0;
    padding: 0;
    list-style: none;
}

/* 가운뎃점은 글머리라 내용이 아니다. 둘째 줄부터는 글자가 점 아래로
   흘러내리지 않도록 flex로 매달아 둔다. */
.detail-list li {
    display: flex;
    gap: var(--space-4);
    font-family: var(--font-base);
    font-size: var(--fs-label);
    font-weight: var(--fw-regular);
    line-height: var(--lh-body);
    color: var(--color-text);
}

.detail-list li::before {
    content: "·";
    flex: 0 0 auto;
}

/* ---- 신청 버튼 ------------------------------------------------------------ */
.detail-apply {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-4);
    margin-top: var(--space-lg);
    min-height: 5.9rem;
    padding: var(--padding-md);
    font-family: var(--font-display);
    font-size: var(--fs-section-title);
    font-weight: var(--fw-bold);
    line-height: var(--lh-body);
    letter-spacing: var(--ls-tight);
    color: var(--color-text-invert);
    text-decoration: none;
    background-color: var(--color-primary);
    border-radius: var(--radius-md);
}

.detail-apply svg {
    flex: 0 0 auto;
}

/* 신청 링크를 아직 받지 못한 자격증은 같은 자리에 눌리지 않는 버튼을 둔다.
   데이터의 applyUrl이 채워지면 자동으로 링크로 바뀐다. */
.detail-apply.is-pending {
    width: 100%;
    color: var(--color-text-disabled);
    background-color: var(--color-bg-disabled);
    border: 0;
    cursor: not-allowed;
}

/* ============================================================================
   search (search.php) — 자격증 검색
   드롭다운은 네이티브 select가 아니라 커스텀이다. 닫힌 모습만 시안이 있어
   열린 목록은 닫힌 버튼의 테두리·색·글자를 그대로 이어 받아 그렸다.
   ========================================================================= */

/* ---- 검색어 + 거르기 ------------------------------------------------------ */
.search-controls {
    width: 100%;
    padding-top: var(--padding-lg);
    padding-bottom: var(--padding-lg);
    background-color: var(--color-bg);
}

/* 칸을 minmax(0, 1fr)로 둬야 한다. grid의 기본 칸(auto)은 안쪽 내용의
   min-content보다 좁아지지 않아서, 아주 좁은 화면(글자를 200%로 키운 경우
   등)에서 검색창·거르기 줄이 화면을 밀어낸다. */
.search-controls > .inner {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-md);
}

.search-field {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    min-height: 4rem;
    padding: var(--space-md);
    background-color: var(--color-bg-mute);
    border-radius: var(--radius-md);
}

/* common.css가 input[type="search"]에 흰 배경·테두리·패딩·둥근 모서리를 준다.
   그 선택자가 클래스 하나보다 무거워서, 여기서는 클래스를 둘 겹쳐 되돌린다.
   검색창의 테두리와 배경은 바깥 .search-field가 맡는다. */
.search-field .search-field__input {
    flex: 1 1 auto;
    width: auto;
    min-width: 0;
    padding: 0;
    font-family: var(--font-base);
    font-size: var(--fs-label);
    font-weight: var(--fw-bold);
    line-height: var(--lh-body);
    color: var(--color-text);
    background: none;
    border: 0;
    border-radius: 0;
    outline: none;
}

.search-field .search-field__input::placeholder {
    color: var(--color-text-mute);
}

/* 검색창 자체가 거르기라 브라우저 기본 지우기 버튼은 쓰지 않는다. */
.search-field .search-field__input::-webkit-search-cancel-button {
    -webkit-appearance: none;
}

.search-field__icon {
    display: block;
    flex: 0 0 auto;
    width: var(--size-icon-md);
    height: var(--size-icon-md);
}

/* ---- 커스텀 드롭다운 ------------------------------------------------------ */
/* min-width: 0이 꼭 있어야 한다. 이 줄은 위 grid의 칸이라 기본값이
   min-width: auto(= 안쪽 내용만큼)인데, 분야를 여럿 고르면 닫힌 칸의 글자가
   길어져 그 최소폭이 화면보다 커지고 페이지가 가로로 밀린다. 0으로 두면
   칸은 화면에 맞고 넘치는 글자는 말줄임표가 맡는다. */
.search-filters {
    display: flex;
    align-items: flex-start;
    gap: var(--space-lg);
    min-width: 0;
}

.search-dropdown {
    position: relative;
    flex: 1 1 0;
    min-width: 0;
}

.search-dropdown__button {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    width: 100%;
    min-width: 0;
    min-height: 4.2rem;
    padding: var(--space-md) var(--space-lg);
    font-family: var(--font-base);
    font-size: var(--fs-label);
    font-weight: var(--fw-bold);
    line-height: var(--lh-body);
    color: var(--color-text-sub);
    text-align: left;
    background-color: var(--color-bg);
    border: var(--size-hairline) solid var(--color-line);
    border-radius: var(--radius-sm);
    cursor: pointer;
}

.search-dropdown.is-filtered .search-dropdown__button {
    color: var(--color-primary-accent);
    border-color: var(--color-primary-accent);
}

.search-dropdown__value {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.search-dropdown__caret {
    display: block;
    flex: 0 0 auto;
    width: var(--size-icon-md);
    height: var(--size-icon-md);
    transition: transform var(--duration-fast) var(--easing-standard);
}

.search-dropdown.is-open .search-dropdown__caret {
    transform: rotate(180deg);
}

/* 열린 목록(복수선택). 시안에서 패널은 버튼까지 덮는 흰 한 장이다.
   그래서 버튼 위부터 깔고, 버튼 높이만큼 위를 비워 글자가 가리지 않게 한다.
   높이는 글꼴 램프에 따라 달라져 JS가 --page-dropdown-trigger로 넣어 준다. */
.search-dropdown__panel {
    position: absolute;
    top: 0;
    right: 0;
    left: 0;
    z-index: var(--z-overlay);
    display: grid;
    gap: var(--space-2);
    padding: 0.5rem;
    padding-top: calc(var(--page-dropdown-trigger, 4.2rem) + 0.5rem);
    background-color: var(--color-bg);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-card);
}

/* display를 선언하면 UA의 [hidden] { display: none }을 이겨서 닫힌 패널이
   그대로 보인다. 닫힘을 다시 명시해 둔다. */
.search-dropdown__panel[hidden] {
    display: none;
}

/* 열렸을 때 버튼은 패널 위에 떠서 그 첫 줄처럼 보인다. */
.search-dropdown.is-open .search-dropdown__button {
    position: relative;
    z-index: calc(var(--z-overlay) + 1);
    border-color: transparent;
}

/* 아무것도 안 고른 상태가 곧 "전체"다. 시안의 오른쪽 패널처럼 강조한다. */
.search-dropdown.is-open.is-all .search-dropdown__button {
    background-color: var(--color-primary-muted);
    color: var(--color-text);
}

.search-dropdown__options {
    display: grid;
    gap: var(--space-2);
    /* 분야가 여덟이라 8*35 + 사이 2px = 294px. 그만큼은 잘리지 않게 두고
       그보다 길어지면 스크롤한다. */
    max-height: 32rem;
    margin: 0;
    padding: 0;
    overflow-y: auto;
    list-style: none;
}

.search-dropdown__option {
    display: flex;
    align-items: center;
    width: 100%;
    min-height: 3.5rem;
    padding: var(--space-4) var(--space-xs);
    font-family: var(--font-base);
    font-size: var(--fs-label);
    font-weight: var(--fw-bold);
    line-height: var(--lh-body);
    color: var(--color-text);
    text-align: left;
    background: none;
    border: 0;
    cursor: pointer;
}

.search-dropdown__option.is-selected {
    background-color: var(--color-primary-muted);
}

.search-dropdown__confirm {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: 3.5rem;
    padding: var(--space-4) var(--space-xs);
    font-family: var(--font-base);
    font-size: var(--fs-label);
    font-weight: var(--fw-bold);
    line-height: var(--lh-body);
    color: var(--color-text-invert);
    background-color: var(--color-primary);
    border: 0;
    border-radius: var(--radius-xs);
    cursor: pointer;
}

/* ---- 지금 걸린 조건 + 개수 ------------------------------------------------ */
/* 아주 좁은 화면에서는 개수를 아래 줄로 내린다. 한 줄에 억지로 세우면
   "분야 전체"가 글자 단위로 쪼개진다. */
.search-summary {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--space-xs);
    margin: 0;
}

.search-summary__state {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-4);
    min-width: 0;
    font-family: var(--font-base);
    font-size: var(--fs-label);
    font-weight: var(--fw-bold);
    line-height: var(--lh-body);
    color: var(--color-primary-accent);
}

/* 조건 한 덩어리는 통째로 줄을 넘긴다. 좁은 화면에서 "분야 전" / "체"로
   끊기지 않게 한다. */
.search-summary__state > [data-summary-field],
.search-summary__state > [data-summary-period] {
    white-space: nowrap;
}

.search-summary__dot {
    flex: 0 0 auto;
    width: 2px;
    height: 2px;
    background-color: var(--color-primary-accent);
}

/* 조건 전체 초기화. 조건이 하나라도 걸렸을 때만 나타나므로, 아무것도 안 고른
   기본 화면은 시안 그대로다. display를 선언하니 [hidden]도 다시 명시한다. */
.search-summary__reset {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    gap: var(--space-2);
    min-height: 2rem;
    margin-left: var(--space-4);
    padding: 0 var(--space-xs);
    font-family: var(--font-base);
    font-size: var(--fs-body);
    font-weight: var(--fw-bold);
    line-height: var(--lh-body);
    color: var(--color-text-sub);
    background-color: var(--color-bg-mute);
    border: 0;
    border-radius: var(--radius-pill);
    cursor: pointer;
}

.search-summary__reset[hidden] {
    display: none;
}

.search-summary__reset svg {
    width: 1.4rem;
    height: 1.4rem;
}

.search-summary__count {
    flex: 0 0 auto;
    font-family: var(--font-base);
    font-size: var(--fs-body);
    font-weight: var(--fw-bold);
    line-height: var(--lh-body);
    color: var(--color-text-mute);
    white-space: nowrap;
}

/* ---- 분야별 목록 ---------------------------------------------------------- */
.search-results {
    width: 100%;
    padding-bottom: var(--padding-lg);
    background-color: var(--color-bg);
}

.search-group__title {
    margin: 0;
    font-family: var(--font-display);
    font-size: var(--fs-section-title);
    font-weight: var(--fw-bold);
    line-height: var(--lh-body);
    letter-spacing: var(--ls-tight);
    color: var(--color-text);
}

/* 분야 머리글만은 띠 색까지 콘텐츠 폭에서 멈춘다. 줄만 가운데 768px로
   줄이면 끝까지 간 분홍 띠 아래에 선이 토막 나 보인다. */
.search-group__title .inner {
    display: block;
    padding-top: var(--space-xs);
    padding-bottom: var(--space-xs);
    background-color: var(--color-bg-soft);
    border-bottom: var(--size-hairline) solid var(--color-line);
}

.search-group__list {
    margin: 0;
    padding: 0;
    list-style: none;
}

/* 줄은 화면 끝까지 가는 띠고, 내용만 읽기 폭 안에 든다. 상세가 없는
   항목은 같은 모양의 div로 나온다. */
.search-row__link {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    min-height: 4.5rem;
    padding-top: var(--space-xs);
    padding-bottom: var(--space-xs);
    color: inherit;
    text-decoration: none;
}

.search-row__name {
    flex: 1 1 auto;
    min-width: 0;
    font-family: var(--font-base);
    font-size: var(--fs-label);
    font-weight: var(--fw-bold);
    line-height: var(--lh-body);
    color: var(--color-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.search-tag {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    min-height: 2rem;
    padding: 0 var(--space-md);
    font-family: var(--font-base);
    font-size: var(--fs-body);
    font-weight: var(--fw-extrabold);
    line-height: var(--lh-body);
    border: var(--size-hairline) solid currentColor;
    border-radius: var(--radius-pill);
    white-space: nowrap;
}

.search-tag--orange { color: var(--color-tag-orange); background-color: var(--color-tag-orange-soft); }
.search-tag--green  { color: var(--color-tag-green);  background-color: var(--color-tag-green-soft); }
.search-tag--blue   { color: var(--color-tag-blue);   background-color: var(--color-tag-blue-soft); }

/* ---- 비었을 때 ------------------------------------------------------------
   검색 결과 없음 / 찜 없음 / 최근 본 없음이 같은 모양을 쓴다.
   display를 선언하므로 [hidden]도 다시 명시한다. */
.state-empty {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-md);
    padding: var(--padding-2xl) var(--padding-md);
    text-align: center;
}

.state-empty[hidden] {
    display: none;
}

.state-empty__art {
    display: block;
    width: 4.4rem;
    height: auto;
}

.state-empty__text {
    margin: 0;
    font-family: var(--font-base);
    font-size: var(--fs-label);
    font-weight: var(--fw-bold);
    line-height: var(--lh-body);
    color: var(--color-text-sub);
}

/* ============================================================================
   collection — 찜 목록(favorite.php)과 최근 본(recent.php)이 같이 쓰는 목록.
   둘 다 서버가 모르는 값(이 기기의 localStorage)이라, 카탈로그 40개를 모두
   감춰 둔 채 그리고 collection-list.js가 해당하는 것만 꺼낸다.
   ========================================================================= */

.collection-intro {
    width: 100%;
    padding-top: var(--padding-lg);
    padding-bottom: var(--padding-lg);
    background-color: var(--color-bg-soft);
}

.collection-intro > .inner {
    display: grid;
    gap: var(--space-xs);
}

.collection-intro__title {
    margin: 0;
    font-family: var(--font-display);
    font-size: var(--fs-section-title);
    font-weight: var(--fw-bold);
    line-height: var(--lh-body);
    letter-spacing: var(--ls-tight);
    color: var(--color-text);
}

.collection-intro__lead {
    margin: 0;
    font-family: var(--font-base);
    font-size: var(--fs-label);
    font-weight: var(--fw-bold);
    line-height: var(--lh-body);
    color: var(--color-text-sub);
}

.collection-count {
    width: 100%;
    padding-top: var(--space-xs);
    padding-bottom: var(--space-xs);
    background-color: var(--color-bg);
}

.collection-count__text {
    margin: 0;
    font-family: var(--font-base);
    font-size: var(--fs-body);
    font-weight: var(--fw-bold);
    line-height: var(--lh-body);
    text-align: right;
    color: var(--color-text-mute);
}

/* ---- 줄 ------------------------------------------------------------------ */
.collection-results {
    width: 100%;
    padding-bottom: var(--padding-lg);
    background-color: var(--color-bg);
}

/* 최근 본 화면은 최근 순으로 보여야 하는데 줄은 카탈로그 순서로 그려져 있다.
   DOM을 옮기는 대신 flex의 order로 자리만 바꾼다. */
.collection-list {
    display: flex;
    flex-direction: column;
    margin: 0;
    padding: 0;
    list-style: none;
}

/* display를 선언한 요소는 UA의 [hidden] { display: none }을 이긴다.
   줄과 쪽 번호는 JS가 hidden으로 여닫으므로 닫힘을 다시 명시해 둔다. */
.collection-row[hidden],
.collection-pager[hidden] {
    display: none;
}

/* 줄은 화면 끝까지 가는 띠고, 내용만 읽기 폭 안에 든다.
   position은 줄 전체를 누를 수 있게 까는 덮개(.collection-row__name::after)의
   기준이다. */
.collection-row {
    position: relative;
    display: grid;
    gap: var(--space-4);
    padding-top: var(--space-md);
    padding-bottom: var(--space-md);
}

.collection-row__head {
    display: flex;
    align-items: center;
    gap: var(--space-4);
}

/* 하트는 줄 덮개보다 위에 있어야 제 몫의 클릭을 가져간다. */
.collection-row__heart {
    position: relative;
    z-index: 1;
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: var(--size-icon-md);
    height: var(--size-icon-md);
    padding: 0;
    background: none;
    border: 0;
    cursor: pointer;
}

.collection-row__heart img {
    width: 100%;
    height: auto;
}

/* 눌림 상태는 aria-pressed 하나로 끝낸다. 선택자 무게를 위 img 규칙보다
   무겁게 둬야 display가 밀리지 않는다. 상세 화면의 하트와 같은 방식이다. */
.collection-row__heart .collection-row__heart-off { display: block; }
.collection-row__heart .collection-row__heart-on { display: none; }
.collection-row__heart[aria-pressed="true"] .collection-row__heart-off { display: none; }
.collection-row__heart[aria-pressed="true"] .collection-row__heart-on { display: block; }

.collection-row__name {
    flex: 1 1 auto;
    min-width: 0;
    font-family: var(--font-base);
    font-size: var(--fs-label);
    font-weight: var(--fw-bold);
    line-height: var(--lh-body);
    color: var(--color-text);
    text-decoration: none;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* 줄 아무 데나 눌러도 상세로 가도록 링크를 줄 전체에 덮는다. 하트는 위에서
   따로 올라와 있고, 덮개는 기준이 .collection-row라 이름 칸의 overflow에
   잘리지 않는다(이름의 position이 static이라 자르는 상자가 아니다). */
.collection-row__name::after {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
}

.collection-row__name:focus-visible::after {
    outline: var(--size-hairline) solid var(--color-primary);
    outline-offset: calc(-2 * var(--size-hairline));
}

/* .inner를 같이 달고 있으므로 가로 마진은 auto로 둬야 한다. margin: 0으로
   덮으면 layout.css의 .inner { margin: 0 auto }가 지워져서, 읽기 폭보다 넓은
   화면에서 머리줄만 가운데 서고 이 줄은 왼쪽에 박힌다(1100px에서 166px 어긋남). */
.collection-row__summary {
    margin: 0 auto;
    /* 한 줄짜리와 두 줄짜리가 섞여 줄 높이가 들쭉날쭉했다. 두 줄을 바닥으로
       깔아 둘 다 같은 높이로 서고, 세 줄 이상이면 알아서 늘어난다.
       한 줄일 때 위에 붙지 않도록 글을 그 칸 가운데에 세운다. */
    display: grid;
    align-content: center;
    min-height: calc(2em * var(--lh-body));
    font-family: var(--font-base);
    font-size: var(--fs-body);
    font-weight: var(--fw-bold);
    line-height: var(--lh-body);
    color: var(--color-text-sub);
}

/* ---- 쪽 나누기 ------------------------------------------------------------
   규칙과 생김새는 tangtang-map의 .app-pagination을 따랐다(색만 이 앱 것).
   번호는 한 번에 넷까지, 그 너머가 남아 있는 쪽에 …을 붙이고, 양 끝 겹화살표는
   첫/마지막 쪽이 아니라 네 쪽씩 묶음을 넘긴다.
   --------------------------------------------------------------------------- */
.collection-pager {
    display: flex;
    /* 마지막 안전장치. 300px 아래에서는 가장 넓은 경우(화살표 4 + 번호 4 +
       … 2)가 한 줄에 서지 못해, 밖으로 삐져나가는 대신 줄을 바꾼다. */
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: var(--space-xs);
    padding-top: var(--padding-md);
    padding-bottom: var(--padding-md);
}

.collection-pager__edge {
    display: flex;
    align-items: center;
    gap: var(--space-4);
}

.collection-pager__numbers {
    display: flex;
    align-items: center;
    gap: var(--space-xs);
    margin: 0;
    padding: 0;
    list-style: none;
}

/* 시안의 32px 칸. 393px에서 32px에 닿고 그 아래로는 24px까지 내려온다.
   가장 넓은 경우에 칸이 열 개라 32px 고정으로는 작은 화면에 들어가지 않는다. */
.collection-pager__step,
.collection-pager__number {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    min-width: clamp(2.4rem, calc(1.002rem + 5.594vw), 3.2rem);
    height: clamp(2.4rem, calc(1.002rem + 5.594vw), 3.2rem);
    padding: 0;
    background-color: var(--color-bg);
    border: 0;
    border-radius: var(--radius-md);
    cursor: pointer;
}

/* …은 번호 사이의 표시지 누를 자리가 아니다. 32px 칸을 주면 가운데 쪽에서
   줄이 화면을 넘긴다. 점 셋은 글자 바닥선에 붙어 있어 숫자들 가운데보다
   아래로 처지므로, em의 1/4만큼 올려 숫자 가운데에 맞춘다. */
.collection-pager__ellipsis {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    font-family: var(--font-ui);
    font-size: var(--fs-body);
    font-weight: var(--fw-semibold);
    line-height: var(--lh-body);
    color: var(--color-text);
    transform: translateY(-0.25em);
    cursor: default;
}

.collection-pager__step img {
    display: block;
    width: var(--size-icon-md);
    height: var(--size-icon-md);
}

/* 더 갈 데가 없는 방향은 자리는 지키고 흐리게 두어 누를 수 없게 한다.
   common.css의 button:disabled가 (0,1,1)이라 클래스 하나로는 못 이긴다.
   그대로 두면 회색 칸(--color-bg-disabled)이 깔리고 커서도 금지 표시가 된다.
   여기서는 흐리게만 하는 게 시안이라 클래스를 겹쳐 되돌린다. */
.collection-pager .collection-pager__step[disabled],
.collection-pager .collection-pager__step.is-dead {
    color: inherit;
    background-color: var(--color-bg);
    opacity: 0.4;
    cursor: default;
}

.collection-pager__number {
    font-family: var(--font-ui);
    font-size: var(--fs-body);
    font-weight: var(--fw-semibold);
    line-height: var(--lh-body);
    color: var(--color-text);
}

/* 지금 쪽은 갈 곳이 아니라 <span>이다. 색은 이 앱 것 그대로 둔다. */
.collection-pager__number.is-current {
    color: var(--color-primary);
    background-color: var(--color-primary-muted);
    cursor: default;
}

/* ============================================================================
   app-toast — 잠깐 떴다 사라지는 알림 (지금은 찜 토글).
   색·그림자는 시안 값이 토큰에 이미 있어 그대로 쓴다.
   (#EEF4FF / #2D67FF / 0 0 10px rgba(10,63,238,.6) / radius 5px)
   ========================================================================= */
.app-toast {
    position: fixed;
    bottom: calc(var(--safe-bottom) + var(--space-md));
    /* left:50%로 세우면 그 지점부터 오른쪽 끝까지(≈196px)가 쓸 수 있는 폭이
       되어 긴 문구가 두 줄로 깨진다. 좌우를 0으로 열고 margin auto로 가운데
       세운 뒤, 폭은 글에 맞춰(max-content) 잡고 화면 밖으로만 안 나가게 한다. */
    right: 0;
    left: 0;
    z-index: var(--z-toast);
    display: flex;
    align-items: center;
    justify-content: center;
    width: max-content;
    max-width: calc(100% - 2 * var(--padding-lg));
    margin: 0 auto;
    padding: var(--space-lg) var(--space-xl);
    font-family: var(--font-base);
    font-size: var(--fs-label);
    font-weight: var(--fw-bold);
    line-height: var(--lh-body);
    text-align: center;
    color: var(--color-success);
    background-color: var(--color-success-soft);
    border: var(--size-hairline) solid var(--color-success);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-toast);
    /* 알림일 뿐이라 탭을 가로채지 않는다. */
    pointer-events: none;
    /* 사라질 때. 나타날 때는 아래 애니메이션이 맡는다. */
    opacity: 0;
    transform: translateY(0.8rem);
    transition: opacity var(--duration-base) var(--easing-standard),
                transform var(--duration-base) var(--easing-standard);
}

@keyframes app-toast-in {
    from { opacity: 0; transform: translateY(0.8rem) scale(0.98); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}

/* 누를 때마다 toast.js가 이 클래스를 뗐다 붙여 애니메이션을 처음부터
   다시 돌린다. 글자가 같아도 방금 눌렸다는 게 눈에 보여야 하기 때문이다. */
.app-toast.is-visible {
    opacity: 1;
    transform: translateY(0);
    animation: app-toast-in var(--duration-base) var(--easing-standard);
}
