/* ============================================================================= * report-print.css — 월간 운영 보고서(PDF 저장 전용) A4 화이트 문서 스타일 * * monthly_report_print.php 만 링크한다(app.css 미링크 — 다크 셸 토큰과 격리). * 폐쇄망: 자기호스팅 로컬 파일. 외부 폰트/CDN 0 — 시스템 폰트만. * 화면(@media screen)에서는 회색 캔버스 위에 뜬 흰 A4 종이로 미리보기(WYSIWYG), * 인쇄(@media print)에서는 캔버스·툴바가 벗겨지고 종이가 곧 PDF 가 된다. * * 대상 브라우저: Chrome / Edge(Chromium) — 고정 러닝 헤더/푸터·색 보존 안정. * FLAG: Chromium print-to-PDF 는 @page 마진박스 counter(page) 미지원 + 폐쇄망 * JS 폴리필 금지 → 라이브 페이지번호 미탑재. 고정 푸터에 문서번호·생성일시·대외비를 * 매 장 반복해 추적성을 확보하고, 화면 노트로 인쇄 대화상자의 머리글/바닥글 옵션을 안내. * ============================================================================= */ .report-paper { /* 라이트 고정 팔레트 — app.css @media print 토큰과 값 정합(흑백/컬러 안전) */ --paper-ink: #1a1f2b; --paper-sub: #5b6472; --paper-navy: #14315e; --paper-gold: #9a7b28; --hair: #d9dee6; --hair-strong: #c2cad6; --ok: #0a6b39; --warn: #8a5a00; --alert: #b11f1f; --band-safe: #e7f0ea; --band-hot: #f6e3dc; --band-cold: #dfeef2; --paper-bg-soft: #f4f6f9; } /* 색 보존 강제(네이비 밴드·골드 룰·판정 씰·차트 획 유실 방지) */ .report-paper, .report-paper * { -webkit-print-color-adjust: exact; print-color-adjust: exact; } /* ── @page: A4 세로 + 여백 ─────────────────────────────────────────────────── */ @page { size: A4 portrait; margin: 18mm 16mm 20mm; } @page :first { margin-top: 22mm; /* 표지 상단 여유 */ } /* ── 종이 본체 ─────────────────────────────────────────────────────────────── */ .report-paper { font-family: "Malgun Gothic", "맑은 고딕", "Apple SD Gothic Neo", "Noto Sans KR", sans-serif; color: var(--paper-ink); background: #fff; line-height: 1.6; font-size: 10.5pt; font-variant-numeric: tabular-nums; -webkit-font-smoothing: antialiased; } .report-paper h1, .report-paper h2, .report-paper h3 { margin: 0; font-weight: 800; } .report-paper p { margin: 0; } .report-paper .num { font-variant-numeric: tabular-nums; } /* ── 러닝 헤더/푸터(position:fixed — Chromium 이 매 장 반복 렌더) ─────────────── */ .run-header, .run-footer { position: fixed; left: 0; right: 0; display: flex; justify-content: space-between; align-items: center; font-size: 8pt; color: var(--paper-sub); letter-spacing: .02em; } .run-header { top: 0; border-bottom: 0.6pt solid var(--hair); padding-bottom: 3pt; } .run-footer { bottom: 0; border-top: 0.6pt solid var(--hair); padding-top: 3pt; } .run-header .cls, .run-footer .cls { color: var(--alert); font-weight: 700; } .run-header b { color: var(--paper-navy); font-weight: 800; } /* ── 표지 마스트헤드 ───────────────────────────────────────────────────────── */ .cover { position: relative; padding-top: 4mm; } .cover-eyebrow { font-size: 9.5pt; font-weight: 700; letter-spacing: .35em; color: var(--paper-navy); margin-bottom: 6mm; } .cover-eyebrow::before { content: ""; display: inline-block; width: 26pt; height: 3pt; vertical-align: middle; background: var(--paper-gold); margin-right: 8pt; border-radius: 2pt; } .cover-title { font-size: 27pt; line-height: 1.15; color: var(--paper-navy); letter-spacing: -.01em; margin-bottom: 3mm; max-width: 70%; } .cover-sub { font-size: 11pt; color: var(--paper-sub); margin-bottom: 10mm; } .cover-month { font-size: 58pt; font-weight: 800; color: var(--paper-navy); line-height: 1; letter-spacing: -.02em; } .cover-period { font-size: 10.5pt; color: var(--paper-sub); margin-top: 2mm; } .cover-seal { position: absolute; top: 0; right: 0; text-align: center; } .cover-seal .seal-cap { font-size: 8pt; color: var(--paper-sub); margin-top: 2pt; } /* 관제 대상 3개소 스트립 */ .cover-scope { display: flex; gap: 6mm; margin-top: 10mm; padding-top: 6mm; border-top: 1pt solid var(--hair-strong); } .scope-item { flex: 1; } .scope-item .k { font-size: 8.5pt; color: var(--paper-sub); letter-spacing: .1em; } .scope-item .v { font-size: 12pt; font-weight: 800; color: var(--paper-navy); } .scope-item .t { font-size: 8.5pt; color: var(--paper-sub); } /* 문서 통제 블록 */ .doc-control { margin-top: 12mm; border: 1pt solid var(--hair-strong); border-radius: 2pt; display: grid; grid-template-columns: repeat(3, 1fr); overflow: hidden; } .doc-control > div { padding: 3.2mm 4mm; border-right: 0.6pt solid var(--hair); border-bottom: 0.6pt solid var(--hair); } .doc-control > div:nth-child(3n) { border-right: none; } .doc-control .dk { font-size: 8pt; color: var(--paper-sub); letter-spacing: .08em; margin-bottom: 1pt; } .doc-control .dv { font-size: 10pt; font-weight: 700; color: var(--paper-ink); } .doc-control .dv.cls { color: var(--alert); } /* ── 섹션 제목 ─────────────────────────────────────────────────────────────── */ .section { margin-top: 8mm; } .section-title { font-size: 13pt; color: var(--paper-navy); padding-bottom: 2mm; border-bottom: 1.6pt solid var(--paper-navy); margin-bottom: 4mm; display: flex; align-items: baseline; gap: 8pt; break-after: avoid; page-break-after: avoid; } .section-title .en { font-size: 8.5pt; font-weight: 600; color: var(--paper-sub); letter-spacing: .12em; } .section-title .no { font-size: 9pt; font-weight: 800; color: #fff; background: var(--paper-navy); border-radius: 2pt; padding: 1pt 6pt; letter-spacing: .05em; } /* ── 경영 요약 KPI ─────────────────────────────────────────────────────────── */ .kpi-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 4mm; } .kpi-card { border: 1pt solid var(--hair-strong); border-radius: 2pt; padding: 3.5mm 4mm; break-inside: avoid; page-break-inside: avoid; position: relative; } .kpi-card::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 3pt; background: var(--paper-navy); } .kpi-card.is-alert::before { background: var(--alert); } .kpi-card.is-warn::before { background: var(--warn); } .kpi-card.is-ok::before { background: var(--ok); } .kpi-card .kpi-k { font-size: 8.5pt; color: var(--paper-sub); letter-spacing: .04em; } .kpi-card .kpi-v { font-size: 21pt; font-weight: 800; color: var(--paper-navy); line-height: 1.1; } .kpi-card.is-alert .kpi-v { color: var(--alert); } .kpi-card .kpi-s { font-size: 8.5pt; color: var(--paper-sub); } .kpi-gauge-wrap { text-align: center; } .exec-summary { margin-top: 4mm; border: 1pt solid var(--hair-strong); border-left: 3pt solid var(--paper-navy); border-radius: 2pt; padding: 3.5mm 4.5mm; background: var(--paper-bg-soft); break-inside: avoid; page-break-inside: avoid; } .exec-summary .verdict-line { font-size: 11pt; font-weight: 800; color: var(--paper-navy); } .exec-summary .verdict-line.is-alert { color: var(--alert); } .exec-summary .verdict-line.is-warn { color: var(--warn); } .exec-summary .verdict-line.is-ok { color: var(--ok); } .exec-summary p { font-size: 10pt; color: var(--paper-ink); margin-top: 1.5mm; } /* ── 정의형 지표 표(경보·이벤트 / 온습도) ──────────────────────────────────── */ .metric-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 6mm; } .metric-block { break-inside: avoid; page-break-inside: avoid; } .metric-block h3 { font-size: 10pt; color: var(--paper-navy); margin-bottom: 2mm; } table.def { width: 100%; border-collapse: collapse; font-size: 9.5pt; } table.def th, table.def td { padding: 2mm 3mm; border-bottom: 0.6pt solid var(--hair); text-align: left; } table.def th { color: var(--paper-sub); font-weight: 600; width: 55%; } table.def td { text-align: right; font-weight: 700; color: var(--paper-ink); font-variant-numeric: tabular-nums; } table.def td.is-alert { color: var(--alert); } /* ── 일반 데이터 표(지점별 등) ─────────────────────────────────────────────── */ table.grid { width: 100%; border-collapse: collapse; font-size: 9pt; } table.grid thead { display: table-header-group; } /* 페이지 넘김 시 머리행 반복 */ table.grid th, table.grid td { padding: 2mm 2.5mm; border: 0.6pt solid var(--hair); text-align: center; } table.grid th { background: var(--paper-navy); color: #fff; font-weight: 700; font-size: 8.5pt; } table.grid td.l { text-align: left; } table.grid tbody tr:nth-child(even) td { background: var(--paper-bg-soft); } table.grid td.is-alert { color: var(--alert); font-weight: 800; } /* ── 지점별 카드 ───────────────────────────────────────────────────────────── */ .loc-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4mm; } .loc-card { border: 1pt solid var(--hair-strong); border-radius: 2pt; padding: 3.5mm 4mm; break-inside: avoid; page-break-inside: avoid; } .loc-card .lc-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 2mm; padding-bottom: 2mm; border-bottom: 0.8pt solid var(--hair); } .loc-card .lc-name { font-size: 11.5pt; font-weight: 800; color: var(--paper-navy); } .loc-card .lc-loc { font-size: 8.5pt; color: var(--paper-sub); } .pill { font-size: 8pt; font-weight: 800; padding: 1pt 6pt; border-radius: 8pt; border: 0.8pt solid currentColor; } .pill.is-ok { color: var(--ok); } .pill.is-warn { color: var(--warn); } .pill.is-alert { color: var(--alert); } .loc-card dl { display: grid; grid-template-columns: auto 1fr; gap: 1mm 3mm; margin: 0; font-size: 9pt; } .loc-card dt { color: var(--paper-sub); } .loc-card dd { margin: 0; text-align: right; font-weight: 700; font-variant-numeric: tabular-nums; } .loc-card dd.is-alert { color: var(--alert); } /* ── 차트 패널 ─────────────────────────────────────────────────────────────── */ .chart-panel { border: 1pt solid var(--hair-strong); border-radius: 2pt; padding: 4mm; margin-top: 3mm; break-inside: avoid; page-break-inside: avoid; } .chart-panel h3 { font-size: 10pt; color: var(--paper-navy); margin-bottom: 1mm; } .chart-panel .chart-cap { font-size: 8.5pt; color: var(--paper-sub); margin-bottom: 2mm; } .chart-empty { padding: 8mm; text-align: center; color: var(--paper-sub); font-size: 9.5pt; border: 0.8pt dashed var(--hair-strong); border-radius: 2pt; } .chart-legend-row { display: flex; flex-wrap: wrap; gap: 4mm; margin-top: 2mm; font-size: 8.5pt; color: var(--paper-sub); } .chart-legend-row span { display: inline-flex; align-items: center; gap: 4pt; } .lg-sw { width: 11pt; height: 8pt; border-radius: 1pt; display: inline-block; } .lg-sw.hatch { background: repeating-linear-gradient(45deg, var(--alert) 0 2pt, #fff 2pt 3.5pt); border: 0.5pt solid var(--alert); } .lg-line { width: 16pt; height: 3pt; border-radius: 2pt; display: inline-block; } .lg-line.dash { background: repeating-linear-gradient(90deg, currentColor 0 4pt, transparent 4pt 7pt) !important; } .lg-band { width: 12pt; height: 9pt; border-radius: 1pt; display: inline-block; border: 0.5pt solid var(--hair-strong); } /* ── 누수 사고 로그 ────────────────────────────────────────────────────────── */ .incident-none { border: 1pt solid var(--ok); border-radius: 2pt; padding: 4mm 4.5mm; color: var(--ok); font-weight: 700; font-size: 10pt; background: var(--band-safe); } /* ── 기준·주석 + 서명란 ────────────────────────────────────────────────────── */ .basis-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 6mm; } .basis-block { break-inside: avoid; page-break-inside: avoid; } .basis-block h3 { font-size: 9.5pt; color: var(--paper-navy); margin-bottom: 2mm; } .basis-block ul { margin: 0; padding-left: 4.5mm; font-size: 9pt; color: var(--paper-ink); } .basis-block li { margin-bottom: 1mm; } .basis-block li b { color: var(--paper-navy); } .sign-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6mm; margin-top: 8mm; break-inside: avoid; page-break-inside: avoid; } .sign-box { border: 1pt solid var(--hair-strong); border-radius: 2pt; } .sign-box .sk { font-size: 8.5pt; color: var(--paper-sub); padding: 2mm 3mm; border-bottom: 0.6pt solid var(--hair); background: var(--paper-bg-soft); } .sign-box .sv { height: 16mm; } .sign-box .sn { font-size: 8pt; color: var(--paper-sub); padding: 1.5mm 3mm; border-top: 0.6pt solid var(--hair); text-align: right; } /* ── 페이지 브레이크 ───────────────────────────────────────────────────────── */ .page-break { break-before: page; page-break-before: always; } /* ── 화면 미리보기(회색 캔버스 위 흰 종이) ─────────────────────────────────── */ @media screen { body { margin: 0; background: #e9eaee; } .report-canvas { padding: 24px 12px 64px; } .report-paper { width: 210mm; max-width: 100%; min-height: 297mm; margin: 0 auto; padding: 22mm 16mm 20mm; background: #fff; box-sizing: border-box; box-shadow: 0 6px 28px rgba(20, 30, 60, .18); } /* 화면에서는 고정 헤더/푸터를 종이 안쪽에 흐름 배치(겹침 방지) */ .run-header, .run-footer { position: static; margin: 0 auto; width: 210mm; max-width: 100%; } .run-header { margin-bottom: 6mm; } .run-footer { margin-top: 6mm; } .print-note { width: 210mm; max-width: 100%; margin: 0 auto 16px; padding: 10px 14px; background: #fff8e6; border: 1px solid #e6c766; border-radius: 6px; font-size: 12px; color: #6b5410; box-sizing: border-box; font-family: "Malgun Gothic", "맑은 고딕", "Apple SD Gothic Neo", sans-serif; } .print-note b { color: #8a5a00; } .print-note a { color: #14315e; } .screen-toolbar { width: 210mm; max-width: 100%; margin: 0 auto 12px; display: flex; gap: 8px; flex-wrap: wrap; box-sizing: border-box; } .screen-toolbar a, .screen-toolbar button { font: inherit; font-size: 13px; font-weight: 700; padding: 8px 14px; border-radius: 6px; border: 1px solid #14315e; background: #14315e; color: #fff; cursor: pointer; text-decoration: none; font-family: "Malgun Gothic", "맑은 고딕", "Apple SD Gothic Neo", sans-serif; } .screen-toolbar a.ghost { background: #fff; color: #14315e; } } /* ── 인쇄(종이가 곧 PDF) ───────────────────────────────────────────────────── */ @media print { html, body { margin: 0; background: #fff; } .report-canvas { padding: 0; background: #fff; } .report-paper { width: auto; max-width: none; min-height: 0; margin: 0; padding: 0; background: #fff; box-shadow: none; } .print-note, .screen-toolbar, .screen-only { display: none !important; } /* 고정 헤더/푸터와 본문 겹침 방지 여백 */ .report-body { padding-top: 6mm; padding-bottom: 6mm; } }