/* ============================================================
   ai-platform.css — 플랫폼 공통 화면 스타일

   KRDS(디지털 정부서비스 UI/UX 가이드라인, 행정안전부 2024.07)를 따른다.
   불러오는 순서는 layout.html 이 정한다:

     krds-tokens.css  →  krds-base.css  →  프로파일(p2/p3)  →  이 파일

   그래서 여기에는 **새 색·새 크기를 만들지 않는다.** 전부 --krds-* 토큰이거나
   프로파일이 내놓는 --krds-ui-*, --krds-gap-* 이다. 값을 직접 적으면 프로파일을
   바꿔도 그 자리만 안 따라와서, 한 화면 안에서 밀도가 어긋난다.

   예외는 아래 :root 에 모은 두 가지뿐이다.
   - 기관 색. KRDS 는 "기관 브랜드 색을 Primary 로 쓰되 10단계 스케일과 WCAG AA
     대비를 갖출 것" 을 허용한다. 그래서 CI 색 두 가지(남색·주황)만 10단계로 깔고
     --krds-primary / --krds-point 에 갈아끼운다.
   - 상태 색의 글자용 짙은 단계(--krds-success-70 · --krds-danger-70). KRDS 의 성공·위험
     색은 연한 바탕 위 글자로 쓰면 4.5:1 에 못 미쳐, 그 자리에만 한 단계 짙은 값을 쓴다.
   그 아래로는 다시 토큰만 쓴다 — 화면 코드에는 hex 가 한 개도 없어야 한다.

   화면 고유 스타일은 각 서비스의 static/css/app.css 에.
   ============================================================ */

:root {
  /* ── 기관 CI (KISTEP) ─────────────────────────────────────
     원본: static/brand/*.gif (workmark). 로고에서 뽑은 원색이다.
       남색 #211D70  흰 바탕 대비 14.2:1
       주황 #F15922  흰 바탕 대비  3.4:1 → 그래픽·테두리 전용.
                     글자에 쓸 때는 --ap-orange-60 (4.8:1) 을 쓴다. */
  --ap-navy:    #211D70;
  --ap-navy-5:  #F4F3F8;  --ap-navy-10: #E4E3EE;  --ap-navy-20: #BFBED6;
  --ap-navy-30: #9B99BE;  --ap-navy-40: #6966A2;  --ap-navy-60: #1D1A63;
  --ap-navy-70: #191654;  --ap-navy-80: #12103E;  --ap-navy-90: #0A0922;

  --ap-orange:    #F15922;
  --ap-orange-5:  #FEF5F2;  --ap-orange-10: #FDE6DE;  --ap-orange-20: #FBCDBD;
  --ap-orange-30: #F8AC91;  --ap-orange-40: #F58359;  --ap-orange-60: #C6491C;
  --ap-orange-70: #9D3A16;  --ap-orange-80: #6C280F;  --ap-orange-90: #3C1609;

  /* KRDS Primary 를 기관 남색으로 갈아끼운다. 이 한 곳만 바꾸면
     단추·링크·초점·선택 표시가 전부 CI 색을 따른다 */
  --krds-primary:    var(--ap-navy);
  --krds-primary-5:  var(--ap-navy-5);   --krds-primary-10: var(--ap-navy-10);
  --krds-primary-20: var(--ap-navy-20);  --krds-primary-30: var(--ap-navy-30);
  --krds-primary-40: var(--ap-navy-40);  --krds-primary-60: var(--ap-navy-60);
  --krds-primary-70: var(--ap-navy-70);  --krds-primary-80: var(--ap-navy-80);
  --krds-primary-90: var(--ap-navy-90);

  /* 강조 한 점 — CI 의 주황 호 */
  --krds-point:    var(--ap-orange);
  --krds-point-5:  var(--ap-orange-5);   --krds-point-10: var(--ap-orange-10);
  --krds-point-20: var(--ap-orange-20);  --krds-point-30: var(--ap-orange-30);
  --krds-point-40: var(--ap-orange-40);  --krds-point-60: var(--ap-orange-60);
  --krds-point-70: var(--ap-orange-70);  --krds-point-80: var(--ap-orange-80);
  --krds-point-90: var(--ap-orange-90);

  /* 기관 아이덴티티 — 위 CI 색에 쓰임새 이름을 붙인 것 */
  --ap-brand:      var(--ap-navy);             /* 머리띠·GNB 바탕 */
  --ap-brand-deep: var(--ap-navy-60);
  --ap-brand-soft: var(--ap-navy-5);
  --ap-accent:     var(--ap-orange);           /* 선택 표시·강조 한 점 */
  --ap-accent-text: var(--ap-orange-60);       /* 주황을 글자에 쓸 때 */

  /* 상태 색의 글자용 짙은 단계 — krds-tokens.css 의 --krds-warning-70 짝.
     원본 성공·위험 색은 연한 바탕(-5) 위 글자 대비가 4:1 남짓이라 배지 글자에 이것을 쓴다 */
  --krds-success-70: #006E19;   /* 성공 글자 — 연한 바탕 5.7:1 · 흰 바탕 6.5:1 */
  --krds-danger-70:  #BD002F;   /* 위험 글자 — 연한 바탕 5.7:1 · 흰 바탕 6.5:1 */

  /* 알약 모양 — KRDS 의 --krds-rd-full 은 100%(원)이라 긴 칩에는 쓸 수 없다 */
  --ap-rd-pill: 9999px;

  /* 셸 치수 */
  --ap-masthead-h: 3.2rem;
  --ap-header-h:   6.4rem;
  --ap-footer-h:   9.6rem;   /* 푸터 어림 높이. 짧은 화면에서도 운영기관 식별자가 첫 화면에 들어오게 */
  --ap-sidebar-w:  24rem;
}

/* ============================================================
   1. 셸 — 머리띠 · 헤더 · 본문 · 푸터
   ============================================================ */

/* 공식 배너. 공공 서비스임을 맨 위에서 한 줄로 밝힌다 */
.ap-masthead {
  background: var(--krds-gray-5);
  border-bottom: 1px solid var(--krds-gray-20);
  font-size: var(--krds-fz-detail-sm);
  color: var(--krds-gray-70);
}
.ap-masthead .inner {
  display: flex; align-items: center; gap: var(--krds-gap-2);
  min-height: var(--ap-masthead-h);
  max-width: var(--krds-content-max); margin-inline: auto;
  padding-inline: var(--krds-gap-5);
}
.ap-masthead .flag {
  width: 1.6rem; height: 1.6rem; flex: none;
  color: var(--ap-brand);
}

/* 헤더 — 흰 바탕. 기관 CI 가 원색 그대로 서고, 색 비율(배경 60)도 지켜진다.
   아래 가는 선 하나로 본문과 나눈다 */
.ap-header {
  position: sticky; top: 0; z-index: 100;
  background: var(--krds-white);
  color: var(--krds-gray-90);
  border-bottom: 1px solid var(--krds-gray-20);
}
/* 고정 헤더가 앵커·초점 이동으로 옮겨 간 자리를 덮지 않게, 문서 스크롤을 헤더 높이만큼 띄워 멈춘다 */
html { scroll-padding-top: calc(var(--ap-header-h) + var(--krds-gap-3)); }
.ap-header .inner {
  display: flex; align-items: center; gap: var(--krds-gap-5);
  min-height: var(--ap-header-h);
  max-width: var(--krds-content-max); margin-inline: auto;
  padding-inline: var(--krds-gap-5);
}
.ap-brand-link {
  display: flex; align-items: center; gap: var(--krds-gap-3);
  flex: none;
  color: var(--ap-brand); text-decoration: none;
  font-size: var(--krds-fz-title-md); font-weight: 700; letter-spacing: -.02em;
}
.ap-brand-link img { height: 3.6rem; width: auto; }
/* 로고가 없을 때만 CI 의 주황 호를 한 점 빌려 기관 자리를 표시한다 */
.ap-brand-link::before {
  content: ""; width: .4rem; height: 2rem; flex: none;
  border-radius: var(--krds-rd-2);
  background: var(--ap-accent);
}
.ap-brand-link:has(img)::before { display: none; }
/* 로고와 서비스 이름 사이의 칸막이 */
.ap-brand-link:has(img) > span:not(.sr-only) {
  padding-left: var(--krds-gap-3);
  border-left: 1px solid var(--krds-gray-30);
  font-size: var(--krds-ui-fz); color: var(--krds-gray-80);
}
.ap-brand-link:hover > span:not(.sr-only) { text-decoration: underline; }

/* ── 헤더 메뉴 감싸개·유틸리티 ── */
/* 주메뉴와 유틸리티를 한 칸에 묶는다. 넓은 화면에서는 지금처럼 한 줄이고,
   좁은 화면에서는 '메뉴' 단추가 이 칸을 세로 목록으로 펼친다(4절) */
.ap-header-menu {
  display: flex; align-items: center; gap: var(--krds-gap-5);
  flex: 1; min-width: 0;
}
/* 서비스가 nav :: utils 로 채우는 유틸리티 링크 자리 */
.ap-utils {
  display: flex; align-items: center; gap: var(--krds-gap-3);
  flex: none;
  font-size: var(--krds-ui-fz-sub);
}
.ap-utils:empty { display: none; }
/* 조각이 공백만 남긴 경우 — :has 를 모르는 브라우저가 위 규칙까지 버리지 않게 따로 둔다 */
.ap-utils:not(:has(*)) { display: none; }
.ap-utils a { color: var(--krds-gray-80); text-decoration: none; }
.ap-utils a:hover { color: var(--ap-brand); text-decoration: underline; }

/* 주메뉴(GNB) */
.ap-gnb { display: flex; align-items: center; gap: var(--krds-gap-1); flex: 1; min-width: 0; }
.ap-gnb a {
  display: inline-flex; align-items: center;
  height: var(--ap-header-h); padding-inline: var(--krds-gap-3);
  color: var(--krds-gray-80); text-decoration: none;
  font-size: var(--krds-ui-fz); font-weight: 700; white-space: nowrap;
  box-shadow: inset 0 -3px 0 transparent;
}
.ap-gnb a:hover { color: var(--ap-brand); box-shadow: inset 0 -3px 0 var(--krds-gray-30); }
/* 지금 보는 메뉴는 색만이 아니라 밑줄로도 알린다 (색상 단독 전달 금지) */
.ap-gnb a[aria-current="page"] {
  color: var(--ap-brand);
  box-shadow: inset 0 -3px 0 var(--ap-accent);
}

/* ── 주메뉴 묶음(2단) ── */
/* 하위 메뉴가 있는 1단 항목은 링크가 아니라 단추다. 누르기·Enter·Space 로 열고
   마우스를 올려서는 열지 않는다(KRDS 메인 메뉴) — 동작은 ai-platform.js */
