
  /* =================================================================
     색상 / 여백 등 공통 값 정의
     ------------------------------------------------------------
     :root 안에 넣어두면 --변수이름 형태로 어디서든 재사용할 수 있어요.
     예를 들어 빨간색을 바꾸고 싶으면 --cr-red 값 하나만 고치면
     로고, 버튼, 테두리 등 이 색을 쓰는 모든 곳이 한 번에 바뀝니다.
     ================================================================= */
  :root{
    --cr-red: #c8102e;       /* 조선내화 브랜드 레드 (제목 바, 버튼 등) */
    --cr-red-dark: #9c0c22;  /* 위 빨간색보다 어두운 톤 (hover 시 사용) */
    --ink: #1c1c1c;          /* 기본 글자색 (거의 검정) */
    --table-head: #3a3a3a;   /* Other Properties 표 헤더용 - 순검정보다 살짝 밝은 흑색 */
    --line: #d8d8d8;         /* 테두리선 색 */
    --paper: #ffffff;        /* 카드/문서 배경색 (흰색) */
    --band: #f4f4f4;         /* 표의 옅은 회색 줄무늬 배경 */
    --spec: #fdecec;         /* 연한 빨간 배경 (hover, 강조용) */
    --muted: #6b6b6b;        /* 부가 설명 글자색 (회색) */
    --ok: #1c7c4c;           /* 성공/완료 상태를 나타내는 녹색 */
  }

  /* 모든 요소의 박스 크기 계산 방식을 통일합니다.
     (padding, border를 width/height 안쪽에 포함해서 계산 → 레이아웃이 안 깨짐) */
  *{
    box-sizing: border-box;
  }

  body{
    margin: 0;
    font-family: 'Pretendard','Segoe UI',Arial,sans-serif;
    background: #e9e9e9;   /* 페이지 전체의 회색 배경 (카드가 도드라져 보이게) */
    color: var(--ink);
  }

  /* 전체 컨텐츠를 가운데 정렬하고 최대 너비를 제한하는 바깥 컨테이너 */
  .app{
    max-width: 1100px;
    margin: 0 auto;
    padding: 28px 20px 60px;
  }

  /* ---------------- 상단 로고/타이틀 영역 ---------------- */
  .masthead{
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 18px;
    flex-wrap: wrap;
    gap: 10px;
  }

  /* 내비게이션 바 - TDS 조회 / 재질 비교 / 재질 추가 전환용 탭.
     실제 화면 전환은 JS가 .view-pane에 active 클래스를 붙였다 뗐다 하는
     것으로 처리하고(페이지 이동 없음), 여기 탭은 그 트리거일 뿐입니다. */
  .nav-bar{
    display: flex;
    gap: 6px;
    margin-bottom: 18px;
    border-bottom: 1px solid var(--line);
  }
  .nav-tab{
    background: transparent;
    border: none;
    border-bottom: 2px solid transparent;
    padding: 10px 18px;
    font-size: 14px;
    font-weight: 700;
    color: var(--muted);
    cursor: pointer;
    margin-bottom: -1px;   /* .nav-bar의 border-bottom과 탭의 활성 밑줄이 겹치도록 */
  }
  .nav-tab:hover{
    color: var(--ink);
  }
  .nav-tab.active{
    color: var(--cr-red);
    border-bottom-color: var(--cr-red);
  }

  /* 화면 전환 - active가 없는 view-pane은 아예 렌더링 안 함(display:none),
     그래서 다른 화면의 요소 id가 겹쳐도 서로 간섭하지 않습니다. */
  .view-pane{
    display: none;
  }
  .view-pane.active{
    display: block;
  }

  .brand{
    display: flex;
    align-items: center;
    gap: 10px;
  }
  .brand .mark{
    width: 38px;
    height: 38px;
    border-radius: 50%;         /* 동그란 배지 모양 */
    background: var(--cr-red);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 800;
    font-size: 16px;
    flex-shrink: 0;              /* 화면이 좁아져도 찌그러들지 않게 */
    cursor: pointer;             /* 클릭하면 처음 화면으로 (홈 버튼) */
    transition: transform .12s ease, box-shadow .12s ease;
  }
  .brand .mark:hover{
    box-shadow: 0 2px 8px rgba(200,16,46,.35);
    transform: translateY(-1px);
  }
  .brand .mark:active{
    transform: translateY(0);
  }
  .brand .name{
    font-weight: 700;
    font-size: 16px;
    letter-spacing: .2px;
  }
  .brand .name small{
    display: block;
    font-weight: 400;
    color: var(--muted);
    font-size: 12px;
  }

  /* ---------------- 엑셀 업로드 영역 (드래그앤드롭 박스) ---------------- */
  /* 우측 상단의 작은 CSV 업로드 아이콘 버튼 - 자동 로드가 기본이라
     평소엔 안 쓰이고, 가끔 다른 CSV를 대신 보고 싶을 때만 누르는 보조 기능 */
  .upload-icon-btn{
    width: 38px;
    height: 38px;
    border-radius: 8px;
    background: var(--band);
    border: 1px solid var(--line);
    font-size: 17px;
    line-height: 1;
    cursor: pointer;
    flex-shrink: 0;
  }
  .upload-icon-btn:hover{
    background: var(--spec);
    border-color: var(--cr-red);
  }
  /* 실제 <input type=file>은 못생겨서 숨기고, 위의 아이콘 버튼으로 대신 클릭시킵니다 */
  #fileInput{
    display: none;
  }

  /* data/data.csv 자동 로드가 실패했을 때만(파일 없음 등) 보이는 안내 배너 */
  /* 사용자 지정 CSV를 보고 있을 때만 나타나는 상시 뱃지 */
  .user-data-badge{
    background: var(--spec);
    border: 1px solid var(--cr-red);
    border-radius: 8px;
    padding: 10px 14px;
    margin-bottom: 18px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    font-size: 13px;
    color: var(--cr-red-dark);
    font-weight: 600;
  }
  .user-data-badge button{
    background: #fff;
    color: var(--cr-red-dark);
    border: 1px solid var(--cr-red);
    padding: 6px 12px;
    border-radius: 6px;
    font-size: 13px;
    font-weight: 700;
    cursor: pointer;
    flex-shrink: 0;
  }
  .user-data-badge button:hover{
    background: var(--cr-red);
    color: #fff;
  }

  .uploader-fallback{
    background: var(--paper);
    border: 1px dashed var(--line);
    border-radius: 8px;
    padding: 16px;
    margin-bottom: 18px;
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
  }
  .uploader-fallback .icon{
    width: 38px;
    height: 38px;
    border-radius: 8px;
    background: var(--band);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 19px;
    flex-shrink: 0;
  }
  .uploader-fallback .text{
    font-size: 14px;
    color: var(--muted);
    flex: 1;
    min-width: 180px;
    line-height: 1.6;
  }
  .uploader-fallback .text b{
    color: var(--ink);
  }

  /* ---------------- 재질 추가 화면 ---------------- */
  .add-material-intro{
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 14px 16px;
    margin-bottom: 18px;
    font-size: 13px;
    color: var(--muted);
    line-height: 1.7;
  }
  .add-material-intro code{
    background: var(--band);
    padding: 1px 5px;
    border-radius: 4px;
    font-size: 12px;
  }
  .add-material-intro b{
    color: var(--ink);
  }

  /* 특수 필드(formulation/product_name/카테고리 등) 입력 영역 */
  .am-special-fields{
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 12px;
    background: #fff;
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 16px;
    margin-bottom: 16px;
  }
  .am-field{
    display: flex;
    flex-direction: column;
    gap: 4px;
  }
  .am-field label{
    font-size: 12.5px;
    font-weight: 700;
    color: var(--muted);
  }
  .am-field.required label::after{
    content: " *";
    color: var(--cr-red);
  }
  .am-field input,
  .am-field select{
    border: 1px solid var(--line);
    border-radius: 6px;
    padding: 7px 10px;
    font-size: 13.5px;
    font-family: inherit;
  }
  .am-field input:focus,
  .am-field select:focus{
    outline: none;
    border-color: var(--cr-red);
  }
  /* formulation 입력값이 기존/이미 추가한 재질과 중복될 때 실시간으로 표시 */
  .am-field input.am-duplicate{
    border-color: var(--cr-red);
    background: var(--spec);
  }
  .am-field-hint{
    font-size: 11.5px;
    color: var(--cr-red-dark);
    display: none;
  }
  .am-field-hint.show{
    display: block;
  }

  /* General/Other Properties - "표시 항목 선택" 패널과 비슷한 톤의
     그룹 카드로 표시. 항목이 175개나 되니 접었다 펼 수 있게 합니다. */
  .am-group{
    background: #fff;
    border: 1px solid var(--line);
    border-radius: 8px;
    margin-bottom: 10px;
    overflow: hidden;
  }
  .am-group-head{
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    background: var(--band);
    border: none;
    padding: 10px 16px;
    font-size: 13.5px;
    font-weight: 700;
    color: var(--ink);
    cursor: pointer;
    text-align: left;
  }
  .am-group-head .am-group-arrow{
    font-size: 11px;
    color: var(--muted);
    transition: transform .15s ease;
  }
  .am-group.collapsed .am-group-arrow{
    transform: rotate(-90deg);
  }
  .am-group-body{
    padding: 14px 16px;
  }
  .am-group.collapsed .am-group-body{
    display: none;
  }
  /* General Properties 그룹만 값 하나짜리라 그리드로, Other Properties
     그룹들은 항목별로 값/Min/Max 세 칸짜리 표라서 별도 레이아웃(.am-prop-row) 사용 */
  .am-general-grid{
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 12px;
  }
  .am-prop-row{
    display: grid;
    grid-template-columns: 140px 1fr 90px 90px 90px;
    align-items: center;
    gap: 8px;
    padding: 5px 0;
    border-bottom: 1px solid var(--line);
  }
  .am-prop-row:last-child{
    border-bottom: none;
  }
  .am-prop-row .am-prop-item-label{
    font-size: 12.5px;
    color: var(--muted);
  }
  .am-prop-row input[type="text"]{
    border: 1px solid var(--line);
    border-radius: 5px;
    padding: 5px 8px;
    font-size: 13px;
    font-family: inherit;
    width: 100%;
  }
  .am-prop-row input[type="text"]:focus{
    outline: none;
    border-color: var(--cr-red);
  }
  .am-prop-col-label{
    font-size: 10.5px;
    color: var(--muted);
    text-align: center;
  }
  /* water_cooling 항목처럼 modifier(이하 < 표시) 체크박스가 붙는 경우 */
  .am-prop-modifier{
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: 11px;
    color: var(--muted);
    white-space: nowrap;
  }

  .add-material-actions{
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 12px;
    margin: 16px 0 24px;
  }
  .add-material-error{
    font-size: 13px;
    color: var(--cr-red-dark);
    font-weight: 600;
  }
  .add-material-add-btn{
    background: var(--cr-red);
    color: #fff;
    border: none;
    padding: 10px 22px;
    border-radius: 6px;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
  }
  .add-material-add-btn:hover{
    background: var(--ink);
  }

  .add-material-staged{
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 16px;
  }
  .add-material-staged-head{
    font-size: 14px;
    margin-bottom: 10px;
  }
  .am-staged-row{
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    background: #fff;
    border: 1px solid var(--line);
    border-radius: 6px;
    padding: 8px 12px;
    margin-bottom: 6px;
    font-size: 13px;
  }
  .am-staged-row .am-staged-name{
    font-weight: 700;
    color: var(--ink);
  }
  .am-staged-row .am-staged-formulation{
    color: var(--muted);
    font-size: 12px;
  }
  .am-staged-remove-btn{
    background: transparent;
    border: 1px solid var(--line);
    border-radius: 5px;
    padding: 4px 10px;
    font-size: 12px;
    color: var(--cr-red-dark);
    cursor: pointer;
    flex-shrink: 0;
  }
  .am-staged-remove-btn:hover{
    background: var(--spec);
  }
  .add-material-download-btn{
    width: 100%;
    background: var(--ink);
    color: #fff;
    border: none;
    padding: 12px;
    border-radius: 6px;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
    margin-top: 10px;
  }
  .add-material-download-btn:hover{
    background: var(--cr-red);
  }

  /* ---------------- 상단 툴바 (재질 선택 드롭다운 + 검색창 + 항목선택 버튼) ---------------- */
  .toolbar{
    display: none;   /* 엑셀을 업로드하기 전에는 숨김, 업로드되면 JS가 flex로 바꿔줌 */
    gap: 10px;
    align-items: flex-start;
    flex-wrap: wrap;
    margin-bottom: 12px;
    background: var(--paper);
    border: 1px solid var(--line);
    padding: 12px 14px;
    border-radius: 8px;
  }
  .tb-group{
    display: flex;
    flex-direction: column;
    gap: 4px;
  }
  .tb-group label{
    font-size: 12.5px;
    color: var(--muted);
    font-weight: 600;
  }
  select{
    font-family: inherit;
    padding: 7px 10px;
    border: 1px solid var(--line);
    border-radius: 6px;
    font-size: 14px;
    background: #fff;
    min-width: 220px;
  }

  /* ---------------- 재질명 검색창 + 실시간 미리보기 드롭다운 ---------------- */
  .search-wrap{
    position: relative;   /* 아래 .search-preview를 이 요소 기준으로 절대배치하기 위함 */
  }
  #searchInput{
    font-family: inherit;
    padding: 7px 30px 7px 10px;
    border: 1px solid var(--line);
    border-radius: 6px;
    font-size: 14px;
    width: 240px;
  }
  #searchInput:focus{
    outline: none;
    border-color: var(--cr-red);
  }
  .search-icon{
    position: absolute;
    right: 9px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 14px;
    color: var(--muted);
    pointer-events: none;  /* 돋보기 아이콘 클릭이 뒤의 입력창으로 그대로 전달되게 */
  }
  /* 타이핑할 때마다 아래로 펼쳐지는 검색 결과 목록 */
  .search-preview{
    position: absolute;
    top: 100%;
    left: 0;
    margin-top: 4px;
    width: 360px;
    max-height: 340px;
    overflow-y: auto;
    background: #fff;
    border: 1px solid var(--line);
    border-radius: 8px;
    box-shadow: 0 6px 18px rgba(0,0,0,.12);
    z-index: 150;   /* .sheet-top(51)보다 훨씬 위로 - 검색창 아래 카드와 겹쳐도 클릭이 항상 드롭다운으로 가도록 */
    display: none;   /* JS가 검색어 있을 때 open 클래스를 붙여서 보여줌 */
  }
  .search-preview.open{
    display: block;
  }
  .search-item{
    padding: 8px 10px;
    cursor: pointer;
    border-bottom: 1px solid var(--band);
    font-size: 13.8px;
    display: flex;
    align-items: center;
    gap: 8px;
  }
  .search-item:last-child{
    border-bottom: none;
  }
  .search-item:hover,
  .search-item.active{
    background: var(--spec);
  }
  .search-item .si-main{
    flex: 1;
    min-width: 0;
    cursor: pointer;
  }
  .search-item .sn{
    font-weight: 700;   /* 재질명(제품명) */
  }
  .search-item .si-formulation{
    font-weight: 400;
    font-size: 12px;
    color: var(--muted);
  }
  .search-item .st{
    color: var(--muted);
    font-size: 12.3px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;  /* 너무 길면 "..." 으로 잘라줌 */
    display: block;
  }
  .search-empty{
    padding: 14px;
    font-size: 13.5px;
    color: var(--muted);
    text-align: center;
  }
  /* 검색 결과 목록 맨 위에 붙는, "전체 추가/전체 해제" 일괄 처리 바 */
  .search-bulk-bar{
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 12px;
    background: var(--band);
    border-bottom: 1px solid var(--line);
    font-size: 11.5px;
    color: var(--muted);
    font-weight: 600;
    position: sticky;
    top: 0;
    z-index: 1;
  }
  .search-bulk-actions{
    display: flex;
    gap: 10px;
  }
  .search-bulk-actions button{
    border: none;
    background: transparent;
    color: var(--cr-red);
    font-size: 11.5px;
    font-weight: 700;
    cursor: pointer;
    text-decoration: underline;
    padding: 0;
  }
  /* 검색어와 일치하는 부분을 노란색으로 하이라이트할 때 쓰는 <mark> 태그 스타일 */
  mark{
    background: #ffe08a;
    border-radius: 2px;
    padding: 0 1px;
  }
  /* "+ 보고서에 추가" / "✓ 보고서에 있음" 작은 버튼 */
  .add-chip-btn{
    flex-shrink: 0;
    border: 1px solid var(--line);
    background: #fff;
    border-radius: 5px;
    font-size: 12px;
    padding: 4px 8px;
    cursor: pointer;
    color: var(--ink);
    font-weight: 600;
  }
  .add-chip-btn:hover{
    border-color: var(--cr-red);
    color: var(--cr-red);
  }
  /* 이미 보고서에 담겨 있으면 초록색으로 표시 */
  .add-chip-btn.added{
    background: var(--ok);
    border-color: var(--ok);
    color: #fff;
  }

  /* ---------------- "표시 항목 선택" 버튼 & 패널 ---------------- */
  .fields-btn{
    background: #fff;
    border: 1px solid var(--line);
    border-radius: 6px;
    padding: 8px 14px;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    align-self: flex-end;
  }
  .fields-btn:hover{
    border-color: var(--cr-red);
    color: var(--cr-red);
  }
  .fields-btn.active{
    background: var(--ink);
    color: #fff;
    border-color: var(--ink);
  }

  /* 체크박스들이 펼쳐지는 패널 (General/Other Properties 항목 선택) */
  .fields-panel{
    display: none;   /* fields-btn 클릭 시 JS가 open 클래스 토글 */
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 16px 18px;
    margin-bottom: 20px;
  }
  /* 표시 항목 선택 패널 하단의 적용/확인 버튼 - fieldsPanel과 별개 요소라
     패널 내용이 다시 그려져도(buildFieldsPanelInto) 안 사라집니다. */
  .fields-panel-footer{
    display: none;   /* fieldsBtn 클릭 시 JS가 fieldsPanel과 함께 보임/숨김 전환 */
    align-items: center;
    gap: 10px;
    margin-top: -12px;
    margin-bottom: 20px;
    padding: 12px 18px;
    background: var(--paper);
    border: 1px solid var(--line);
    border-top: none;
    border-radius: 0 0 8px 8px;
  }
  /* X(닫기) 버튼은 왼쪽에, 적용/확인은 오른쪽에 - 이 spacer가 가운데
     남는 공간을 다 차지해서 둘을 양 끝으로 밀어냅니다. */
  .fields-footer-spacer{
    flex: 1;
  }
  .fields-close-btn{
    border: none;
    background: transparent;
    color: var(--muted);
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
    padding: 4px 8px;
    border-radius: 6px;
  }
  .fields-close-btn:hover{
    background: var(--band-soft, #ececec);
    color: var(--ink);
  }
  .fields-apply-btn,
  .fields-confirm-btn{
    border: 1px solid var(--line);
    background: #fff;
    border-radius: 6px;
    padding: 8px 18px;
    font-size: 13px;
    font-weight: 700;
    cursor: pointer;
  }
  .fields-confirm-btn{
    background: var(--cr-red);
    border-color: var(--cr-red);
    color: #fff;
  }
  .fields-apply-btn:hover{
    border-color: var(--cr-red);
    color: var(--cr-red);
  }
  .fields-confirm-btn:hover{
    background: var(--cr-red-dark);
    border-color: var(--cr-red-dark);
  }
  .fields-panel.open{
    display: block;
  }
  .fp-quick{
    display: flex;
    gap: 6px;
  }
  .fp-quick button{
    font-size: 12px;
    border: 1px solid var(--line);
    background: #fff;
    border-radius: 5px;
    padding: 3px 9px;
    cursor: pointer;
    color: var(--muted);
  }
  .fp-quick button:hover{
    border-color: var(--cr-red);
    color: var(--cr-red);
  }
  .fp-section{
    margin-bottom: 16px;
  }
  .fp-section:last-child{
    margin-bottom: 0;
  }
  .fp-section-title{
    font-size: 13px;
    font-weight: 700;
    color: var(--cr-red-dark);
    text-transform: uppercase;
    letter-spacing: .3px;
    margin-bottom: 8px;
    border-bottom: 1px solid var(--line);
    padding-bottom: 5px;
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  .fp-chips{
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
  }
  /* 체크박스 + 라벨을 알약(pill) 모양으로 감싼 항목 하나 */
  .fp-chk{
    display: inline-flex;
    align-items: center;
    gap: 5px;
    border: 1px solid var(--line);
    border-radius: 6px;
    padding: 4px 9px 4px 7px;
    font-size: 13px;
    cursor: pointer;
    user-select: none;   /* 클릭할 때 글자가 드래그 선택되는 것 방지 */
    background: #fafafa;
  }
  .fp-chk input{
    margin: 0;
    accent-color: var(--cr-red);  /* 체크박스 자체의 색상을 브랜드색으로 */
    cursor: pointer;
  }
  .fp-chk.checked{
    background: #fff;
    border-color: #c9c9c9;
  }
  .fp-group{
    margin-bottom: 10px;
  }
  .fp-group-head{
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 13.3px;
    font-weight: 700;
    margin-bottom: 6px;
    cursor: pointer;
  }
  .fp-group-head input{
    accent-color: var(--cr-red);
  }
  .fp-group-unit{
    font-weight: 400;
    color: var(--muted);
    font-size: 12px;
  }
  .fp-group-items{
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    padding-left: 20px;
  }

  /* =================================================================
     보고서(report) 관련 UI
     - 사용자가 "보고서에 추가"한 재질들의 목록/설정을 담는 패널입니다.
     ================================================================= */
  .report-panel{
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 14px 16px;
    margin-bottom: 20px;
    display: none;   /* 보고서에 담긴 재질이 1개 이상일 때만 JS가 보여줌 */
  }
  .report-panel.has-items{
    display: block;
  }
  .report-panel-head{
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 10px;
  }
  .report-panel-head .rp-title{
    font-size: 14px;
    font-weight: 700;
  }
  /* rp-title이 이제 버튼(접기/펼치기)이기도 해서 기본 버튼 스타일을 지웁니다 */
  .rp-title-toggle{
    display: flex;
    align-items: center;
    gap: 6px;
    border: none;
    background: transparent;
    padding: 0;
    cursor: pointer;
    color: var(--ink);
  }
  .rp-toggle-arrow{
    display: inline-block;
    font-size: 11px;
    color: var(--muted);
    transition: transform .15s ease;
  }
  .rp-title-toggle.collapsed .rp-toggle-arrow{
    transform: rotate(-90deg);   /* 접혔을 때 화살표가 옆을 향하게 */
  }
  .report-panel-head .rp-title .count{
    color: var(--cr-red);
  }
  .rp-list{
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-bottom: 14px;
  }
  /* 접힌 상태 - 재질이 많아서 스크롤이 길어질 때 목록 전체를 숨깁니다.
     기본값은 펼침(이 클래스가 안 붙어있는 상태)입니다. */
  .rp-list.rp-list-collapsed{
    display: none;
  }

  /* 카테고리별 그룹화 켜기/끄기 체크박스 + 그룹 순서 조절 칩 */
  .rp-group-controls{
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 10px;
  }
  .rp-group-toggle{
    display: flex;
    align-items: center;
    gap: 7px;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--ink);
    cursor: pointer;
    user-select: none;
  }
  .rp-group-toggle input{
    accent-color: var(--cr-red);
    cursor: pointer;
  }
  .group-order-wrap{
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
  }
  .group-order-chip{
    display: inline-flex;
    align-items: center;
    gap: 4px;
    background: #fff;
    border: 1px solid var(--line);
    border-radius: 999px;
    padding: 4px 6px 4px 12px;
    font-size: 12px;
    font-weight: 700;
    color: var(--ink);
  }
  .group-order-chip button{
    border: none;
    background: var(--band);
    color: var(--muted);
    width: 20px;
    height: 20px;
    border-radius: 50%;
    font-size: 10px;
    cursor: pointer;
    line-height: 1;
  }
  .group-order-chip button:hover:not(:disabled){
    background: var(--cr-red);
    color: #fff;
  }
  .group-order-chip button:disabled{
    opacity: .3;
    cursor: not-allowed;
  }

  /* 보고서 목록 안에서 카테고리 구분선 (그룹화 켜져있을 때만 나타남) */
  .rp-group-header{
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    font-size: 11.5px;
    font-weight: 800;
    color: var(--cr-red);
    text-transform: uppercase;
    letter-spacing: .4px;
    padding: 10px 2px 2px;
    border-top: 1px dashed var(--line);
    margin-top: 4px;
  }
  .rp-group-header:first-child{
    border-top: none;
    margin-top: 0;
    padding-top: 0;
  }

  /* 보고서 목록에 있는 재질 한 줄 (이름 + 항목선택 버튼 + 제거 버튼) */
  .rp-row{
    display: flex;
    align-items: center;
    flex-wrap: wrap;   /* 요소가 많아져서 좁은 화면에 다 안 들어가면 줄바꿈되게 (숨거나 안 보이는 대신) */
    gap: 8px;
    border: 1px solid var(--line);
    border-radius: 6px;
    padding: 7px 10px;
    background: #fafafa;
    transition: opacity .15s ease, border-color .15s ease;
  }
  /* "이번엔 제외" 체크를 끈 재질 - 목록엔 남아있지만 이번 출력에서는
     안 나간다는 걸 흐릿하게 표시해서 알 수 있게 합니다. */
  .rp-row.rp-excluded{
    opacity: .45;
  }
  .rp-include-label{
    display: flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
    cursor: pointer;
    background: #fff;
    border: 1px solid var(--line);
    border-radius: 999px;
    padding: 3px 9px 3px 7px;
  }
  .rp-include-label:hover{
    border-color: var(--cr-red);
  }
  .rp-include-text{
    font-size: 11px;
    font-weight: 600;
    color: var(--muted);
    white-space: nowrap;
  }
  .rp-include-check{
    accent-color: var(--cr-red);
    cursor: pointer;
    width: 15px;
    height: 15px;
  }
  .rp-row.dragging{
    /* 흐려지는 대신, 살짝 진하게(테두리+배경) 강조해서 "이게 선택돼서
       움직이는 중"이라는 게 더 명확하게 보이도록 합니다. */
    background: var(--spec);
    border-color: var(--cr-red);
    box-shadow: 0 4px 12px rgba(0,0,0,.15);
    transform: scale(1.01);
    z-index: 5;
    position: relative;
  }
  .rp-row.drag-over{
    border-color: var(--cr-red);
    border-width: 2px;
    padding: 6px 9px;   /* 테두리 두꺼워진 만큼 안쪽 padding 살짝 줄여서 크기 안 튀게 */
  }
  .rp-drag-handle{
    cursor: grab;
    color: var(--muted);
    font-size: 15px;
    line-height: 1;
    padding: 0 2px;
    flex-shrink: 0;
    user-select: none;
    touch-action: none;   /* 터치 화면에서 드래그할 때 스크롤 제스처와 충돌하지 않도록 */
  }
  .rp-drag-handle:active{
    cursor: grabbing;
  }
  .rp-num{
    color: var(--cr-red);
    font-weight: 800;
    font-size: 12.5px;
    flex-shrink: 0;
  }
  .rp-row .rp-name{
    font-weight: 700;
    font-size: 13.8px;
    flex: 1;
  }
  .rp-row .rp-type{
    color: var(--muted);
    font-size: 12.5px;
    margin-right: 6px;
  }
  /* 이 재질에 "값 수정"이 하나라도 적용돼 있을 때 뜨는 작은 배지 */
  .rp-row .rp-edited-badge{
    background: var(--cr-red);
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    border-radius: 999px;
    padding: 2px 7px;
    margin-right: 6px;
    flex-shrink: 0;
  }
  .rp-row button{
    border: 1px solid var(--line);
    background: #fff;
    border-radius: 5px;
    font-size: 12px;
    padding: 4px 9px;
    cursor: pointer;
  }
  .rp-row button:hover{
    border-color: var(--cr-red);
    color: var(--cr-red);
  }
  .rp-row button.rp-remove:hover{
    background: #fdecec;
    border-color: #e0a0a0;
    color: #8a1c1c;
  }

  /* 문서번호 / 설비명 / Revision 등을 입력하는 설정 영역 */
  .rp-docsettings{
    border-top: 1px solid var(--line);
    padding-top: 12px;
    margin-bottom: 12px;
  }
  .rp-docsettings-inputs{
    display: grid;
    /* 화면 너비에 맞춰 카드 개수가 자동으로 줄어드는 반응형 그리드 */
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 10px;
  }
  .rp-field{
    display: flex;
    flex-direction: column;
    gap: 4px;
  }
  .rp-field label{
    font-size: 12px;
    color: var(--muted);
    font-weight: 600;
  }
  .rp-field input[type=text]{
    font-family: inherit;
    padding: 7px 9px;
    border: 1px solid var(--line);
    border-radius: 6px;
    font-size: 13.5px;
  }
  /* 입력칸 3개(문서번호/설비명/Revision) 바로 아래에, 체크박스 4개를
     하나의 묶음으로 따로 모아둡니다 - 입력칸이랑 안 섞이고 항상 그 아래에
     나란히 보이도록. */
  .rp-docsettings-checks{
    display: flex;
    flex-wrap: wrap;
    gap: 8px 18px;
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px dashed var(--line);
  }
  .checkrow{
    display: flex;
    align-items: center;
    gap: 7px;
    cursor: pointer;
  }
  .checkrow input{
    accent-color: var(--cr-red);
    width: 15px;
    height: 15px;
    cursor: pointer;
  }
  .checkrow span{
    font-size: 13.5px;
    color: var(--ink);
    font-weight: 600;
  }

  .rp-actions{
    display: flex;
    justify-content: flex-start;   /* PDF 내보내기 + 미리보기를 왼쪽 하단에 나란히 */
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
  }
  .pdf-btn{
    background: var(--cr-red);
    color: #fff;
    border: none;
    border-radius: 6px;
    padding: 10px 18px;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
  }
  .pdf-btn:hover{
    background: var(--cr-red-dark);
  }
  .pdf-btn:disabled{
    background: #c9a4a9;
    cursor: not-allowed;
  }
  .preview-btn{
    background: #fff;
    color: var(--ink);
    border: 1px solid var(--line);
    border-radius: 6px;
    padding: 10px 18px;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
  }
  .preview-btn:hover{
    border-color: var(--cr-red);
    color: var(--cr-red);
  }
  .pdf-status{
    font-size: 13px;
    color: var(--muted);
  }
  .clear-report-btn{
    border: 1px solid var(--line);
    background: #fff;
    border-radius: 5px;
    font-size: 12.5px;
    padding: 5px 10px;
    cursor: pointer;
    color: var(--muted);
  }
  .clear-report-btn:hover{
    border-color: #8a1c1c;
    color: #8a1c1c;
  }
  .rp-head-actions{
    display: flex;
    align-items: center;
    gap: 6px;
  }
  .rp-include-all-btn{
    border: 1px solid var(--line);
    background: #fff;
    border-radius: 5px;
    font-size: 12.5px;
    padding: 5px 10px;
    cursor: pointer;
    color: var(--muted);
  }
  .rp-include-all-btn:hover{
    border-color: var(--cr-red);
    color: var(--cr-red);
  }
  /* 카테고리 그룹 헤더 안에, 그 그룹만 전체 포함/제외 하는 작은 버튼 */
  .rp-group-header-actions{
    display: flex;
    gap: 4px;
    flex-shrink: 0;
  }
  .rp-group-header-actions button{
    border: none;
    background: transparent;
    color: var(--cr-red);
    font-size: 10.5px;
    font-weight: 700;
    cursor: pointer;
    padding: 2px 4px;
    text-decoration: underline;
  }

  /* "선택한 재질 미리보기" 영역 맨 위의 작은 타이틀 + 개수 배지 */
  .report-preview-head{
    font-size: 15px;
    font-weight: 800;
    color: var(--ink);
    margin: 8px 0 12px;
    display: flex;
    align-items: center;
    gap: 8px;
  }
  .report-preview-head .badge{
    background: var(--cr-red);
    color: #fff;
    font-size: 12.5px;
    font-weight: 700;
    border-radius: 999px;
    padding: 2px 10px;
  }

  /* =================================================================
     재질별 "항목 선택"을 위한 팝업창(모달)
     ================================================================= */
  .modal-backdrop{
    display: none;   /* 열려있을 때만 JS가 open 클래스를 붙여서 보여줌 */
    position: fixed;
    inset: 0;                        /* top/right/bottom/left를 전부 0으로 = 화면 전체 덮기 */
    background: rgba(0,0,0,.45);     /* 어두운 반투명 배경 */
    z-index: 200;
    align-items: center;
    justify-content: center;
    padding: 20px;
  }
  .modal-backdrop.open{
    display: flex;
  }
  .modal-box{
    background: #fff;
    border-radius: 10px;
    max-width: 640px;
    width: 100%;
    max-height: 85vh;
    overflow-y: auto;
    overscroll-behavior: contain;   /* 스크롤이 끝(맨 위/아래)에 닿아도 배경 페이지로 스크롤이 안 새어나가게 함 */
    padding: 0;   /* 패딩은 modal-head/modal-body가 나눠 가집니다 - 그래야 sticky 헤더가
                     스크롤 영역의 진짜 맨 위 끝까지 닿아서, 스크롤할 때 그 틈으로
                     뒤 내용이 비쳐 보이는 문제가 없습니다. */
    box-shadow: 0 20px 50px rgba(0,0,0,.25);
  }
  .modal-body{
    padding: 0 22px 4px;   /* 아래쪽 여백은 이제 sticky 푸터가 자기 몫으로 가지므로 살짝만 */
  }
  /* 버튼(완료/적용)을 모달 맨 아래에 고정해서, 내용이 길어도 끝까지 스크롤
     안 해도 항상 보이게 합니다 (위쪽 modal-head를 sticky로 고정한 것과 동일한 방식). */
  .modal-footer-sticky{
    position: sticky;
    bottom: 0;
    background: #fff;
    padding: 10px 22px 20px;
    border-top: 1px solid var(--line);
    z-index: 20;
  }
  .modal-footer-sticky .modal-done{
    margin-top: 0;
  }
  .modal-head{
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 14px;   /* 텍스트가 줄바꿈돼도 ✕ 버튼과 최소 간격은 유지 */
    border-bottom: 1px solid var(--line);
    /* modal-box 자체엔 패딩이 없고(모달-body가 대신 가짐), 이 헤더가
       스크롤 영역의 진짜 맨 위/좌우 끝에 직접 붙어있기 때문에, 스크롤해도
       그 틈으로 뒤 내용이 비쳐 보이는 문제가 생기지 않습니다. */
    position: sticky;
    top: 0;
    margin-bottom: 14px;
    padding: 20px 22px 10px;
    background: #fff;
    border-radius: 10px 10px 0 0;   /* modal-box 위쪽 둥근 모서리와 어긋나지 않도록 */
    z-index: 20;
  }
  /* 제목+부제목을 감싸는 div - flex:1과 min-width:0이 없으면, 부제목이
     길어서 줄바꿈될 때 flex 아이템이 안 줄어들고 자기 원래 너비를
     고집해서 옆에 있는 ✕ 닫기 버튼과 겹쳐 보이는 문제가 생깁니다
     (좁은 모달일수록 잘 드러남). */
  .modal-head > div:not(.modal-head-actions){
    flex: 1;
    min-width: 0;
  }
  .modal-head h3{
    margin: 0;
    font-size: 16px;
  }
  .modal-head .modal-sub{
    font-size: 12.5px;
    color: var(--muted);
    margin-top: 2px;
  }
  /* 미리보기 모달 헤더 우측: PDF 내보내기 버튼 + 닫기 버튼을 나란히 */
  .modal-head-actions{
    display: flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
  }
  .preview-pdf-btn{
    background: var(--cr-red);
    color: #fff;
    border: none;
    border-radius: 6px;
    padding: 8px 16px;
    font-size: 13px;
    font-weight: 700;
    cursor: pointer;
    white-space: nowrap;
  }
  .preview-pdf-btn:hover{
    background: var(--cr-red-dark);
  }
  .preview-apply-btn{
    background: #fff;
    color: var(--ink);
    border: 1px solid var(--line);
    border-radius: 6px;
    padding: 8px 16px;
    font-size: 13px;
    font-weight: 700;
    cursor: pointer;
    white-space: nowrap;
  }
  .preview-apply-btn:hover{
    border-color: var(--cr-red);
    color: var(--cr-red);
  }
  .modal-close{
    border: none;
    background: var(--band);
    border-radius: 6px;
    width: 30px;
    height: 30px;
    font-size: 16px;
    cursor: pointer;
    color: var(--muted);
  }
  .modal-close:hover{
    background: var(--spec);
    color: var(--cr-red-dark);
  }
  .modal-done{
    margin-top: 14px;
    width: 100%;
    padding: 10px;
    background: var(--ink);
    color: #fff;
    border: none;
    border-radius: 6px;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
  }
  .modal-done:hover{
    background: var(--cr-red);
  }

  /* 표시 항목 선택 모달보다 넓게 써야 하는 모달(값 수정, 미리보기)용 */
  .modal-box-wide{
    max-width: 900px;
  }
  /* 업로드 확인처럼 짧은 메시지 + 버튼 두 개만 있는 작은 모달용 */
  .modal-box-small{
    max-width: 420px;
  }
  /* 미리보기 모달은 실제 TDS 문서를 통째로 봐야 해서 훨씬 크게 씁니다 */
  .modal-box-preview{
    max-width: 1200px;
    width: 96vw;
    max-height: 94vh;
  }

  /* =================================================================
     "값 수정" 팝업창 - 이번 보고서 출력에만 일회성으로 반영되는 값 입력
     ================================================================= */
  .edit-fields{
    display: flex;
    flex-direction: column;
    gap: 18px;
  }
  .edit-fields-section-title{
    font-size: 13px;
    font-weight: 800;
    color: var(--cr-red);
    text-transform: uppercase;
    letter-spacing: .3px;
    margin-bottom: 8px;
  }
  .edit-fields-grid{
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 10px 14px;
  }
  .edit-field{
    display: flex;
    flex-direction: column;
    gap: 4px;
  }
  .edit-field label{
    font-size: 11.5px;
    color: var(--muted);
    font-weight: 600;
  }
  .edit-field input{
    border: 1px solid var(--line);
    border-radius: 6px;
    padding: 7px 9px;
    font-size: 13px;
    color: var(--ink);
  }
  .edit-field input.edit-changed{
    border-color: var(--cr-red);
    background: var(--spec);
  }

  /* Other Properties용 Value/Min/Max 묶음 블록 - 한 줄에 깔끔하게 나란히 배치 */
  .edit-field-prop{
    grid-column: span 2;   /* 3칸짜리 입력이 들어가니 General 필드 블록보다 넓게 */
    min-width: 280px;
  }
  .edit-prop-inputs{
    display: flex;
    gap: 6px;
  }
  .epi-group{
    display: flex;
    flex-direction: column;
    gap: 3px;
  }
  .epi-group:first-child{
    flex: 2;   /* Value 칸을 Min/Max보다 넓게 */
  }
  .epi-group:not(:first-child){
    flex: 1;
  }
  .epi-tag{
    font-size: 10px;
    color: var(--muted);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .3px;
  }
  .epi-group input{
    width: 100%;
    border: 1px solid var(--line);
    border-radius: 6px;
    padding: 6px 8px;
    font-size: 12.5px;
    color: var(--ink);
  }
  .epi-group input.edit-changed{
    border-color: var(--cr-red);
    background: var(--spec);
  }
  .edit-field-label-row{
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 6px;
  }
  .edit-field-remove{
    border: none;
    background: none;
    color: var(--muted);
    font-size: 12px;
    cursor: pointer;
    padding: 0 2px;
    flex-shrink: 0;
  }
  .edit-field-remove:hover{
    color: #8a1c1c;
  }

  /* "+ 필드 추가" / "+ 항목 추가" 미니 입력 폼 (DB에 없는 항목을 직접 추가) */
  .edit-add-row{
    display: flex;
    gap: 8px;
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px dashed var(--line);
    flex-wrap: wrap;
  }
  .edit-add-row input{
    flex: 1;
    min-width: 110px;
    border: 1px solid var(--line);
    border-radius: 6px;
    padding: 7px 9px;
    font-size: 13px;
  }
  .edit-add-row-prop input{
    flex: 1 1 120px;
  }
  .edit-add-row button{
    flex: 0 0 auto;
    padding: 7px 14px;
    background: #fff;
    color: var(--cr-red);
    border: 1px solid var(--cr-red);
    border-radius: 6px;
    font-size: 12.5px;
    font-weight: 700;
    cursor: pointer;
    white-space: nowrap;
  }
  .edit-add-row button:hover{
    background: var(--cr-red);
    color: #fff;
  }
  .edit-modal-footer{
    display: flex;
    gap: 10px;
    margin-top: 0;   /* modal-footer-sticky가 이미 자기 패딩으로 여백을 주므로 중복 방지 */
  }
  /* 값 수정 모달처럼 넓은 모달에선 "초기화"(작게)+"적용"(꽉 채움)이
     자연스럽지만, 업로드 확인처럼 좁은 모달(.modal-box-small)에서는
     그렇게 꽉 채우면 버튼이 과하게 커 보여서, 우측 하단에 내용 크기만큼만
     차지하는 버튼 두 개를 나란히 배치합니다(흔한 확인창 스타일). */
  .modal-box-small .modal-head{
    margin-bottom: 7px;
  }

  .modal-box-small .edit-modal-footer{
    justify-content: flex-end;
    padding-bottom: 14px;
  }
  .modal-box-small .edit-modal-footer .edit-reset-btn{
    flex: 0 0 auto;
    padding: 10px 23px;
  }
  .modal-box-small .edit-modal-footer .modal-done{
    flex: 0 0 auto;
    width: auto;
    padding: 10px 24px;
    /* 기본은 사이트 테마의 빨간색, 호버 시에만 검정으로 - 다른 모달의
       "적용" 버튼(검정 고정)과는 다르게 이 확인창만 강조색을 씁니다. */
    background: var(--cr-red);
  }
  .modal-box-small .edit-modal-footer .modal-done:hover{
    background: var(--ink);
  }
  .edit-reset-btn{
    flex: 0 0 auto;
    padding: 10px 16px;
    background: #fff;
    color: var(--muted);
    border: 1px solid var(--line);
    border-radius: 6px;
    font-size: 13.5px;
    font-weight: 700;
    cursor: pointer;
  }
  .edit-reset-btn:hover{
    border-color: #8a1c1c;
    color: #8a1c1c;
  }
  .edit-modal-footer .modal-done{
    flex: 1;
    margin-top: 0;
  }
  .edit-apply-note{
    margin-top: 14px;
    padding: 10px 12px;
    background: #eaf6ee;
    border: 1px solid #b8e0c4;
    color: var(--ok);
    font-size: 12.5px;
    border-radius: 6px;
    line-height: 1.5;
  }

  /* =================================================================
     "보고서 미리보기" 팝업창
     ================================================================= */
  .preview-content{
    background: var(--band-soft, #ececec);
    max-height: 82vh;   /* 모달이 커진 만큼(.modal-box-preview) 미리보기 영역도 같이 키움 */
    overflow-y: auto;
    overscroll-behavior: contain;   /* 스크롤이 끝에 닿아도 배경 페이지로 스크롤이 안 새어나가게 함 */
  }
  /* 재질 이름 칩 바 - 스크롤해도 계속 위에 붙어있어서 언제든 다른 재질로 바로 이동 가능 */
  .preview-nav{
    position: sticky;
    top: 0;
    z-index: 100;   /* 시트 안의 요소(제목바 등)보다 확실히 위로 - 스크롤해도 내용이 안 비쳐 보이게 */
    background: #f5f5f5;
    border-bottom: 1px solid var(--line);
    padding: 10px 20px;
    box-shadow: 0 2px 6px rgba(0,0,0,.08);   /* 겹치는 경계가 또렷하게 보이도록 */
    display: flex;
    align-items: flex-start;
    gap: 12px;
  }
  .preview-nav-chips{
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    flex: 1;
    min-width: 0;
  }
  /* 기본은 접힌 상태 - 재질이 많아지면 칩이 여러 줄로 늘어나서 아래 보고서
     내용을 가리는 문제가 있었습니다. 접혔을 땐 한 줄 높이(약 34px)만큼만
     보여주고 나머지는 잘라둡니다 - "목록 펼치기" 버튼을 눌러야 다 보입니다. */
  .preview-nav-collapsed .preview-nav-chips{
    max-height: 34px;
    overflow: hidden;
  }
  /* 펼치기/접기 버튼을 칩들과 같은 줄, 맨 오른쪽에 고정합니다 - 줄바꿈되거나
     아래로 밀려나지 않게 flex-shrink:0 + white-space:nowrap을 둡니다. */
  .preview-nav-toggle{
    flex-shrink: 0;
    white-space: nowrap;
    border: none;
    background: transparent;
    color: var(--cr-red);
    font-size: 12px;
    font-weight: 700;
    cursor: pointer;
    padding: 6px 0;

  }
  .preview-nav-chip{
    display: inline-flex;
    align-items: center;
    gap: 5px;
    border: 1px solid var(--line);
    background: #fff;
    border-radius: 999px;
    padding: 5px 12px;
    font-size: 12px;
    font-weight: 600;
    color: var(--ink);
    cursor: pointer;
    white-space: nowrap;
  }
  .preview-nav-chip:hover{
    border-color: var(--cr-red);
    color: var(--cr-red);
  }
  .preview-edited-dot{
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--cr-red);
    display: inline-block;
  }
  .preview-sheets{
    padding: 20px;
  }
  .preview-sheet-anchor{
    scroll-margin-top: 60px;   /* sticky nav에 안 가려지게 스크롤 위치 보정 */
  }

  /* =================================================================
     TDS 문서(재질 한 장) 카드 스타일
     - 실제 인쇄물처럼 보이도록 원본 PDF 디자인을 최대한 흉내냈습니다.
     - 화면 미리보기와 PDF 캡처(html2canvas) 모두 이 스타일을 그대로 씁니다.
     ================================================================= */
  .sheet{
    position: relative;   /* 안쪽의 워터마크(.watermark)를 이 카드 기준으로 배치하기 위함 */
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: 2px;
    box-shadow: 0 1px 3px rgba(0,0,0,.06);
    overflow: hidden;      /* 워터마크 글자가 카드 밖으로 삐져나가지 않게 잘라줌 */
    margin-bottom: 22px;
  }
  /* 항상 떠있는 메인 브라우징 화면(.sheet-page가 안 붙는, 문서표 없는 카드)
     전용 - Other Properties 표가 끝나자마자 카드 테두리가 바로 나오면
     너무 딱 붙어 보여서, 카드 안쪽에 흰 여백을 살짝 추가합니다. PDF/미리보기
     (.sheet-page)는 여기 영향 안 받습니다 - 거긴 문서표 위치를 별도로 관리합니다. */
  .sheet:not(.sheet-page){
    padding-bottom: 10px;
  }

  /* PDF/미리보기 전용(!interactive일 때만 붙는 클래스) - 내용 높이만큼만
     페이지를 쓰고(generatePdf에서 페이지 크기를 내용에 맞춰 계산), 문서번호
     표/저작권 문구는 내용 바로 아래 작은 고정 간격만 두고 따라옵니다.
     flex-shrink:0을 모든 자식에 걸어두는 게 핵심입니다 - 이게 없으면 flex
     컨테이너가 자식들을 찌그러뜨려서 제목/표가 겹쳐 보이는 문제가 생깁니다. */
  .sheet-page{
    display: flex;
    flex-direction: column;
    /* PDF 캡처(pdfStage)가 항상 748px(=A4 내용 폭) 고정으로 렌더링하는데,
       미리보기는 이 폭 지정이 없어서 모달 폭(최대 1200px)에 맞춰 훨씬
       넓게 늘어나 있었습니다 - 그러면 글자 크기는 고정(px)인데 카드만
       넓어지니, 줄바꿈이 실제 PDF와 다르게 일어나고 압축 단계 판단도
       달라져서 미리보기와 PDF가 서로 다르게 보였습니다. 폭을 똑같이
       고정해서 미리보기가 실제 PDF와 항상 동일하게 보이도록 맞춥니다. */
    width: 748px;
    max-width: 100%;
    margin-left: auto;
    margin-right: auto;
  }
  .sheet-page > *{
    flex-shrink: 0;
  }
  /* 표(General/Other Properties, 또는 목차 표)를 담는 영역만 예외적으로
     줄어들 수 있고(flex-shrink:1) 넘치는 부분을 잘라냅니다(overflow:hidden).
     그래서 항목이 너무 많아져서 페이지를 넘칠 때, "표만" 잘리고 문서표·
     카피라이트는 항상 온전하게 보입니다(둘 다 flex-shrink:0 그대로라 절대
     안 줄어들고, 잘리지도 않습니다). min-height:0은 flex item이 원래
     "내용물 크기 밑으로는 못 줄어드는" 기본 동작을 풀어주는 필수 설정입니다. */
  .sheet-page > .content-area{
    flex-shrink: 1;
    min-height: 0;
    overflow: hidden;
  }
  .sheet-page .doc-footer-wrap{
    margin-top: auto;   /* 문서표/카피라이트를 항상 컨테이너 맨 아래에 고정 (표가 짧으면 그 사이 간격이 벌어짐) */
  }

  /* 문서표를 안 보이게 설정했을 때(사용자가 체크박스로 끔) - 페이지는 여전히
     A4 한 장 비율만큼 최소 높이를 확보하고(JS의 fitSheetPageToOnePage 참고),
     그 남는 공간을 Other Properties 표가 늘어나서 채우도록 합니다 - 화면이
     허전해 보이지 않게 하기 위함입니다.
     ★ table.props 자체의 margin-bottom은 0으로 고정돼있어서(문서표가 있을
     땐 그 사이 간격을 .doc-footer-wrap의 margin-top이 전담하므로 문제 없음),
     문서표가 없을 때는 표가 카드 맨 아래까지 닿아버려 여백이 하나도 없이
     딱 붙어 보였습니다. 재질/목차 페이지 둘 다, 문서표를 꺼놨을 때는
     카드 자체(.sheet-page)에 하단 여백을 20px 고정으로 둡니다. */
  .no-footer-page{
    padding-bottom: 20px;
  }

  /* 표 셀 여백/글자 크기는 항상 고정값입니다 - 재질(또는 목차 항목) 개수에
     따라 계산해서 바뀌는 로직은 전부 없앴습니다. "Technical Data Sheet"
     표시줄, 제목바, 섹션 제목, 표, 문서표, 카피라이트 문구까지 모든 요소가
     몇 개를 선택했든 항상 똑같은 위치·크기를 유지합니다. 항목이 너무
     많아져서 페이지 한 장(A4)을 넘치면, 페이지 크기나 글자 크기를 바꾸는
     대신 그냥 넘치는 부분을 잘라냅니다 - .sheet의 overflow:hidden이
     이 역할을 합니다. */

  /* 카드 전체에 옅게 깔리는 회사 워터마크 이미지(assets/watermark.png를
     base64로 구운 것). background-image 대신 실제 <img> + opacity 조합을
     쓰는 이유: html2canvas로 PDF 캡처할 때 CSS background-image의 알파
     채널이 제대로 안 살아나서 훨씬 진하고 뭉개지게 나오는 문제가 있는데,
     <img> + opacity는 캡처 결과가 화면에서 보는 것과 동일하게 나옵니다. */
  .watermark{
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;   /* 워터마크가 마우스 클릭을 가로채지 않도록 */
    overflow: hidden;
    z-index: 50;   /* 표의 셀 배경색 밑에 깔리지 않고, 표 위로 겹쳐 보이도록 확실히 앞으로 */
  }
  .watermark img{
    width: 42%;
    height: auto;
    opacity: .55;
  }

  /* 카드 맨 위 줄: "Technical Data Sheet" 라벨 + (선택시) Revision/날짜 */
  .sheet-top{
    position: relative;
    z-index: 51;   /* 워터마크(z-index 50)보다 위에 오도록 */
    display: flex;
    justify-content: space-between;
    align-items: flex-end;   /* center → flex-end: 공간(패딩)은 그대로 두고, 글자만 바닥에 붙여서 덜 휑해 보이게 */
    padding: 6px 22px;   /* 14px → 6px, 별 내용도 없는데 공간을 너무 많이 차지해서 위아래로 줄임 */
    border-bottom: 2px solid var(--ink);
    font-size: 14px;
    font-weight: 700;
    gap: 10px;
    flex-wrap: wrap;
    min-height: 20px;
  }
  .sheet-top .st-left{
    display: flex;
    align-items: center;
    gap: 10px;
  }
  .sheet-top .st-rev{
    font-weight: 400;
    color: var(--muted);
    font-size: 13px;
  }

  /* 빨간 배경의 제목 바 (제품명 + 제품 종류) */
  .titlebar{
    position: relative;
    z-index: 1;
    background: var(--cr-red);
    color: #fff;
    padding: 10px 22px;
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    font-size: 17px;
    flex-wrap: wrap;
    gap: 4px;
  }
  .titlebar .idx{
    font-weight: 800;
  }
  /* 목차 제목("INDEX") - 미리보기에서만 contenteditable로 바뀝니다.
     .idx의 흰 글씨/굵기는 그대로 물려받고, 편집 가능하다는 티만 살짝 냅니다. */
  .toc-title-input{
    display: inline-block;
    background: transparent;
    color: inherit;
    font: inherit;
    cursor: text;
    outline: none;
    border-bottom: 1px dashed rgba(255,255,255,.5);
  }
  .toc-title-input:focus{
    border-bottom-style: solid;
  }
  /* product_name 옆에 작게 붙는 formulation(고유 ID) 표시. 웹 화면에만 뜨고
     보고서(PDF)에는 안 나갑니다 - renderSheet에서 interactive일 때만 렌더링. */
  .titlebar .formulation-tag{
    font-weight: 400;
    font-size: 12.5px;
    opacity: .8;
    margin-left: 6px;
  }
  .titlebar .kind{
    font-weight: 600;
    font-size: 14px;
    opacity: .95;
  }

  /* major_category / minor_category 작게 표시 (필터링용, 웹 화면 전용 -
     보고서에는 안 나갑니다). 나중에 필터 기능을 붙일 걸 대비해 배지 형태로. */
  .category-tags{
    position: relative;
    z-index: 1;
    margin: 8px 22px 0;
    font-size: 12px;
    color: var(--muted);
    letter-spacing: .2px;
  }

  /* "General Properties" / "Other Properties" 섹션 제목 */
  .section-label{
    position: relative;
    z-index: 1;
    text-align: left;
    margin: 8px 22px 5px;   /* 14px 8px → 8px 5px: 압축 없이도 세로 공간을 더 확보하기 위해 기본값 자체를 줄임 */
  }
  .section-label span{
    display: inline-block;
    font-size: 18px;          /* 16px → 18px */
    font-weight: 800;
    letter-spacing: .4px;
    color: var(--ink);
    padding-bottom: 7px;
    border-bottom: 3px solid var(--cr-red);   /* 밑줄로 한 번 더 강조 */
  }

  /* 보고서 첫 페이지 목차 - 업로드해주신 참고 이미지 스타일(CATEGORY/NO/
     Product Name/Product Type/Remark 5열, CATEGORY는 같은 값이 연속되면
     병합)대로 구성합니다.
     ★ <table rowspan>도, CSS Grid(span 있는 버전/없는 버전 둘 다)도
     html2canvas에서 레이아웃이 깨졌습니다. 이 앱의 다른 모든 페이지
     (General/Other Properties)는 전부 순수 <table>이고 PDF에서 멀쩡했으므로,
     목차도 CSS Grid를 버리고 똑같은 순수 <table>(스팬 전혀 없음)로
     만듭니다. "병합"처럼 보이는 효과는 셀 사이 테두리만 지워서 냅니다. */
  table.toc-table{
    position: relative;
    z-index: 1;
    width: calc(100% - 44px);
    margin: 0 22px 0;   /* 30px → 0, 문서표까지 간격은 이제 .doc-footer-wrap의 margin-top이 전담 */
    border-collapse: collapse;
    font-size: 13.5px;
  }
  table.toc-table th,
  table.toc-table td{
    border: 1px solid var(--line);
    padding: 9px 10px;   /* 보기 좋은 고정값 - 재질 개수와 무관하게 항상 이 값 그대로 */
    text-align: center;
    vertical-align: middle;
    overflow-wrap: break-word;
    word-break: break-word;
  }
  table.toc-table thead th{
    background: var(--table-head);
    color: #fff;
    font-weight: 700;
    font-size: 13px;
  }
  table.toc-table .toc-td-category{ width: 15%; }
  table.toc-table .toc-td-no{ width: 8%; }
  table.toc-table .toc-td-name{ width: 20%; }
  table.toc-table .toc-td-type{ width: 37%; }
  table.toc-table .toc-td-remark{ width: 20%; }
  table.toc-table td.toc-category-merged{
    font-weight: 700;
    background: var(--band);
  }
  /* 병합된 그룹 텍스트를 담는 span - 평소엔 그냥 보통 흐름대로 표시되고,
     JS(centerMergedCategoryText)가 그룹이 2줄 이상일 때만 position:absolute로
     정확한 세로 중앙 위치를 계산해서 넣어줍니다. */
  .toc-category-text-inner{
    display: block;
    text-align: center;
  }
  /* border-collapse:collapse에서는 인접한 두 셀의 테두리가 충돌하면 "더
     진하게 그려지는 쪽"(실선)이 이겨버려서, border-bottom:none 하나만으론
     아래쪽 셀의 기본 border-top(실선)에 밀려 경계선이 계속 보였습니다.
     border-collapse 충돌 해석에서 항상 이기는 값인 hidden을 쓰고, 위/아래
     양쪽 다 지워야 확실하게 안 보입니다. */
  table.toc-table td.toc-no-bottom-border{
    border-bottom-style: hidden;
  }
  table.toc-table td.toc-no-top-border{
    border-top-style: hidden;
  }
  table.toc-table td.toc-zebra{
    background: var(--band);
  }
  /* Remark를 직접 입력한 줄은 살짝 색을 넣어서 "채워져 있다"는 걸 표시 */
  table.toc-table td.toc-remark-filled{
    background: var(--spec);
  }
  /* Remark 칸 - 사용자가 직접 타이핑해서 채우는 입력창 (테두리 없이 표 칸처럼 보이게) */
  .toc-remark-input{
    display: block;
    box-sizing: border-box;
    width: 100%;
    min-width: 0;
    background: transparent;
    font-size: 13.5px;
    font-family: inherit;
    letter-spacing: normal;
    color: var(--ink);
    text-align: center;
    padding: 0;
    margin: 0;
    line-height: 1.4;
    cursor: text;
    white-space: pre-wrap;   /* 아래 .toc-remark-text와 동일한 줄바꿈 방식 */
    overflow-wrap: break-word;
    word-break: break-word;
  }
  .toc-remark-input:focus{
    outline: 1px solid var(--cr-red);
    outline-offset: 2px;
    border-radius: 3px;
  }
  .toc-remark-text{
    display: block;
    box-sizing: border-box;
    width: 100%;
    min-width: 0;
    font-size: 13.5px;
    font-family: inherit;
    letter-spacing: normal;
    color: var(--ink);
    text-align: center;
    margin: 0;
    line-height: 1.4;
    white-space: pre-wrap;   /* textarea와 동일한 줄바꿈 방식 - 웹/PDF 줄바꿈 지점이 어긋나지 않도록 */
    overflow-wrap: break-word;
    word-break: break-word;
  }

  /* General Properties 표 (제품명, 원료, 성상 등 2열 표) */
  table.gp{
    position: relative;
    z-index: 1;
    width: calc(100% - 44px);
    margin: 0 22px 15px;   /* 아래쪽 15px - Other Properties 제목과 간격을 더 띄움 (마진 겹침 규칙상 .section-label의 margin-top 8px보다 커야 실제로 적용됨) */
    border-collapse: collapse;
    font-size: 14px;
  }
  table.gp td{
    padding: 5px 10px;   /* 보기 좋은 고정값 - 재질 개수와 무관하게 항상 이 값 그대로 */
    border-bottom: 1px solid var(--line);
    vertical-align: middle;   /* 우측 값 칸이 위쪽으로 붙지 않고 세로 가운데 정렬되도록 */
  }
  /* 메인 브라우징 화면(.sheet-page가 안 붙는 카드)은 A4 크기 제약이 없어서
     PDF처럼 빡빡하게 짤 필요는 없지만, 8px는 과했다는 피드백에 따라 살짝만 줍니다. */
  .sheet:not(.sheet-page) table.gp td{
    padding: 4px 12px;
  }
  .sheet:not(.sheet-page) table.props th,
  .sheet:not(.sheet-page) table.props td{
    padding: 3px 10px;
  }
  table.gp td.key{
    width: 220px;   /* Other Properties 표의 Product Properties 열(220px)과 폭을 맞췄습니다 */
    color: #333;
    font-weight: 600;
    background: var(--band);
  }
  table.gp td.pname{
    font-size: 16px;
    font-weight: 800;
  }

  /* Other Properties 표 (물성값들이 들어가는 4열 표) */
  table.props{
    position: relative;
    z-index: 1;
    width: calc(100% - 44px);
    margin-left: 22px;
    margin-right: 22px;
    margin-bottom: 10px;   /* 0 → 10px, 문서표와의 최소 간격 확보 */
    border-collapse: collapse;
    font-size: 13.8px;
  }
  table.props th,
  table.props td{
    border: 1px solid var(--line);
    padding: 4px 10px;   /* 기본값 4px - Other Properties 데이터 셀은 JS가 항목 수에 맞춰 이 값을 늘리거나 줄임 (헤더는 항상 이 값 그대로 고정) */
    text-align: center;   /* 기본은 가운데 정렬 (Exp.Cond, Value, Unit 칸이 여기 해당) */
  }
  table.props thead th{
    background: var(--table-head);   /* 순검정 대신 살짝 밝은 흑색 - 보고서 톤과 부드럽게 어울리도록 */
    color: #fff;
    font-weight: 700;
    font-size: 13px;
  }
  /* Product Properties 헤더(첫 칸) 너비를 General Properties 표의 왼쪽
     라벨 열(table.gp td.key, 220px)과 동일하게 맞춥니다. */
  table.props th.propname-col{
    width: 220px;
  }
  /* 항목 이름(예: Chemical Analysis)이 들어가는 첫 칸만 왼쪽 정렬 */
  table.props td.propname{
    text-align: left;
    background: var(--band);
    font-weight: 600;
    max-width: 220px;
  }
  /* Unit(단위) 칸: 항목 이름과 같은 배경이지만 가운데 정렬 */
  table.props td.unitcell{
    text-align: center;
    background: var(--band);
    font-weight: 600;
    color: #333;
  }
  table.props td.exp{
    color: var(--muted);
    white-space: nowrap;
  }
  table.props td.val{
    font-weight: 700;
  }
  /* Spec(Min/Max) 칸: 값 옆에 규격 하한/상한을 보여줍니다.
     min-max 사이는 시각적으로 "한 쌍"처럼 보이도록 경계선을 없앱니다.
     헤더(Min/Max)는 Spec과 같은 흰색(thead th 기본값 상속), 값도 흐리게
     죽이지 않고 일반 글자색 그대로 또렷하게 보이도록 합니다. */
  table.props th.spec-min,
  table.props th.spec-max{
    font-size: 12.5px;
  }
  table.props td.spec-min,
  table.props td.spec-max{
    font-size: 12.5px;
    color: var(--ink);
  }
  table.props td.spec-min{
    border-right: none;
  }
  table.props td.spec-max{
    border-left: none;
  }
  table.props th.spec-min{
    border-right: none;
  }
  table.props th.spec-max{
    border-left: none;
  }

  /* =================================================================
     문서 하단 정보 표 (문서번호 / 페이지 / TDS / 회사로고)
     ================================================================= */
  .doc-footer-wrap{
    position: relative;
    z-index: 1;
    margin-left: 22px;
    margin-right: 22px;
    /* margin-top은 여기서 아예 선언하지 않습니다 - .sheet-page .doc-footer-wrap이
       전담해서 정합니다. (margin shorthand로 0을 넣으면 그것도 하나의 선언이라
       나중에 캐스케이드 우선순위 계산에서 혼선을 줄 수 있어서, 아예 안 쓰는 쪽이 안전합니다.) */
  }
  table.doc-footer{
    width: 100%;
    border-collapse: collapse;
    font-size: 14px;      /* 12px → 14px, 문서표 전체 글자 크기 통일 */
    letter-spacing: 1px;  /* 폰트 크기에 비해 칸이 커 보여서 자간을 넓힘 */
    table-layout: fixed;   /* 칸 너비를 아래 %값대로 고정 (내용 길이에 흔들리지 않게) */
  }
  table.doc-footer td{
    border: 1px solid var(--line);
    padding: 5px 8px;      /* 7px 10px → 5px 8px, 표를 좀 더 작게 */
    vertical-align: middle;
  }
  table.doc-footer td.df-docnum{     /* 1행 1열: 문서번호 - 셀을 꽉 채우도록 정렬 */
    font-weight: 700;
    width: 34%;
    vertical-align: middle;
    white-space: nowrap;   /* JS가 자간을 계산해서 셀 너비에 맞춰 늘려줍니다 */
    overflow: hidden;
  }
  /* 글자가 칸 너비에 비해 너무 짧으면(한글 몇 글자, 짧은 코드 등) 자간을
     억지로 늘리지 않고 그냥 가운데 정렬합니다 (justifyCellText가 판단) */
  table.doc-footer td.df-docnum.df-cell-centered,
  table.doc-footer td.df-plant.df-cell-centered{
    text-align: center;
  }
  table.doc-footer td.df-pagenum{    /* 1행 2열: "현재페이지/전체페이지" */
    font-weight: 700;
    text-align: center;
    width: 14%;
  }
  table.doc-footer td.df-tds{        /* 1행 3열: 고정 텍스트 "TDS" */
    font-weight: 700;
    text-align: center;
    width: 14%;
  }
  table.doc-footer td.df-plant{      /* 2행 1열: 설비명 - 셀을 꽉 채우도록 정렬 */
    font-weight: 700;
    vertical-align: middle;
    white-space: nowrap;   /* JS가 자간을 계산해서 셀 너비에 맞춰 늘려줍니다 */
    overflow: hidden;
  }
  table.doc-footer td.df-pagelabel{  /* 2행 2열: 고정 텍스트 "Page" */
    text-align: center;
    color: var(--muted);
    font-weight: 600;
  }
  table.doc-footer td.df-catlabel{   /* 2행 3열: 고정 텍스트 "Category" */
    text-align: center;
    color: var(--muted);
    font-weight: 600;
  }
  table.doc-footer td.df-logo{       /* 4열: 1~2행 병합, 회사 로고 이미지 */
    width: 20%;
    text-align: center;
    padding: 6px 12px;
  }
  table.doc-footer td.df-logo img{
    max-width: 100%;
    height: auto;
    display: block;
    margin: 0 auto;
  }

  /* 저작권 안내 문구 (아주 작고 흐린 회색 글씨, 2줄) */
  .copyright-note{
    position: relative;
    z-index: 1;
    margin: 6px 22px 12px;   /* 8px 18px → 6px 12px, 여백 살짝 줄임 */
    font-size: 9px;
    line-height: 1.4;
    color: #9a9a9a;
    text-align: left;
  }

  /* ---------------- 빈 화면 / 오류 화면 ---------------- */
  .empty-state{
    text-align: center;
    padding: 70px 20px;
    color: var(--muted);
    font-size: 14.5px;
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: 8px;
  }
  .error-state{
    text-align: center;
    padding: 24px 20px;
    color: #8a1c1c;
    background: var(--spec);
    border: 1px solid #eab8b8;
    border-radius: 8px;
    font-size: 14px;
    margin-bottom: 20px;
  }

  /* PDF를 만들 때만 잠깐 쓰는 "숨겨진 작업 공간".
     화면 밖(왼쪽으로 아주 멀리)에 위치시켜서 사용자 눈에는 안 보이지만,
     html2canvas가 캡처할 수 있도록 실제로 DOM에는 존재하게 합니다. */
  #pdfStage{
    position: fixed;
    left: -99999px;
    top: 0;
    background: #ffffff;
  }

  /* ---------------- 좁은 화면(모바일)용 스타일 조정 ---------------- */
  @media (max-width: 640px){
    table.gp td.key,
    table.props th.propname-col{ width: 120px; font-size: 13px; }
    .titlebar{ font-size: 14px; padding: 10px 14px; }
    .sheet-top{ padding: 10px 14px; font-size: 12px; }
    table.gp,
    table.props{
      margin-left: 14px;
      margin-right: 14px;
      width: calc(100% - 28px);
      font-size: 12.5px;
    }
    #searchInput{ width: 100%; }
    select{ min-width: 0; width: 100%; }
    .search-preview{ width: 100%; }
    .doc-footer-wrap{ margin-left: 14px; margin-right: 14px; }
    .copyright-note{ margin-left: 14px; margin-right: 14px; }
  }

  /* 맨 위로 스크롤 버튼 - 화면 우측 하단에 떠있음 */
  .scroll-top-btn{
    position: fixed;
    right: 24px;
    bottom: 24px;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    border: none;
    background: var(--cr-red);
    color: #fff;
    font-size: 20px;
    font-weight: 700;
    cursor: pointer;
    box-shadow: 0 3px 10px rgba(0,0,0,.25);
    z-index: 300;
  }
  .scroll-top-btn:hover{
    background: var(--cr-red-dark);
  }