.ap-gnb-group { position: relative; display: flex; align-items: center; }
.ap-gnb-btn {
  display: inline-flex; align-items: center; gap: var(--krds-gap-1);
  height: var(--ap-header-h); padding-inline: var(--krds-gap-3);
  border: 0; background: transparent; cursor: pointer;
  color: var(--krds-gray-80);
  font-size: var(--krds-ui-fz); font-weight: 700; white-space: nowrap;
  box-shadow: inset 0 -3px 0 transparent;
}
/* 펼침 꺾쇠 — 공식 아이콘의 모양만 빌려 글자색으로 칠한다 */
.ap-gnb-btn::after {
  content: ""; flex: none; width: 1.6rem; height: 1.6rem;
  background-color: currentColor;
  -webkit-mask: url("icons/head_gnb_ico_arr.svg") no-repeat center / contain;
  mask: url("icons/head_gnb_ico_arr.svg") no-repeat center / contain;
  transition: transform var(--krds-ease);
}
.ap-gnb-btn:hover { color: var(--ap-brand); box-shadow: inset 0 -3px 0 var(--krds-gray-30); }
/* 펼친 묶음 — 글자색·밑줄에 꺾쇠 방향까지 바꿔 색만으로 알리지 않는다 */
.ap-gnb-btn[aria-expanded="true"] { color: var(--ap-brand); box-shadow: inset 0 -3px 0 var(--ap-brand); }
.ap-gnb-btn[aria-expanded="true"]::after { transform: rotate(180deg); }
/* 하위에 지금 보는 화면이 있는 묶음 — 1단 링크의 현재 표시와 같은 밑줄 */
.ap-gnb-btn[aria-current]:not([aria-current="false"]) {
  color: var(--ap-brand);
  box-shadow: inset 0 -3px 0 var(--ap-accent);
}
/* 하위 목록 — 묶음 단추 바로 아래에 뜬다. 길면 화면 높이를 넘지 않고 제 안에서
   스크롤한다(KRDS 드롭다운 최대 높이) — 그래서 뷰포트 단위를 쓴다 */
.ap-gnb-sub {
  position: absolute; top: 100%; left: 0; z-index: 1;
  min-width: var(--ap-sidebar-w);
  max-height: calc(100vh - var(--ap-header-h) - var(--ap-masthead-h));
  overflow-y: auto;
  margin: 0; padding: var(--krds-gap-2);
  border: 1px solid var(--krds-gray-20); border-radius: var(--krds-rd-8);
  background: var(--krds-white);
  box-shadow: var(--krds-shadow-md);
}
/* 하위 항목은 1단 링크의 헤더 높이·밑줄을 물려받지 않는다 */
.ap-gnb .ap-gnb-sub a {
  display: block; height: auto;
  padding: var(--krds-gap-2) var(--krds-gap-3);
  border-radius: var(--krds-ui-rd);
  font-weight: 400; white-space: normal;
  box-shadow: none;
}
.ap-gnb .ap-gnb-sub a:hover { background: var(--krds-gray-5); text-decoration: underline; }
/* 지금 보는 화면 — 곁메뉴의 현재 표시와 같다(바탕 + 굵기) */
.ap-gnb .ap-gnb-sub a[aria-current="page"] {
  background: var(--krds-primary-5); color: var(--krds-primary-60); font-weight: 700;
}

/* ── 좁은 화면 메뉴 단추 ── */
/* 넓은 화면에서는 숨는다. 4절이 768px 이하·(곁메뉴가 있으면) 1024px 이하에서 꺼내고,
   펼칠 것이 없으면 hidden 속성이 이긴다 */
.ap-menu-toggle {
  display: none; align-items: center; gap: var(--krds-gap-1);
  flex: none;
  min-height: var(--krds-ui-h); padding-inline: var(--krds-gap-3);
  border: 1px solid var(--krds-gray-30); border-radius: var(--krds-ui-rd);
  background: var(--krds-white); color: var(--krds-gray-80); cursor: pointer;
  font-size: var(--krds-ui-fz-sub); font-weight: 700; white-space: nowrap;
  transition: background-color var(--krds-ease), border-color var(--krds-ease), color var(--krds-ease);
}
.ap-menu-toggle:hover { background: var(--krds-gray-5); }
.ap-menu-toggle[aria-expanded="true"] { color: var(--ap-brand); border-color: var(--ap-brand); }

/* ── 글자색을 따르는 아이콘(mask) ── */
/* 공식 SVG 의 모양만 빌리고 색은 글자색으로 칠한다 — 상태마다 색을 바꾼 파일을 따로 두지 않는다.
   주소는 이 파일 기준 상대 경로라 컨텍스트 경로·폐쇄망과 무관하다 */
.ap-mask-ico {
  display: inline-block; flex: none;
  width: 2rem; height: 2rem;
  background-color: currentColor;
  -webkit-mask: no-repeat center / contain;
  mask: no-repeat center / contain;
}
.ap-mask-ico.menu {
  -webkit-mask-image: url("icons/head_ico_navi_all.svg");
  mask-image: url("icons/head_ico_navi_all.svg");
}
.ap-mask-ico.close {
  -webkit-mask-image: url("icons/ico_close_modal.svg");
  mask-image: url("icons/ico_close_modal.svg");
}
.ap-mask-ico.check {
  -webkit-mask-image: url("icons/ico_check_chip.svg");
  mask-image: url("icons/ico_check_chip.svg");
}
.ap-mask-ico.chip-del {
  -webkit-mask-image: url("icons/ico_chip_del.svg");
  mask-image: url("icons/ico_chip_del.svg");
}
/* 올림·지우기는 KRDS 원본(lib/krds)을 빌린다 — 흰색으로 박힌 파일이라도 mask 는 모양만 쓴다 */
.ap-mask-ico.upload {
  -webkit-mask-image: url("../krds/1/icons/ico_upload_20_wh.svg");
  mask-image: url("../krds/1/icons/ico_upload_20_wh.svg");
}
.ap-mask-ico.del {
  -webkit-mask-image: url("../krds/1/icons/ico_del_20.svg");
  mask-image: url("../krds/1/icons/ico_del_20.svg");
}

.ap-user {
  display: flex; align-items: center; gap: var(--krds-gap-2);
  margin-left: auto; flex: none;
  font-size: var(--krds-ui-fz-sub); color: var(--krds-gray-70);
}
.ap-user .who { font-weight: 700; color: var(--krds-gray-90); }
.ap-user .dept { color: var(--krds-gray-60); }
.ap-user .btn { margin-left: var(--krds-gap-1); }

/* 본문 — 사이드바가 있으면 두 단 */
.ap-body {
  display: flex; align-items: flex-start;
  max-width: var(--krds-content-max); margin-inline: auto;
  min-height: calc(100vh - var(--ap-header-h) - var(--ap-footer-h));
}
.ap-main { flex: 1; min-width: 0; padding: var(--krds-gap-5); }

/* 곁메뉴(LNB) */
.ap-sidebar {
  width: var(--ap-sidebar-w); flex: none;
  align-self: stretch;
  padding: var(--krds-gap-4) var(--krds-gap-3);
  border-right: 1px solid var(--krds-gray-20);
  background: var(--krds-white);
}
.ap-sidebar a {
  display: block;
  padding: var(--krds-gap-2) var(--krds-gap-3);
  border-radius: var(--krds-ui-rd);
  color: var(--krds-gray-80); text-decoration: none;
  font-size: var(--krds-ui-fz);
}
.ap-sidebar a:hover { background: var(--krds-gray-5); }
.ap-sidebar a[aria-current="page"], .ap-sidebar a.active {
  background: var(--krds-primary-5); color: var(--krds-primary-60); font-weight: 700;
}
.ap-sidebar .ap-group {
  margin: var(--krds-gap-4) var(--krds-gap-3) var(--krds-gap-1);
  font-size: var(--krds-fz-detail-sm); font-weight: 700; color: var(--krds-gray-60);
}
.ap-sidebar .ap-group:first-child { margin-top: 0; }
/* 곁메뉴의 빈 상태·오류 문장. 링크와 같은 들여쓰기로 줄을 맞춘다 */
.ap-sidebar .ap-muted {
  margin: 0; padding: var(--krds-gap-2) var(--krds-gap-3);
  font-size: var(--krds-ui-fz-sub); line-height: 1.5;
}

/* 푸터 — 운영기관 식별자 */
.ap-footer {
  margin-top: auto;
  border-top: 1px solid var(--krds-gray-20);
  background: var(--krds-gray-5);
  font-size: var(--krds-fz-detail-sm); color: var(--krds-gray-60);
}
.ap-footer .inner {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--krds-gap-3) var(--krds-gap-5);
  max-width: var(--krds-content-max); margin-inline: auto;
  padding: var(--krds-gap-4) var(--krds-gap-5);
}
/* 운영기관 CI. 회색조로 봐도 읽히게 원색 그대로 두고 크기만 줄인다 */
.ap-footer-logo { height: 3.2rem; width: auto; flex: none; }
.ap-footer-info { min-width: 0; }
.ap-footer-info .lines {
  display: flex; flex-wrap: wrap; gap: var(--krds-spacer-1) var(--krds-gap-3);
  margin: 0;
}
.ap-footer-info .lines + .lines { margin-top: var(--krds-spacer-1); }
.ap-footer-links {
  display: flex; flex-wrap: wrap; gap: var(--krds-gap-3);
  margin: 0 0 0 auto;
}
.ap-footer-links a { font-weight: 700; color: var(--krds-gray-80); }
.ap-footer .org { font-weight: 700; color: var(--krds-gray-80); }
.ap-footer a { color: inherit; }

/* ============================================================
   2. 페이지 머리 · 안내
   ============================================================ */

.ap-page-head {
  display: flex; align-items: flex-end; flex-wrap: wrap;
  gap: var(--krds-gap-2) var(--krds-gap-3);
  margin-bottom: var(--krds-gap-4);
}
.ap-page-head .ap-actions { margin-left: auto; display: flex; gap: var(--krds-gap-2); }
.ap-page-desc { margin-top: var(--krds-gap-1); color: var(--krds-gray-60); font-size: var(--krds-ui-fz-sub); }

/* 필수 표시 설명에 쓰는 별표 */
.ap-req-mark { color: var(--krds-danger); font-weight: 700; }

/* 칸 전체를 채우는 단추 (곁메뉴 맨 위 같은 자리) */
.ap-block { width: 100%; }

/* 입력 화면 — 폼 하나가 본문 전부일 때. 너무 넓으면 읽기 어렵다 */
.ap-form-page { max-width: var(--krds-measure); }
.ap-form-page .btn-wrap { margin-top: var(--krds-gap-5); justify-content: flex-end; }

/* 상세 화면의 머리 정보 — 등록·조회 같은 짧은 항목을 한 줄에 */
.ap-meta {
  display: flex; flex-wrap: wrap; gap: var(--krds-spacer-1) var(--krds-gap-3);
  margin: 0 0 var(--krds-gap-4); padding-bottom: var(--krds-gap-3);
  border-bottom: 1px solid var(--krds-gray-20);
  font-size: var(--krds-ui-fz-sub); color: var(--krds-gray-60);
}
.ap-meta dt { font-weight: 400; }
.ap-meta dd { margin: 0 var(--krds-gap-2) 0 var(--krds-spacer-1); color: var(--krds-gray-80); }

/* 본문 글 — 마크다운을 그려 넣는 자리. 읽는 길이를 제한한다 */
.ap-prose { max-width: var(--krds-measure); line-height: 1.7; }
.ap-prose > * + * { margin-top: var(--krds-gap-3); }
.ap-prose h2 { font-size: var(--krds-ui-fz-sect); margin-top: var(--krds-gap-5); }
.ap-prose h3 { font-size: var(--krds-fz-title-md); margin-top: var(--krds-gap-4); }
.ap-prose ul, .ap-prose ol { padding-left: var(--krds-gap-4); }
.ap-prose li + li { margin-top: var(--krds-spacer-2); }
.ap-prose img { max-width: 100%; height: auto; }
.ap-prose pre {
  overflow-x: auto; padding: var(--krds-gap-3);
  border: 1px solid var(--krds-gray-20); border-radius: var(--krds-rd-6);
  background: var(--krds-gray-5);
}
.ap-prose blockquote {
  padding-left: var(--krds-gap-3);
  border-left: 3px solid var(--krds-gray-30); color: var(--krds-gray-70);
}
.ap-prose table { width: 100%; border-collapse: collapse; }
.ap-prose th, .ap-prose td { padding: var(--krds-gap-2); border: 1px solid var(--krds-gray-20); text-align: left; }

/* 두 단 — 왼쪽이 본 일, 오른쪽이 곁들이는 정보. 좁아지면 한 단으로 쌓인다 */
.ap-cols {
  display: grid; gap: var(--krds-gap-4);
  grid-template-columns: 2fr 1fr; align-items: start;
}
@media (max-width: 900px) { .ap-cols { grid-template-columns: 1fr; } }

/* 카드 제목줄 — 제목 + 오른쪽 단추 */
.ap-card-head {
  display: flex; align-items: center; gap: var(--krds-gap-2);
  margin-bottom: var(--krds-gap-3);
}
.ap-card-head > :first-child { flex: 1; min-width: 0; margin-bottom: 0; }

/* 키·해시처럼 줄바꿈이 필요한 긴 값 */
.ap-key { font-family: ui-monospace, SFMono-Regular, Consolas, monospace; word-break: break-all; }

/* 요약 숫자 줄 — 관리 화면 맨 위의 "몇 개 / 몇 대 / 몇 MB" */
.ap-stat-row { display: flex; flex-wrap: wrap; gap: var(--krds-gap-3) var(--krds-gap-5); }
.ap-stat { min-width: 0; }
.ap-stat.grow { flex: 1 1 24rem; }
.ap-stat .label { display: block; font-size: var(--krds-ui-fz-sub); color: var(--krds-gray-60); }
.ap-stat strong {
  display: block; margin-top: var(--krds-spacer-1);
  font-size: var(--krds-ui-fz-sect); color: var(--krds-gray-90);
  font-variant-numeric: tabular-nums;
}

/* 표 안의 숫자 입력 칸 — 값만 보이면 되므로 좁게 */
.ap-num-input { width: 9rem; text-align: right; font-variant-numeric: tabular-nums; }

/* 카드 안 구역 제목 */
.krds-card > .krds-section-title { margin-bottom: var(--krds-gap-3); }

/* 배포 기록처럼 한 줄씩 쌓이는 목록 */
.ap-loglines { margin: 0; padding: 0; list-style: none; }
.ap-loglines li {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--krds-spacer-2);
  padding: var(--krds-gap-2) 0;
  border-bottom: 1px solid var(--krds-gray-10);
  font-size: var(--krds-ui-fz-sub);
}
.ap-loglines li:last-child { border-bottom: 0; }

/* 카드 격자 — 앱 마켓처럼 고르는 목록. 좁아지면 한 단이 된다 */
.ap-card-grid {
  display: grid; gap: var(--krds-gap-3);
  grid-template-columns: repeat(auto-fill, minmax(28rem, 1fr));
  list-style: none; margin: 0; padding: 0;
}
.ap-app-card { display: flex; flex-direction: column; gap: var(--krds-gap-2); height: 100%; }
.ap-app-card h2 { font-size: var(--krds-ui-fz); font-weight: 700; color: var(--krds-gray-90); }
.ap-app-card p { font-size: var(--krds-ui-fz-sub); color: var(--krds-gray-60); }
.ap-app-card .foot {
  display: flex; align-items: center; gap: var(--krds-spacer-2);
  margin-top: auto; padding-top: var(--krds-gap-2);
}
.ap-app-card .foot .addr { font-size: var(--krds-fz-detail-sm); color: var(--krds-gray-60); }

/* 조회 조건 — 목록 위. 칸은 한 줄에 흘리고 단추는 오른쪽 아래에 모은다
   (KRDS 필터링·조회 패턴: 조건을 바꾸면 결과 수를 바로 알린다) */
.ap-filter {
  padding: var(--krds-gap-4);
  margin-bottom: var(--krds-gap-4);
  border: 1px solid var(--krds-gray-20);
  border-radius: var(--krds-rd-12);
  background: var(--krds-gray-5);
}
.ap-filter .fields { display: flex; flex-wrap: wrap; gap: var(--krds-gap-3); }
.ap-filter .fields .form-group { flex: 1 1 22rem; min-width: 0; margin-top: 0; }
.ap-filter .fields .form-group.narrow { flex: 0 1 20rem; }
.ap-filter .btn-wrap { margin-top: var(--krds-gap-3); justify-content: flex-end; }

/* 결과 수 — 목록 바로 위. 조건을 건 뒤 몇 건인지 먼저 알려 준다 */
.ap-result-count {
  margin: 0 0 var(--krds-gap-2);
  font-size: var(--krds-ui-fz-sub); color: var(--krds-gray-70);
}
.ap-result-count strong { color: var(--krds-gray-90); }

/* 알림 — 색 말고 아이콘·문장으로도 알린다. 왼쪽 색 띠는 쓰지 않는다 (테두리 전체를 옅은 종류 색으로) */
.ap-alert {
  display: flex; align-items: flex-start; gap: var(--krds-gap-2);
  padding: var(--krds-gap-3) var(--krds-gap-4);
  margin-bottom: var(--krds-gap-4);
  border: 1px solid var(--krds-gray-20);
  border-radius: var(--krds-rd-6);
  background: var(--krds-gray-5);
  font-size: var(--krds-ui-fz-sub);
}
.ap-alert .ico { width: 2rem; height: 2rem; flex: none; margin-top: .1rem; }
.ap-alert code {
  padding: 0 .4rem; border-radius: var(--krds-rd-4);
  background: var(--krds-white); border: 1px solid var(--krds-gray-20);
  font-size: inherit;   /* 고정폭 서체는 기본 크기가 작다. 본문과 줄을 맞춘다 */
}
/* urgent_badge 계열 아이콘은 흰 글리프라 색 바탕 위에서만 보인다.
   밝은 알림 상자에 그대로 얹으면 사라지므로 바탕을 깔아 준다 */
.ap-alert.warning .ico {
  padding: .2rem; border-radius: var(--krds-rd-full);
  background: var(--krds-warning-70);
}
.ap-alert.info    { border-color: var(--krds-primary-20); background: var(--krds-primary-5); }
.ap-alert.success { border-color: color-mix(in srgb, var(--krds-success) 30%, var(--krds-white)); background: var(--krds-success-5); }
.ap-alert.warning { border-color: color-mix(in srgb, var(--krds-warning-70) 30%, var(--krds-white)); background: var(--krds-warning-5); }
.ap-alert.error   { border-color: color-mix(in srgb, var(--krds-danger) 30%, var(--krds-white)); background: var(--krds-danger-5); color: var(--krds-gray-90); }

/* 페이지 이동 — 목록 아래 가운데. 한 화면에 하나만 둔다 */
.ap-pagination {
  display: flex; align-items: center; justify-content: center;
  gap: var(--krds-gap-2); margin-top: var(--krds-gap-5);
}
.ap-pagination .links {
  display: flex; align-items: center; gap: var(--krds-gap-1);
  list-style: none; margin: 0; padding: 0;
}
.ap-pagination a, .ap-pagination .navi, .ap-pagination .dots {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--krds-spacer-1);
  min-width: var(--krds-ui-h); height: var(--krds-ui-h);
  padding-inline: var(--krds-gap-2);
  border: 1px solid transparent; border-radius: var(--krds-ui-rd);
  background: transparent; color: var(--krds-gray-80); text-decoration: none;
  font-size: var(--krds-ui-fz-sub);
}
.ap-pagination .navi { border-color: var(--krds-gray-30); background: var(--krds-white); }
.ap-pagination .navi img { width: 1.6rem; height: 1.6rem; }
.ap-pagination .dots { min-width: 2.4rem; padding-inline: 0; color: var(--krds-gray-50); }
.ap-pagination a:hover { background: var(--krds-gray-5); text-decoration: underline; }
/* 현재 화면 — 배경 반전 + 굵기. 색만으로 구분하지 않는다 */
.ap-pagination .current {
  background: var(--krds-primary); border-color: var(--krds-primary);
  color: var(--krds-white); font-weight: 700; text-decoration: none; cursor: default;
}
.ap-pagination .current:hover { background: var(--krds-primary); text-decoration: none; }
/* 갈 수 없는 이전/다음 — 감추지 않고 자리를 지킨다 */
.ap-pagination .is-disabled { color: var(--krds-gray-50); border-color: var(--krds-gray-20); cursor: not-allowed; }
.ap-pagination .is-disabled img { opacity: .4; }

/* 좁은 화면 — 이전/다음을 위로 올리고 숫자를 아래로 (KRDS 모바일 배치) */
@media (max-width: 480px) {
  .ap-pagination { flex-wrap: wrap; }
  .ap-pagination .navi.prev { order: 1; margin-right: auto; }
  .ap-pagination .navi.next { order: 1; margin-left: auto; }
  .ap-pagination .links { order: 2; width: 100%; justify-content: center; flex-wrap: wrap; }
}

/* 아이콘 — 이모지를 쓰지 않는다. KRDS 공식 SVG 를 쓴다 */
.ap-ico { width: 2rem; height: 2rem; flex: none; }
.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: var(--krds-ui-h); min-height: var(--krds-ui-h);
  border: 1px solid transparent; border-radius: var(--krds-ui-rd);
  background: transparent; color: var(--krds-gray-70); cursor: pointer;
}
.icon-btn:hover { background: var(--krds-gray-10); }

/* 불러오는 중 */
.ap-spinner {
  display: inline-block; width: 1.8rem; height: 1.8rem;
  border: 2px solid var(--krds-gray-20); border-top-color: var(--krds-primary);
  border-radius: var(--krds-rd-full);
  animation: ap-spin .8s linear infinite;
}
@keyframes ap-spin { to { transform: rotate(360deg); } }
.ap-skeleton {
  border-radius: var(--krds-rd-4);
  background: linear-gradient(90deg, var(--krds-gray-10) 25%, var(--krds-gray-5) 37%, var(--krds-gray-10) 63%);
  background-size: 400% 100%;
  animation: ap-shimmer 1.4s ease infinite;
}
@keyframes ap-shimmer { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }
.ap-loading {
  display: flex; align-items: center; justify-content: center; gap: var(--krds-gap-2);
  padding: var(--krds-gap-5); color: var(--krds-gray-60); font-size: var(--krds-ui-fz-sub);
}

/* 오류 화면 — 레이아웃 없이 그리는 error/*.html. 403·404·500 의 머리·푸터는 1절 셸 규칙을 그대로 쓴다 */
.ap-error { max-width: 52rem; margin: var(--krds-spacer-20) auto; text-align: center; }
/* 큰 상태 숫자도 글자다 — 흰 바탕 대비 4.5:1 이상인 회색 */
.ap-error .status { font-size: var(--krds-fz-heading-md); font-weight: 700; color: var(--krds-gray-60); line-height: 1; }
.ap-error h1 { margin: var(--krds-gap-3) 0 var(--krds-gap-2); font-size: var(--krds-ui-fz-title); }
.ap-error p { color: var(--krds-gray-60); margin-bottom: var(--krds-gap-5); }
/* 셸 안(403·404·500)에서는 본문 안쪽 여백이 이미 있어 바깥 여백을 줄인다 */
.ap-body > .ap-error { margin-block: var(--krds-gap-4); }
.ap-error-ico { display: block; width: 12rem; height: auto; margin: 0 auto var(--krds-gap-3); }
/* 안내 문장 — 서비스 조각이 넣은 문단에도 같은 결 */
.ap-error-guide p { color: var(--krds-gray-80); margin-bottom: var(--krds-gap-4); }
/* 요청한 주소·참조 번호 — 문의할 때 옮겨 적는 값이라 왼쪽 맞춤·고른 숫자 폭. 긴 주소는 좁은 화면에서 칸 안에서 줄을 바꾼다 */
.ap-error-info {
  margin: 0 0 var(--krds-gap-5); padding: var(--krds-gap-3) var(--krds-gap-4);
  border: 1px solid var(--krds-gray-20); border-radius: var(--krds-ui-rd);
  background: var(--krds-gray-5);
  text-align: left; font-size: var(--krds-ui-fz-sub);
}
.ap-error-info > div { display: flex; flex-wrap: wrap; gap: 0 var(--krds-gap-3); }
.ap-error-info > div + div { margin-top: var(--krds-gap-1); }
.ap-error-info dt { flex: none; min-width: 8rem; font-weight: 700; color: var(--krds-gray-70); }
.ap-error-info dd {
  flex: 1 1 0; min-width: 0; margin: 0;
  color: var(--krds-gray-90); overflow-wrap: anywhere; font-variant-numeric: tabular-nums;
}

/* ============================================================
   3. 짧은 이름 — 기존 화면이 쓰던 ap-* 를 KRDS 로 잇는다

   화면을 새로 짤 때는 KRDS 클래스(btn / form-group / krds-table / krds-card)를
   쓴다. 아래는 이미 있는 화면이 한꺼번에 KRDS 규격을 따르도록 이어 준 층이고,
   값은 전부 위와 같은 토큰이라 두 이름이 같은 모양으로 그려진다.
   ============================================================ */

.ap-btn { }
.ap-btn, .ap-input, .ap-select, .ap-textarea { font-family: inherit; }

.ap-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--krds-gap-1);
  height: var(--krds-ui-h); padding-inline: var(--krds-ui-px);
  border: 1px solid var(--krds-gray-30); border-radius: var(--krds-ui-rd);
  background: var(--krds-white); color: var(--krds-gray-80);
  font-size: var(--krds-ui-fz); font-weight: 700; text-decoration: none;
  cursor: pointer; white-space: nowrap;
  transition: background-color var(--krds-ease), border-color var(--krds-ease), color var(--krds-ease);
}
.ap-btn:hover { background: var(--krds-gray-5); text-decoration: none; }
.ap-btn:active { background: var(--krds-gray-10); }
.ap-btn.primary { background: var(--krds-primary); border-color: var(--krds-primary); color: var(--krds-white); }
.ap-btn.primary:hover { background: var(--krds-primary-60); border-color: var(--krds-primary-60); }
.ap-btn.primary:active { background: var(--krds-primary-70); border-color: var(--krds-primary-70); }
.ap-btn.danger { color: var(--krds-danger); border-color: var(--krds-danger); }
.ap-btn.danger:hover { background: var(--krds-danger); color: var(--krds-white); }
.ap-btn.sm { height: var(--krds-ui-h-sub); padding-inline: var(--krds-gap-3); font-size: var(--krds-ui-fz-sub); }
.ap-btn:disabled, .ap-btn[aria-disabled="true"] {
  background: var(--krds-gray-20); border-color: transparent; color: var(--krds-gray-50); cursor: not-allowed;
}

.ap-input, .ap-select, .ap-textarea {
  width: 100%; height: var(--krds-ui-h);
  padding-inline: var(--krds-ui-px);
  border: 1px solid var(--krds-gray-60); border-radius: var(--krds-ui-rd);
  background: var(--krds-white); color: var(--krds-gray-80);
  font-size: var(--krds-ui-fz);
  transition: border-color var(--krds-ease), box-shadow var(--krds-ease);
}
.ap-textarea { height: auto; min-height: 12rem; padding-block: var(--krds-gap-2); resize: vertical; }
.ap-input::placeholder, .ap-textarea::placeholder { color: var(--krds-gray-50); }
.ap-input:focus, .ap-select:focus, .ap-textarea:focus {
  border-color: var(--krds-primary); box-shadow: 0 0 0 1px var(--krds-primary);
  outline: 2px solid transparent; outline-offset: 1px;
}
.ap-input:disabled, .ap-select:disabled, .ap-textarea:disabled {
  background: var(--krds-gray-10); color: var(--krds-gray-50); cursor: not-allowed;
}
.ap-input.is-invalid, .ap-select.is-invalid, .ap-textarea.is-invalid { border-color: var(--krds-danger); }

.ap-form .ap-field + .ap-field { margin-top: var(--krds-gap-3); }
.ap-form label {
  display: block; margin-bottom: var(--krds-gap-1);
  font-size: var(--krds-ui-fz-label); font-weight: 700; color: var(--krds-gray-80);
}
.ap-form label.required::after { content: " *"; color: var(--krds-danger); }
/* 오류는 테두리·아이콘·문장을 함께 준다 */
.ap-field-error {
  display: flex; align-items: flex-start; gap: var(--krds-gap-1);
  margin-top: var(--krds-gap-1);
  font-size: var(--krds-ui-fz-sub); color: var(--krds-danger);
}
.ap-field-error::before { content: "!"; flex: none; font-weight: 700; }
.ap-help { margin-top: var(--krds-gap-1); font-size: var(--krds-ui-fz-sub); color: var(--krds-gray-60); }

.ap-card {
  padding: var(--krds-gap-4);
  margin-bottom: var(--krds-gap-4);
  border: 1px solid var(--krds-gray-20); border-radius: var(--krds-rd-12);
  background: var(--krds-white);
}

.ap-table { width: 100%; border-collapse: collapse; background: var(--krds-white); }
.ap-table th, .ap-table td {
  height: var(--krds-row-h); padding: var(--krds-gap-2) var(--krds-gap-3);
  border-bottom: 1px solid var(--krds-gray-20);
  text-align: left; vertical-align: middle; font-size: var(--krds-ui-fz-sub);
}
.ap-table thead th {
  background: var(--krds-gray-5); color: var(--krds-gray-80);
  font-weight: 700; border-top: 2px solid var(--krds-gray-70);
}
.ap-table tbody tr:hover td { background: var(--krds-gray-5); }
.ap-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.ap-table .center { text-align: center; }
/* 표는 좁은 화면에서 제 안에서 가로로 움직인다 — 문서가 통째로 밀리면 안 된다 */
.ap-table-wrap { overflow-x: auto; }

/* 표 칸 안의 보조 문장 (실패 사유 등) — 배지 색만으로 알리지 않기 위한 자리 */
.ap-cell-note {
  margin: var(--krds-spacer-1) 0 0;
  font-size: var(--krds-fz-detail-sm); color: var(--krds-danger);
  white-space: normal;
}
/* 표 맨 오른쪽 관리 단추 묶음 */
.ap-cell-actions { display: flex; flex-wrap: wrap; gap: var(--krds-spacer-2); }
.krds-table td.center .ap-cell-actions { justify-content: center; }

/* 카드가 이어지면 사이를 띄운다 */
.krds-card + .krds-card { margin-top: var(--krds-gap-4); }

/* 빈 상태 — 아이콘 + 무엇이 없는지 + (있으면) 다음 행동 */
.ap-empty {
  display: flex; flex-direction: column; align-items: center; gap: var(--krds-gap-2);
  padding: var(--krds-spacer-12) var(--krds-gap-5);
  text-align: center; color: var(--krds-gray-60);
}
.ap-empty .ico { width: 2.8rem; height: 2.8rem; opacity: .5; }
.ap-empty p { margin: 0; }
.ap-empty .btn { margin-top: var(--krds-gap-2); }

.ap-badge {
  display: inline-flex; align-items: center; height: 2.6rem;
  padding-inline: var(--krds-gap-2);
  border-radius: var(--krds-rd-4);
  background: var(--krds-gray-10); color: var(--krds-gray-70);
  font-size: var(--krds-fz-detail-sm); font-weight: 700;
}
.ap-badge.primary { background: var(--krds-primary-5); color: var(--krds-primary-60); }
.ap-badge.success { background: var(--krds-success-5); color: var(--krds-success-70); }
.ap-badge.danger  { background: var(--krds-danger-5); color: var(--krds-danger-70); }
/* krds-base 의 배지도 같은 글자색으로 덮는다 — 원본 상태 색은 연한 바탕 위에서 4.5:1 에 못 미친다 */
.krds-badge.success { color: var(--krds-success-70); }
.krds-badge.danger  { color: var(--krds-danger-70); }
.ap-badge.warning { background: var(--krds-warning-5); color: var(--krds-warning-70); }

.ap-page-title { font-size: var(--krds-ui-fz-title); font-weight: 700; color: var(--krds-gray-90); letter-spacing: -.02em; }
.ap-section-title { font-size: var(--krds-ui-fz-sect); font-weight: 700; color: var(--krds-gray-90); margin-bottom: var(--krds-gap-2); }
.ap-row { display: flex; gap: var(--krds-gap-3); align-items: center; flex-wrap: wrap; }
.ap-grow { flex: 1; min-width: 0; }
.ap-muted { color: var(--krds-gray-60); }
.ap-right { text-align: right; }
.ap-mt { margin-top: var(--krds-gap-4); }
.ap-mb { margin-bottom: var(--krds-gap-4); }

a { color: var(--krds-primary); }
a:hover { text-decoration: underline; }

/* ============================================================
   4. 좁은 화면 — 360px 에서 가로 스크롤이 없어야 한다
   ============================================================ */

/* 숨는 메뉴는 '메뉴' 단추(ai-platform.js 가 body 에 ap-menu-open 을 켠다)로 다시 펼친다.
   요소를 복제하지 않고 같은 요소를 세로로 늘어놓는다. 넓은 화면에서는 열림 상태가
   남아도 모양이 바뀌지 않게 이 규칙들은 모두 미디어 쿼리 안에 둔다 */
@media (max-width: 1024px) {
  .ap-sidebar { display: none; }
  /* 곁메뉴가 있는 화면은 이 폭부터 단추를 꺼내 곁메뉴를 본문 위에 펼친다 */
  .ap-has-sidebar .ap-menu-toggle { display: inline-flex; }
  .ap-menu-open .ap-body { flex-direction: column; }
  .ap-menu-open .ap-sidebar {
    display: block; width: 100%;
    border-right: 0; border-bottom: 1px solid var(--krds-gray-20);
  }
}
@media (max-width: 768px) {
  .ap-header .inner, .ap-masthead .inner, .ap-footer .inner { padding-inline: var(--krds-gap-4); }
  .ap-main { padding: var(--krds-gap-4); }
  .ap-user .dept { display: none; }

  /* 헤더 첫 줄은 브랜드·메뉴 단추·사용자. 좁으면 줄을 바꿔 가로로 넘치지 않게 하고,
     첫 줄 높이는 펼쳐도 그대로 두려고 브랜드가 헤더 높이를 잡는다 */
  .ap-header .inner { flex-wrap: wrap; gap: var(--krds-gap-2) var(--krds-gap-3); }
  .ap-brand-link { flex: 0 1 auto; min-width: 0; min-height: var(--ap-header-h); }
  .ap-user { flex-wrap: wrap; min-width: 0; }
  .ap-menu-toggle { display: inline-flex; margin-left: auto; }
  .ap-menu-toggle:not([hidden]) ~ .ap-user { margin-left: 0; }

  /* 주메뉴·유틸리티는 단추 뒤로 들어가고, 펼치면 다음 줄에 세로 목록으로 선다 */
  .ap-header-menu { display: none; }
  .ap-menu-open .ap-header-menu {
    display: flex; flex-direction: column; align-items: stretch; gap: 0;
    order: 1; flex-basis: 100%;
    padding-block: var(--krds-gap-2);
    border-top: 1px solid var(--krds-gray-20);
  }
  /* 펼친 헤더가 화면보다 길면(확대·가로 화면) 헤더 안에서 스크롤한다 — 고정 헤더라
     문서 스크롤로는 끝에 닿지 않는다. 주소창이 접히는 모바일은 dvh 가 맞는 높이다 */
  .ap-menu-open .ap-header { max-height: 100vh; max-height: 100dvh; overflow-y: auto; }
  .ap-menu-open .ap-gnb, .ap-menu-open .ap-utils, .ap-menu-open .ap-gnb-group {
    flex: none; flex-direction: column; align-items: stretch; gap: 0;
  }
  .ap-menu-open .ap-utils { padding-top: var(--krds-gap-2); border-top: 1px solid var(--krds-gray-20); }
  .ap-menu-open .ap-gnb a, .ap-menu-open .ap-gnb-btn, .ap-menu-open .ap-utils a {
    display: flex; align-items: center; width: 100%;
    height: auto; min-height: var(--krds-ui-h);
    padding-inline: var(--krds-gap-3);
    text-align: left; white-space: normal;
    box-shadow: none;
  }
  .ap-menu-open .ap-gnb-btn::after { margin-left: auto; }
  .ap-menu-open .ap-gnb a:hover, .ap-menu-open .ap-gnb-btn:hover, .ap-menu-open .ap-utils a:hover {
    background: var(--krds-gray-5); box-shadow: none;
  }
  /* 세로 목록의 현재 표시 — 아래 밑줄과 굵기. 위·왼쪽 변에 색 띠를 긋지 않는다 */
  .ap-menu-open .ap-gnb a[aria-current="page"],
  .ap-menu-open .ap-gnb-btn[aria-current]:not([aria-current="false"]) {
    box-shadow: none; font-weight: 700;
    text-decoration-line: underline; text-decoration-color: var(--ap-accent);
    text-decoration-thickness: .2rem; text-underline-offset: .4rem;
  }
  /* 하위 목록은 떠 있지 않고 묶음 아래에 들여 쓴다 */
  .ap-menu-open .ap-gnb-sub {
    position: static; min-width: 0; max-height: none; overflow: visible;
    padding: 0 0 0 var(--krds-gap-4);
    border: 0; border-radius: 0; box-shadow: none;
  }
}

/* ============================================================
   5. 로그인 — KRDS 서비스 패턴(로그인) 단일형

   한 화면에서 한 가지 인증 방식만 받는다. 인증 방식이 여럿이면
   목록/탭으로 나누라는 것이 가이드라인이지만, 이 플랫폼은 포털 계정 하나뿐이다.
   ============================================================ */

.ap-auth {
  width: 100%; max-width: 44rem;
  margin: var(--krds-spacer-16) auto;
}
/* 로그인 화면 맨 위의 기관 CI. 헤더보다 크게 세워 "어디에 들어가는지" 를 먼저 보인다 */
.ap-auth-logo { display: block; height: 4rem; width: auto; margin: 0 auto var(--krds-gap-5); }
.ap-auth .eyebrow {
  display: block; margin-bottom: var(--krds-gap-1);
  font-size: var(--krds-ui-fz-sub); font-weight: 700; color: var(--krds-secondary);
}
.ap-auth h1 { margin-bottom: var(--krds-gap-2); }
.ap-auth .lead { margin-bottom: var(--krds-gap-5); color: var(--krds-gray-60); font-size: var(--krds-ui-fz-sub); }
.ap-auth .btn { width: 100%; }
.ap-auth .form-group + .btn-wrap { margin-top: var(--krds-gap-5); }
.ap-auth .after {
  margin-top: var(--krds-gap-4); padding-top: var(--krds-gap-4);
  border-top: 1px solid var(--krds-gray-20);
  text-align: center; font-size: var(--krds-ui-fz-sub); color: var(--krds-gray-60);
}

/* 칸 아래 오류 문장의 아이콘. 색만으로 알리지 않기 위한 것이라 크기를 고정한다 */
.form-hint-invalid img { width: 1.8rem; height: 1.8rem; flex: none; }

/* 비밀번호 보기/가리기 — 입력칸 안쪽 오른쪽.
   오류 문장이 붙어 칸이 세로로 길어져도 단추는 입력칸 줄에 남아야 하므로
   컨테이너 가운데(50%)가 아니라 입력칸 높이의 절반에 건다 */
.ap-pw { position: relative; }
.ap-pw .form-control { padding-right: calc(var(--krds-ui-h) + var(--krds-gap-1)); }
.ap-pw .toggle {
  position: absolute; top: calc(var(--krds-ui-h) / 2); right: var(--krds-gap-1); transform: translateY(-50%);
  display: inline-flex; align-items: center; justify-content: center;
  min-width: var(--krds-ui-h-sub); min-height: var(--krds-ui-h-sub);
  border: 0; border-radius: var(--krds-ui-rd);
  background: transparent; color: var(--krds-gray-60); cursor: pointer;
  font-size: var(--krds-ui-fz-sub);
}
.ap-pw .toggle:hover { background: var(--krds-gray-10); }

/* 폼 맨 위 오류 요약. 초점을 여기로 옮겨 낭독기가 먼저 읽게 한다 */
.ap-form-error {
  display: flex; align-items: flex-start; gap: var(--krds-gap-2);
  padding: var(--krds-gap-3);
  margin-bottom: var(--krds-gap-4);
  border: 1px solid var(--krds-danger); border-radius: var(--krds-rd-6);
  background: var(--krds-danger-5); color: var(--krds-gray-90);
  font-size: var(--krds-ui-fz-sub);
}
.ap-form-error .ico { width: 2rem; height: 2rem; flex: none; }

/* 막대 — 차트 라이브러리 없이 (폐쇄망). 높이만 데이터로 주고 숫자는 표로 함께 준다 */
.ap-bars {
  display: flex; align-items: flex-end; gap: 2px;
  height: 12rem; padding-top: var(--krds-gap-2);
  border-bottom: 1px solid var(--krds-gray-30);
}
.ap-bars span {
  flex: 1; min-height: 1px;
  background: var(--krds-primary);
  border-radius: var(--krds-rd-2) var(--krds-rd-2) 0 0;
}

/* 알림(토스트). 흰 카드 한 장 + 종류별 아이콘 + 글. 왼쪽·위쪽 색 띠는 쓰지 않는다 (src/CLAUDE.md — 색 강조선 금지).
   종류는 아이콘 모양(체크·X·느낌표·i)과 색 두 가지로 알린다 (색만으로 알리지 않는다).
   낭독기에는 알림마다 role(status/alert)로 전해진다 — ai-platform.js 의 toast() */
.ap-toast-host {
  position: fixed; z-index: 9999;
  /* 헤더(고정)를 덮지 않게 그 아래에서 시작한다 */
  top: calc(var(--ap-header-h) + var(--krds-gap-3)); right: var(--krds-gap-3);
  display: flex; flex-direction: column; gap: var(--krds-gap-2);
  max-width: min(36rem, calc(100vw - var(--krds-gap-5)));
}
.ap-toast {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 10px 14px 10px 12px;
  border: 1px solid var(--krds-gray-20); border-radius: 10px;
  background: var(--krds-white);
  color: var(--krds-gray-90);
  font-size: var(--krds-ui-fz-sub); line-height: 1.5;
  box-shadow: 0 6px 20px rgba(0, 0, 0, .10);
  animation: ap-toast-in .18s ease-out;
}
.ap-toast-ico { flex: none; width: 18px; height: 18px; margin-top: 1px; color: var(--krds-information); }
.ap-toast.success .ap-toast-ico { color: var(--krds-success); }
.ap-toast.error   .ap-toast-ico { color: var(--krds-danger); }
.ap-toast.warning .ap-toast-ico { color: var(--krds-warning-70); }
@keyframes ap-toast-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .ap-toast { animation: none; } }

/* ============================================================
   6. 상태 보강 — 초점·눌림

   초점 윤곽선은 krds-base 의 :focus-visible(2px primary)을 그대로 쓰고 지우지 않는다.
   여기서는 잘리기 쉬운 자리의 윤곽선만 안쪽으로 당기고, 누른 순간(:active)을
   한 단계 짙게 보탠다 — 눌렸는지 눈으로 알 수 있어야 한다.
   ============================================================ */

/* 새 대화 요소의 초점 — 기본값과 같지만 서비스 CSS 가 덮어도 남게 적어 둔다 */
.ap-menu-toggle:focus-visible, .ap-gnb-btn:focus-visible,
.ap-gnb-sub a:focus-visible, .ap-utils a:focus-visible {
  outline: 2px solid var(--krds-primary); outline-offset: 2px;
}
/* 헤더 높이를 꽉 채운 주메뉴 항목과 제 안에서 스크롤하는 하위 목록 — 바깥 윤곽선이
   헤더 밑선에 겹치거나 잘리므로 안쪽에 긋는다 */
.ap-gnb a:focus-visible, .ap-gnb-btn:focus-visible, .ap-gnb-sub a:focus-visible { outline-offset: -2px; }
@media (max-width: 768px) {
  /* 펼친 헤더는 스크롤 상자라 바깥 윤곽선이 잘린다 */
  .ap-menu-open .ap-header-menu :focus-visible { outline-offset: -2px; }
}

/* 눌림 — 누르는 동안 한 단계 짙게. 자리는 옮기지 않는다.
   aria-disabled 단추는 눌러도 아무 일이 없으므로 눌림 색도 내지 않는다 */
.btn.secondary:active:not([aria-disabled="true"]) { background: var(--krds-primary-10); }
.btn.tertiary:active:not([aria-disabled="true"]) { background: var(--krds-gray-10); }
.btn.danger:active:not([aria-disabled="true"]) { background: var(--krds-danger-5); color: var(--krds-danger-70); border-color: var(--krds-danger-70); }
.ap-btn.danger:active { background: var(--krds-danger-70); border-color: var(--krds-danger-70); color: var(--krds-white); }
.icon-btn:active, .ap-pw .toggle:active { background: var(--krds-gray-20); }
.ap-gnb a:active, .ap-gnb-btn:active, .ap-menu-toggle:active,
.ap-sidebar a:active, .ap-pagination a:active { background: var(--krds-gray-10); }
.ap-gnb .ap-gnb-sub a:active,
.ap-menu-open .ap-gnb a:active, .ap-menu-open .ap-gnb-btn:active, .ap-menu-open .ap-utils a:active { background: var(--krds-gray-10); }
/* 본문 글 속 링크. 단추·메뉴처럼 class 가 붙은 링크는 저마다 눌림 색이 있어 건드리지 않는다 */
a:not([class]):active { color: var(--krds-primary-70); }

/* 고대비 모드 — 배경색으로 칠한 아이콘과 그림자로 그린 밑줄은 지워지므로
   아이콘은 시스템 글자색으로 다시 칠하고, 현재·펼침 표시는 글자 밑줄로 대신한다 */
@media (forced-colors: active) {
  .ap-mask-ico, .ap-gnb-btn::after { forced-color-adjust: none; background-color: ButtonText; }
  .ap-gnb a[aria-current="page"],
  .ap-gnb-btn[aria-current]:not([aria-current="false"]),
  .ap-gnb-btn[aria-expanded="true"] { text-decoration: underline; }
}

/* ============================================================
   7. 부품 — 모달·탭·단계·브레드크럼

   마크업은 templates/ai-platform/fragments.html 의 조각(modal·tabLinks·tabs·tabPanel·
   steps·breadcrumb)이 그리고, 동작(모달 초점·탭 방향키)은 ai-platform.js 의
   AP.modal·AP.tabs 가 붙인다. 바깥 감싸개는 ap- 이름, 안쪽은 KRDS 표준 마크업 이름이다.
   선택·현재 표시는 아래 밑줄·굵기·채움·글자로 한다 — 윗변·왼쪽 변에 색 띠를 긋지 않는다.
   ============================================================ */

/* ── 모달 ── */
/* 머리 / 본문(제 안에서 스크롤) / 바닥(늘 보임) 세 칸 — 본문이 길어도 행동 단추가 화면 밖으로 밀리지 않는다(KRDS).
   닫힌 창은 브라우저 기본(숨김)을 따르도록 세로 배치는 [open] 에만 준다. 머리 오른쪽은 닫기 단추 자리만큼 비운다 */
.ap-modal {
  width: min(56rem, calc(100vw - 2 * var(--krds-gap-4)));
  max-width: none;
  max-height: calc(100vh - 2 * var(--krds-gap-4));
  max-height: calc(100dvh - 2 * var(--krds-gap-4));
  padding: 0;
  border: .1rem solid var(--krds-gray-20); border-radius: var(--krds-rd-12);
  background: var(--krds-white); color: var(--krds-gray-80);
  box-shadow: var(--krds-shadow-lg);
  overflow: hidden;
}
.ap-modal[open] { display: flex; flex-direction: column; }
/* 가림막 — 뒤 화면이 잠겼음을 보인다. 사용자 속성을 물려받지 못하는 옛 브라우저에서는 투명하게 남는다 */
.ap-modal::backdrop { background-color: var(--krds-gray-90); opacity: .6; }
.ap-modal .modal-header {
  flex: none;
  padding: var(--krds-gap-4) calc(var(--krds-ui-h) + var(--krds-gap-3) + var(--krds-gap-1)) var(--krds-gap-2) var(--krds-gap-4);
}
.ap-modal .modal-title {
  font-size: var(--krds-ui-fz-sect); font-weight: 700; line-height: 1.4;
  color: var(--krds-gray-90);
}
/* 본문이 넘치면 아래쪽에 옅은 그늘이 생겨 더 있음을 알린다(KRDS 흐림 효과) — 끝까지 내리면 흰 덮개(local)가 그늘(scroll)을 가린다 */
.ap-modal .modal-conts {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  padding: var(--krds-gap-2) var(--krds-gap-4) var(--krds-gap-4);
  background:
    linear-gradient(transparent, var(--krds-white) 70%) center bottom / 100% var(--krds-gap-4) no-repeat local,
    linear-gradient(transparent, var(--krds-gray-30)) center bottom / 100% var(--krds-gap-2) no-repeat scroll,
    var(--krds-white);
}
.ap-modal .modal-conts > * + * { margin-top: var(--krds-gap-3); }
.ap-modal .modal-btn {
  flex: none; justify-content: flex-end;
  padding: var(--krds-gap-3) var(--krds-gap-4);
}
/* 닫기(X) — 마크업은 창의 마지막 요소(KRDS)이고 자리는 오른쪽 위다. hover·눌림은 .icon-btn 을 따른다 */
.ap-modal .modal-close {
  position: absolute; top: var(--krds-gap-3); right: var(--krds-gap-3);
  color: var(--krds-gray-80);
}
.ap-modal .modal-close:focus-visible { outline: .2rem solid var(--krds-primary); outline-offset: .2rem; }

/* ── 탭 ── */
/* 주소형(.ap-tab-links — 링크 + aria-current="page")과 같은 화면형(.ap-tabs — role="tab" 단추 + aria-selected)이
   같은 모양이다. 목록은 줄을 바꾸지 않고 제 안에서 가로로 움직인다 — 좁은 화면에서도 문서가 가로로 밀리지 않게.
   사용 불가 탭은 두지 않으므로(KRDS) disabled 모양을 만들지 않는다 */
.ap-tab-links { margin-bottom: var(--krds-gap-4); }
.ap-tab-links ul, .ap-tabs {
  display: flex; gap: var(--krds-gap-1);
  margin: 0; padding: 0; list-style: none;
  overflow-x: auto;
  border-bottom: .1rem solid var(--krds-gray-30);
}
.ap-tab-links li { flex: none; }
.ap-tab-links a, .ap-tab {
  display: inline-flex; align-items: center; flex: none;
  min-height: var(--krds-ui-h); padding-inline: var(--krds-gap-3);
  border: 0; border-radius: var(--krds-ui-rd) var(--krds-ui-rd) 0 0;
  background: transparent; color: var(--krds-gray-70); cursor: pointer;
  font-size: var(--krds-ui-fz); font-weight: 400; white-space: nowrap; text-decoration: none;
  box-shadow: inset 0 -.3rem 0 transparent;
  transition: background-color var(--krds-ease), color var(--krds-ease), box-shadow var(--krds-ease);
}
.ap-tab-links a:hover, .ap-tab:hover {
  background: var(--krds-gray-5); color: var(--krds-gray-90);
  box-shadow: inset 0 -.3rem 0 var(--krds-gray-30);
}
.ap-tab-links a:active, .ap-tab:active { background: var(--krds-gray-10); }
/* 가로 스크롤 상자라 바깥 윤곽선이 잘리므로 안쪽에 긋는다 */
.ap-tab-links a:focus-visible, .ap-tab:focus-visible { outline: .2rem solid var(--krds-primary); outline-offset: -.2rem; }
/* 고른 탭·지금 화면 — 글자색에 굵기와 아래 밑줄을 더해 색만으로 알리지 않는다 */
.ap-tab-links a[aria-current="page"], .ap-tab[aria-selected="true"] {
  color: var(--krds-primary-60); font-weight: 700;
  box-shadow: inset 0 -.3rem 0 var(--krds-primary);
}
.ap-tab-panel { padding-top: var(--krds-gap-4); }

/* ── 단계 표시기 ── */
/* 완료·현재·실패·예정을 글자(.step-state)와 테두리·채움·굵기로 함께 알린다 — 색만으로 가리지 않는다.
   조작 요소가 아니라 hover·눌림·초점 모양이 없다. 좁으면 줄을 바꿔 문서가 가로로 밀리지 않는다 */
.ap-steps {
  display: flex; flex-wrap: wrap; gap: var(--krds-gap-2);
  margin: 0; padding: 0; list-style: none;
}
.ap-steps > li {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--krds-spacer-1) var(--krds-gap-1);
  flex: 1 1 12rem; min-width: 0;
  padding: var(--krds-gap-2) var(--krds-gap-3);
  border: .1rem solid var(--krds-gray-30); border-radius: var(--krds-rd-8);
  background: var(--krds-white); color: var(--krds-gray-70);
  font-size: var(--krds-ui-fz-sub);
}
.ap-steps .step { flex-basis: 100%; font-size: var(--krds-fz-detail-sm); color: var(--krds-gray-70); }
.ap-steps .step-tit { min-width: 0; color: var(--krds-gray-90); }
.ap-steps .step-state {
  padding-inline: var(--krds-gap-1);
  border-radius: var(--krds-rd-4);
  font-size: var(--krds-fz-detail-sm); font-weight: 700;
}
.ap-steps > .is-done { border-color: var(--krds-primary-20); }
.ap-steps > .is-done .step-state { background: var(--krds-primary-5); color: var(--krds-primary-60); }
/* 현재 — 테두리를 안쪽 그림자로 한 겹 더 두껍게(자리 이동 없이), 옅은 채움과 굵은 이름 */
.ap-steps > .is-current {
  border-color: var(--krds-primary); background: var(--krds-primary-5);
  box-shadow: inset 0 0 0 .1rem var(--krds-primary);
}
.ap-steps > .is-current .step-state { background: var(--krds-primary); color: var(--krds-white); }
.ap-steps > .is-error {
  border-color: var(--krds-danger); background: var(--krds-danger-5);
  box-shadow: inset 0 0 0 .1rem var(--krds-danger);
}
.ap-steps > .is-error .step-state { background: var(--krds-danger-70); color: var(--krds-white); }
.ap-steps > .is-current .step-tit, .ap-steps > .is-error .step-tit { font-weight: 700; }
/* 예정 — 점선 테두리로 아직 오지 않은 단계임을 모양으로도 알린다 */
.ap-steps > .is-todo { border-style: dashed; }
.ap-steps > .is-todo .step-tit { color: var(--krds-gray-70); }

/* ── 브레드크럼 ── */
/* 링크는 밑줄로 링크임을 보이고(KRDS), 갈 화면이 없는 항목·지금 화면은 밑줄·hover 없는 글자다.
   구분자·홈 아이콘은 의사 요소라 낭독기에 읽히지 않는다. 구분자 색 gray-60 은 흰 바탕 대비 3:1 이상.
   아이콘은 KRDS 원본(lib/krds)을 이 파일 기준 상대 경로로 빌린다 */
.ap-breadcrumb ol {
  display: flex; flex-wrap: wrap; align-items: center;
  margin: 0 0 var(--krds-gap-2); padding: 0; list-style: none;
  font-size: var(--krds-ui-fz-sub); color: var(--krds-gray-70);
}
.ap-breadcrumb li { display: inline-flex; align-items: center; min-width: 0; }
.ap-breadcrumb li + li::before {
  content: ""; flex: none; width: 1.6rem; height: 1.6rem;
  margin-inline: var(--krds-spacer-1);
  background-color: var(--krds-gray-60);
  -webkit-mask: url("../krds/1/icons/ico_bread_arr.svg") no-repeat center / contain;
  mask: url("../krds/1/icons/ico_bread_arr.svg") no-repeat center / contain;
}
.ap-breadcrumb .home > a::before, .ap-breadcrumb .home > span::before {
  content: ""; flex: none; width: 2rem; height: 2rem;
  margin-right: var(--krds-spacer-1);
  background-color: currentColor;
  -webkit-mask: url("../krds/1/icons/ico_bread_home.svg") no-repeat center / contain;
  mask: url("../krds/1/icons/ico_bread_home.svg") no-repeat center / contain;
}
.ap-breadcrumb a, .ap-breadcrumb span { display: inline-flex; align-items: center; padding-block: var(--krds-spacer-1); }
.ap-breadcrumb a {
  border-radius: var(--krds-rd-2);
  color: var(--krds-gray-80);
  text-decoration: underline; text-underline-offset: .3rem;
}
.ap-breadcrumb a:hover { color: var(--krds-primary); text-decoration-thickness: .2rem; }
.ap-breadcrumb a:active { color: var(--krds-primary-70); }
.ap-breadcrumb a:focus-visible { outline: .2rem solid var(--krds-primary); outline-offset: .2rem; }
.ap-breadcrumb [aria-current="page"] { color: var(--krds-gray-90); font-weight: 700; }

/* 고대비 모드 — 배경색으로 칠한 구분자·홈 아이콘과 그림자로 그린 선택 밑줄·두꺼운 테두리가 지워지므로
   아이콘은 시스템 색으로 다시 칠하고, 고른 탭·지금 단계는 글자 밑줄로 대신한다 */
@media (forced-colors: active) {
  .ap-breadcrumb li + li::before, .ap-breadcrumb .home > span::before {
    forced-color-adjust: none; background-color: CanvasText;
  }
  .ap-breadcrumb .home > a::before { forced-color-adjust: none; background-color: LinkText; }
  .ap-tab-links a[aria-current="page"], .ap-tab[aria-selected="true"],
  .ap-steps > [aria-current="step"] .step-tit { text-decoration: underline; }
}

/* ============================================================
   8. 부품 — 칩·툴팁·스위치·파일 업로드

   마크업은 templates/ai-platform/fragments.html 의 조각(chip·chipLink·chipDel·tooltip·
   formSwitch·fileUpload)이 그리고, 동작(툴팁 여닫기·파일 끌어다 놓기·올리기)은 ai-platform.js 의
   AP.tooltip·AP.upload 가 붙인다. 바깥 감싸개는 ap- 이름, 안쪽은 KRDS 표준 마크업 이름이다.
   고름·켜짐·오류는 색만이 아니라 체크 표시·굵기·손잡이 위치·아이콘과 문장으로 함께 알린다.
   누르는 자리는 모두 --krds-ui-h-sub 이상이다(조작 대상 크기). 윗변·왼쪽 변에 색 띠를 긋지 않는다.
   ============================================================ */

/* ── 칩 ── */
.ap-chips {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--krds-gap-2);
  margin: 0; padding: 0;
}
/* 테두리 gray-50 은 흰 바탕 대비 3:1 이상 — 경계가 보여야 누를 수 있는 것임을 안다 */
.ap-chip {
  display: inline-flex; align-items: center; gap: var(--krds-gap-1);
  min-height: var(--krds-ui-h-sub); padding-inline: var(--krds-gap-3);
  border: .1rem solid var(--krds-gray-50); border-radius: var(--ap-rd-pill);
  background: var(--krds-white); color: var(--krds-gray-80);
  font-size: var(--krds-ui-fz-sub); font-weight: 400; line-height: 1.4; white-space: nowrap;
  text-decoration: none; cursor: pointer;
  transition: background-color var(--krds-ease), border-color var(--krds-ease), color var(--krds-ease);
}
.ap-chip .ap-mask-ico.check { display: none; width: 1.6rem; height: 1.6rem; }
.ap-chip .chip-count { font-weight: 700; color: var(--krds-gray-70); font-variant-numeric: tabular-nums; }
/* 칩 링크는 본문 링크의 밑줄·글자색(a:hover)을 받지 않는다 — 칩 모양이 누를 수 있음을 대신 보인다 */
.ap-chip:hover { background: var(--krds-gray-5); color: var(--krds-gray-80); text-decoration: none; }
.ap-chip:active { background: var(--krds-gray-10); }
.ap-chip:focus-visible { outline: .2rem solid var(--krds-primary); outline-offset: .2rem; }
/* 고른 칩·지금 조건 — 테두리·채움에 체크 표시와 굵기를 더해 색만으로 알리지 않는다 */
.ap-chip[aria-pressed="true"], .ap-chip[aria-current="page"] {
  border-color: var(--krds-primary); background: var(--krds-primary-5);
  color: var(--krds-primary-60); font-weight: 700;
}
.ap-chip[aria-pressed="true"] .ap-mask-ico.check,
.ap-chip[aria-current="page"] .ap-mask-ico.check { display: inline-block; }
.ap-chip[aria-pressed="true"] .chip-count, .ap-chip[aria-current="page"] .chip-count { color: var(--krds-primary-60); }
.ap-chip[aria-pressed="true"]:hover, .ap-chip[aria-current="page"]:hover { background: var(--krds-primary-10); color: var(--krds-primary-60); }
.ap-chip[aria-pressed="true"]:active, .ap-chip[aria-current="page"]:active { background: var(--krds-primary-20); }
button.ap-chip:disabled, button.ap-chip:disabled:hover, button.ap-chip:disabled:active {
  border-color: var(--krds-gray-30); background: var(--krds-gray-10); color: var(--krds-gray-50); cursor: not-allowed;
}
button.ap-chip:disabled .chip-count { color: var(--krds-gray-50); }
/* 지울 수 있는 칩 — 칩 자체는 누르는 것이 아니고 안의 삭제 단추만 누른다 */
.ap-chip.is-input { gap: var(--krds-spacer-1); padding-inline-end: 0; cursor: default; }
.ap-chip.is-input:hover, .ap-chip.is-input:active { background: var(--krds-white); }
/* 삭제 단추는 칩 높이를 채운다 — 작은 X 만 누르게 하지 않는다 */
.ap-chip > .chip-del {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  min-width: calc(var(--krds-ui-h-sub) - .2rem); min-height: calc(var(--krds-ui-h-sub) - .2rem);
  padding: 0; border: 0; border-radius: var(--ap-rd-pill);
  background: transparent; color: var(--krds-gray-80); cursor: pointer;
  transition: background-color var(--krds-ease);
}
.ap-chip > .chip-del .ap-mask-ico { width: 1.6rem; height: 1.6rem; }
.ap-chip > .chip-del:hover { background: var(--krds-gray-10); }
.ap-chip > .chip-del:active { background: var(--krds-gray-20); }
/* 칩 테두리 안쪽에 긋는다 — 바깥에 그으면 칩 테두리와 겹쳐 흐려진다 */
.ap-chip > .chip-del:focus-visible { outline: .2rem solid var(--krds-primary); outline-offset: -.2rem; }

/* ── 툴팁(맥락적 도움말) ── */
.ap-tooltip { position: relative; display: inline-flex; vertical-align: middle; }
/* 투명 테두리는 고대비 모드에서 단추의 경계로 보인다 */
.ap-tooltip-btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: var(--krds-ui-h-sub); min-height: var(--krds-ui-h-sub); padding: 0;
  border: .1rem solid transparent; border-radius: var(--krds-ui-rd);
  background: transparent; cursor: pointer;
  transition: background-color var(--krds-ease);
}
.ap-tooltip-btn img { width: 2rem; height: 2rem; }
.ap-tooltip-btn:hover, .ap-tooltip-btn[aria-expanded="true"] { background: var(--krds-gray-10); }
.ap-tooltip-btn:active { background: var(--krds-gray-20); }
.ap-tooltip-btn:focus-visible { outline: .2rem solid var(--krds-primary); outline-offset: .2rem; }
/* 말풍선 — 단추 아래에 왼쪽을 맞춰 열고, 화면 밖으로 넘치면 스크립트가 옆(--ap-tooltip-x)·위(.is-top)로 옮긴다.
   오른쪽 여백은 닫기 단추 자리다. 헤더(z-index 100)보다 낮게 둔다 */
.ap-tooltip-in {
  position: absolute; top: calc(100% + var(--krds-gap-1)); left: 0; z-index: 50;
  width: max-content; max-width: min(32rem, calc(100vw - 2 * var(--krds-gap-4)));
  padding: var(--krds-gap-3) calc(var(--krds-ui-h-sub) + var(--krds-gap-1)) var(--krds-gap-3) var(--krds-gap-3);
  border: .1rem solid var(--krds-gray-30); border-radius: var(--krds-rd-8);
  background: var(--krds-white); color: var(--krds-gray-80);
  font-size: var(--krds-ui-fz-sub); font-weight: 400; line-height: 1.6; white-space: normal; text-align: left;
  box-shadow: var(--krds-shadow-md);
  transform: translateX(var(--ap-tooltip-x, 0));
}
.ap-tooltip.is-top .ap-tooltip-in { top: auto; bottom: calc(100% + var(--krds-gap-1)); }
.ap-tooltip-in:focus-visible { outline: .2rem solid var(--krds-primary); outline-offset: .2rem; }
.ap-tooltip-in .tool-tit { margin: 0 0 var(--krds-gap-1); font-weight: 700; color: var(--krds-gray-90); }
.ap-tooltip-in .tool-cnt > * + * { margin-top: var(--krds-gap-2); }
.ap-tooltip-in .tool-close {
  position: absolute; top: var(--krds-gap-1); right: var(--krds-gap-1);
  display: inline-flex; align-items: center; justify-content: center;
  min-width: var(--krds-ui-h-sub); min-height: var(--krds-ui-h-sub); padding: 0;
  border: 0; border-radius: var(--krds-ui-rd);
  background: transparent; color: var(--krds-gray-80); cursor: pointer;
}
.ap-tooltip-in .tool-close:hover { background: var(--krds-gray-10); }
.ap-tooltip-in .tool-close:active { background: var(--krds-gray-20); }
.ap-tooltip-in .tool-close:focus-visible { outline: .2rem solid var(--krds-primary); outline-offset: -.2rem; }

/* ── 스위치 ── */
/* 보이는 트랙 위에 같은 크기의 native 체크박스를 겹친다 — 누르기·초점 윤곽선이 트랙 자리에 맞고,
   낭독기·키보드는 native 그대로 쓴다. 칸을 display·visibility·opacity 로 숨기면 초점이 사라진다 */
.ap-switch {
  position: relative; display: inline-flex; align-items: center; gap: var(--krds-gap-2);
  min-height: var(--krds-ui-h-sub);
}
.ap-switch .switch-input {
  position: absolute; left: 0; top: 50%; z-index: 1;
  width: var(--krds-switch-w-lg); height: var(--krds-switch-h-lg); margin: 0;
  transform: translateY(-50%);
  -webkit-appearance: none; appearance: none;
  border: 0; border-radius: var(--krds-switch-rd-lg);
  background: transparent; cursor: pointer;
}
/* 트랙 gray-60 은 흰 바탕 대비 4.5:1 이상 — 꺼진 스위치도 경계가 보인다 */
.ap-switch .switch-track {
  position: relative; flex: none;
  width: var(--krds-switch-w-lg); height: var(--krds-switch-h-lg);
  border-radius: var(--krds-switch-rd-lg);
  background: var(--krds-gray-60);
  transition: background-color var(--krds-ease);
}
.ap-switch .switch-track::after {
  content: ""; position: absolute;
  top: calc((var(--krds-switch-h-lg) - var(--krds-switch-b-lg)) / 2);
  left: calc((var(--krds-switch-h-lg) - var(--krds-switch-b-lg)) / 2);
  width: var(--krds-switch-b-lg); height: var(--krds-switch-b-lg);
  border-radius: var(--krds-rd-full);
  background: var(--krds-white);
  transition: transform var(--krds-ease);
}
/* 켜짐 — 색에 더해 손잡이가 오른쪽으로 간다 */
.ap-switch .switch-input:checked + .switch-track { background: var(--krds-primary); }
.ap-switch .switch-input:checked + .switch-track::after {
  transform: translateX(calc(var(--krds-switch-w-lg) - var(--krds-switch-h-lg)));
}
.ap-switch:hover .switch-input:not(:disabled) + .switch-track { background: var(--krds-gray-70); }
.ap-switch:hover .switch-input:checked:not(:disabled) + .switch-track { background: var(--krds-primary-60); }
.ap-switch .switch-input:active:not(:disabled) + .switch-track { background: var(--krds-gray-80); }
.ap-switch .switch-input:checked:active:not(:disabled) + .switch-track { background: var(--krds-primary-70); }
.ap-switch .switch-input:focus-visible { outline: .2rem solid var(--krds-primary); outline-offset: .2rem; }
.ap-switch .switch-input:disabled { cursor: not-allowed; }
.ap-switch .switch-input:disabled + .switch-track { background: var(--krds-gray-20); }
.ap-switch .switch-input:disabled + .switch-track::after { background: var(--krds-gray-5); }
/* 옛 .ap-form label(블록·아래 여백)보다 특이도를 높여 트랙 옆 한 줄로 둔다 */
.ap-switch > label, .ap-form .ap-switch > label {
  display: inline; margin: 0;
  font-size: var(--krds-ui-fz); font-weight: 400; color: var(--krds-gray-90); cursor: pointer;
}
.ap-switch .switch-input:disabled ~ label, .ap-form .ap-switch .switch-input:disabled ~ label {
  color: var(--krds-gray-50); cursor: not-allowed;
}

/* ── 파일 업로드 ── */
.ap-upload { position: relative; }
.ap-upload > .form-hint { margin: 0 0 var(--krds-gap-2); }
/* 끌어다 놓는 칸 — 점선은 '여기에 놓을 수 있음' 을, 끌고 있는 동안의 실선·채움은 '놓으면 들어감' 을 보인다 */
.ap-upload-drop {
  position: relative;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: var(--krds-gap-2) var(--krds-gap-3);
  padding: var(--krds-gap-4);
  border: .1rem dashed var(--krds-gray-50); border-radius: var(--krds-rd-8);
  background: var(--krds-gray-5); text-align: center;
  transition: background-color var(--krds-ease), border-color var(--krds-ease);
}
.ap-upload-drop.is-dragover { border-style: solid; border-color: var(--krds-primary); background: var(--krds-primary-5); }
.ap-upload-txt { flex-basis: 100%; margin: 0; font-size: var(--krds-ui-fz-sub); color: var(--krds-gray-70); }
/* 파일 칸은 시각적으로만 숨긴다 — 초점·낭독기·키보드 고르기는 남아야 한다 */
.ap-upload .ap-upload-input {
  position: absolute; width: .1rem; height: .1rem; padding: 0; margin: -.1rem;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
/* '파일 선택' 은 파일 칸의 label 이다. 모양·hover·눌림은 .btn.secondary 를 받고, 옛 .ap-form label 보다 특이도를 높인다 */
.ap-upload .ap-upload-btn, .ap-form .ap-upload .ap-upload-btn { display: inline-flex; margin: 0; cursor: pointer; }
.ap-upload-btn .ap-mask-ico { width: 2rem; height: 2rem; }
/* 숨긴 칸의 초점을 보이는 단추에 옮겨 그린다 */
.ap-upload-input:focus-visible + .ap-upload-btn { outline: .2rem solid var(--krds-primary); outline-offset: .2rem; }
.ap-upload .ap-upload-input:disabled + .ap-upload-btn {
  border-color: transparent; background: var(--krds-gray-20); color: var(--krds-gray-50); cursor: not-allowed;
}
/* 오류 — 칸 테두리를 실선 위험색으로 바꾼다. 아이콘과 문장은 .form-hint-invalid 가 그린다 */
.ap-upload .form-conts.is-error .ap-upload-drop { border-style: solid; border-color: var(--krds-danger); }
.ap-upload-bar { display: block; width: 100%; height: .8rem; margin-top: var(--krds-gap-2); accent-color: var(--krds-primary); }
/* 진행 상태 문단은 비어 있어도 숨기지 않는다 — 문서에 남아 있어야 바뀐 글을 낭독기가 읽는다 */
.ap-upload-status { margin: var(--krds-gap-2) 0 0; font-size: var(--krds-ui-fz-sub); color: var(--krds-gray-70); }
.ap-upload-status:empty, .ap-upload-list:empty { margin: 0; }
/* 오류 중에는 진행 상태가 오류 문장을 낭독기에 한 번 더 읽어 주는 자리다 — 눈에는 한 번만 보이게 시각적으로만 숨긴다 */
.ap-upload .form-conts.is-error ~ .ap-upload-status {
  position: absolute; width: .1rem; height: .1rem; padding: 0; margin: -.1rem;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
.ap-upload-list { margin: var(--krds-gap-2) 0 0; padding: 0; list-style: none; }
.ap-upload-list > li {
  display: flex; align-items: center; gap: var(--krds-gap-2);
  padding: var(--krds-gap-2) 0;
  border-bottom: .1rem solid var(--krds-gray-20);
}
/* 파일 이름은 한 줄 — 넘치면 말줄임, 전체 이름은 title 로 */
.ap-upload-name {
  flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--krds-gray-90);
}
.ap-upload-meta { flex: none; font-size: var(--krds-fz-detail-sm); color: var(--krds-gray-60); }
.ap-upload-state {
  flex: none; display: inline-flex; align-items: center; gap: var(--krds-spacer-1);
  font-size: var(--krds-ui-fz-sub); color: var(--krds-gray-70);
}
.ap-upload-state img { width: 1.8rem; height: 1.8rem; }
.ap-upload-list > li.is-error .ap-upload-state { color: var(--krds-danger-70); }
.ap-upload-list > li.is-done .ap-upload-state { color: var(--krds-success-70); }
.ap-upload-del .ap-mask-ico { width: 1.6rem; height: 1.6rem; }

/* 고대비 모드 — 바탕색으로 칠한 트랙·손잡이가 지워지므로 시스템 색으로 다시 칠하고,
   고른 칩·지금 조건은 글자 밑줄로도 알린다. 칩·단추 아이콘(.ap-mask-ico)은 6절이 다시 칠한다 */
@media (forced-colors: active) {
  .ap-switch .switch-track,
  .ap-switch:hover .switch-input:not(:disabled) + .switch-track,
  .ap-switch .switch-input:active:not(:disabled) + .switch-track {
    forced-color-adjust: none; background: Canvas; border: .1rem solid CanvasText;
  }
  .ap-switch .switch-track::after { forced-color-adjust: none; background: CanvasText; }
  .ap-switch .switch-input:checked + .switch-track,
  .ap-switch:hover .switch-input:checked:not(:disabled) + .switch-track,
  .ap-switch .switch-input:checked:active:not(:disabled) + .switch-track { background: Highlight; border-color: Highlight; }
  .ap-switch .switch-input:checked + .switch-track::after { background: HighlightText; }
  .ap-switch .switch-input:disabled + .switch-track { background: Canvas; border-color: GrayText; }
  .ap-switch .switch-input:disabled + .switch-track::after { background: GrayText; }
  .ap-chip[aria-pressed="true"], .ap-chip[aria-current="page"] { text-decoration: underline; }
}

/* ============================================================
   9. 로그인 만료 안내

   마크업은 templates/ai-platform/fragments.html 의 조각 sessionNotice 를 레이아웃이 그리고,
   동작(여닫기·남은 시간·연장)은 ai-platform.js 의 AP.session 이 붙인다. 창·단추·오류 줄은
   7절 모달·.btn·.form-hint-invalid 를 그대로 따른다. 남은 시간은 굵기·크기로 강조하고 색 띠를 쓰지 않는다.
   ============================================================ */

/* 짧은 안내 창 — 문장이 한 줄로 길게 늘어지지 않게 기본 모달보다 좁힌다(KRDS 모달 크기) */
.ap-session-modal { width: min(48rem, calc(100vw - 2 * var(--krds-gap-4))); }
.ap-session-time { color: var(--krds-gray-80); }
/* 1초마다 바뀌는 숫자 — 글자 폭이 고정이라 줄이 흔들리지 않는다 */
.ap-session-left {
  font-size: var(--krds-ui-fz-sect); font-weight: 700; color: var(--krds-gray-90);
  font-variant-numeric: tabular-nums;
}