/* AI 노출 분석 플랫폼 - design system
   kmong 1404692 / order 7577722

   One accent, one neutral ramp, one radius scale. Data is the thing on screen,
   so chrome stays quiet: hairline borders, no drop shadows except on things
   that actually float (popovers, the sticky header). */

@import url("https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable-dynamic-subset.min.css");

:root {
  --bg: #f7f8fa;
  --surface: #ffffff;
  --surface-2: #fbfcfd;
  --line: #e6e9ef;
  --line-strong: #d3d8e2;

  --ink: #131722;
  --ink-2: #454c5c;
  --ink-3: #6b7385;
  --ink-4: #9aa1b1;

  --accent: #2f6bff;
  --accent-ink: #1d4fd8;
  --accent-soft: #eaf0ff;

  --good: #0f9d58;
  --good-soft: #e6f6ed;
  --warn: #c77700;
  --warn-soft: #fdf3e2;
  --bad: #d93b3b;
  --bad-soft: #fdeceb;

  --chatgpt: #10a37f;
  --gemini: #4285f4;

  --r-sm: 6px;
  --r: 10px;
  --r-lg: 14px;

  --sidebar-w: 244px;
  --shadow-pop: 0 8px 28px rgba(19, 23, 34, 0.12);

  --mono: "SFMono-Regular", ui-monospace, "JetBrains Mono", Menlo, Consolas, monospace;
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
}

body {
  background: var(--bg);
  color: var(--ink);
  font-family: "Pretendard Variable", Pretendard, -apple-system, BlinkMacSystemFont, "Apple SD Gothic Neo",
    "Malgun Gothic", system-ui, sans-serif;
  font-size: 14px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  font-feature-settings: "tnum";
}

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

h1,
h2,
h3,
h4 {
  margin: 0;
  font-weight: 700;
  letter-spacing: -0.02em;
}

/* ------------------------------------------------------------- app shell */

.app {
  display: grid;
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
  min-height: 100vh;
}

.sidebar {
  background: #10131c;
  color: #cfd4e0;
  padding: 18px 14px 28px;
  display: flex;
  flex-direction: column;
  gap: 18px;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.brand {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 0 6px;
  color: #fff;
  font-weight: 700;
  font-size: 15px;
  letter-spacing: -0.03em;
}

.brand .mark {
  width: 26px;
  height: 26px;
  border-radius: 8px;
  background: linear-gradient(135deg, #2f6bff, #7aa2ff);
  display: grid;
  place-items: center;
  font-size: 12px;
  font-weight: 800;
  color: #fff;
  flex: none;
}

.brand small {
  display: block;
  font-size: 10.5px;
  font-weight: 500;
  color: #7b849b;
  letter-spacing: 0;
}

/* hospital switcher */
.switcher {
  position: relative;
}

.switcher > summary {
  list-style: none;
  cursor: pointer;
  background: #1b202e;
  border: 1px solid #262c3d;
  border-radius: var(--r);
  padding: 9px 11px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  color: #fff;
  font-weight: 600;
  font-size: 13.5px;
}

.switcher > summary::-webkit-details-marker {
  display: none;
}

.switcher > summary:hover {
  background: #212736;
}

.switcher > summary .caret {
  color: #7b849b;
  font-size: 10px;
}

.switcher .menu {
  position: absolute;
  z-index: 40;
  left: 0;
  right: 0;
  top: calc(100% + 6px);
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--shadow-pop);
  padding: 5px;
  max-height: 320px;
  overflow-y: auto;
}

.switcher .menu a,
.switcher .menu button {
  display: block;
  width: 100%;
  text-align: left;
  padding: 8px 10px;
  border-radius: var(--r-sm);
  font-size: 13.5px;
  border: 0;
  background: none;
  cursor: pointer;
  font: inherit;
  color: var(--ink);
}

.switcher .menu a:hover,
.switcher .menu button:hover {
  background: var(--surface-2);
}

.switcher .menu a.on {
  background: var(--accent-soft);
  color: var(--accent-ink);
  font-weight: 600;
}

.switcher .menu .sep {
  height: 1px;
  background: var(--line);
  margin: 5px 0;
}

.switcher .menu .role {
  float: right;
  font-size: 11px;
  color: var(--ink-4);
  font-weight: 500;
}

/* nav */
.nav {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.nav-group > .nav-title {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: #666f85;
  padding: 0 8px 6px;
  text-transform: uppercase;
}

.nav a {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 7.5px 9px;
  border-radius: var(--r-sm);
  color: #b8bfcf;
  font-size: 13.5px;
  font-weight: 500;
}

.nav a:hover {
  background: #1a1f2c;
  color: #fff;
}

.nav a.on {
  background: var(--accent);
  color: #fff;
  font-weight: 600;
}

.nav a .ico {
  width: 15px;
  text-align: center;
  opacity: 0.85;
  font-size: 13px;
}

.nav a .pill {
  margin-left: auto;
  background: #2b3243;
  color: #aab2c4;
  border-radius: 99px;
  font-size: 10.5px;
  padding: 1px 6px;
  font-weight: 600;
}

.nav a.on .pill {
  background: rgba(255, 255, 255, 0.24);
  color: #fff;
}

.sidebar-foot {
  margin-top: auto;
  border-top: 1px solid #232838;
  padding-top: 14px;
  font-size: 12px;
  color: #7b849b;
}

.sidebar-foot .who {
  color: #cfd4e0;
  font-weight: 600;
  font-size: 12.5px;
}

.sidebar-foot a {
  color: #7b849b;
}

.sidebar-foot a:hover {
  color: #cfd4e0;
}

/* ---------------------------------------------------------------- main */

main {
  min-width: 0;
  padding: 0 0 64px;
}

.topbar {
  position: sticky;
  top: 0;
  z-index: 30;
  /* Opaque, not a translucent pane. The old rgba(...,0.88) + backdrop-filter
     let scrolled cards smear through the header, and because the blur only
     applied where a compositing layer existed, half the bar looked painted and
     half looked broken. A page header does not need to be see-through. */
  background: var(--bg);
  border-bottom: 1px solid var(--line);
  padding: 16px 28px;
  display: flex;
  align-items: flex-start;
  gap: 16px;
  flex-wrap: wrap;
}

.topbar h1 {
  font-size: 19px;
}

.topbar .sub {
  color: var(--ink-3);
  font-size: 12.5px;
  margin-top: 2px;
}

.topbar .spacer {
  flex: 1;
}

.page {
  padding: 20px 28px 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
  max-width: 1400px;
}

/* --------------------------------------------------------------- cards */

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 18px 20px;
}

.card > header {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
  flex-wrap: wrap;
}

.card > header h2 {
  font-size: 15px;
}

.card > header .hint {
  color: var(--ink-3);
  font-size: 12.5px;
}

.card > header .spacer {
  flex: 1;
}

.card.pad0 {
  padding: 0;
}

.card.pad0 > header {
  padding: 16px 20px 0;
  margin-bottom: 12px;
}

.grid {
  display: grid;
  gap: 16px;
}

.grid.c2 {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.grid.c3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.grid.c4 {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

.grid.side {
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
  /* Do not stretch the short card to the tall one. The 노출점유율 chart card
     was being pulled to the height of 언급 상위 병원 next to it, leaving ~150px
     of blank white under the plot that read as a broken render. */
  align-items: start;
}

/* ----------------------------------------------------------- stat card */

.stat {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 15px 17px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.stat .k {
  color: var(--ink-3);
  font-size: 12.5px;
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 5px;
}

.stat .v {
  font-size: 26px;
  font-weight: 750;
  letter-spacing: -0.035em;
  line-height: 1.15;
}

.stat .v .unit {
  font-size: 14px;
  font-weight: 600;
  color: var(--ink-3);
  margin-left: 1px;
}

.stat .d {
  font-size: 12px;
  color: var(--ink-3);
}

.delta {
  font-weight: 700;
  font-size: 12px;
  border-radius: 99px;
  padding: 1px 7px;
}

.delta.up {
  background: var(--good-soft);
  color: var(--good);
}

.delta.down {
  background: var(--bad-soft);
  color: var(--bad);
}

.delta.flat {
  background: #eef0f4;
  color: var(--ink-3);
}

/* ----------------------------------------------------------- info dot */

.info {
  position: relative;
  display: inline-flex;
}

.info > .dot {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  color: var(--ink-4);
  font-size: 9.5px;
  font-weight: 700;
  display: grid;
  place-items: center;
  cursor: help;
  background: var(--surface);
}

.info > .bubble {
  display: none;
  position: absolute;
  z-index: 50;
  top: 20px;
  left: -8px;
  right: auto;
  width: 320px;
  max-width: min(320px, calc(100vw - 32px));
  background: var(--ink);
  color: #e9ecf3;
  border-radius: var(--r);
  padding: 11px 13px;
  font-size: 12.2px;
  line-height: 1.6;
  font-weight: 400;
  white-space: normal;
  text-align: left;
  box-shadow: var(--shadow-pop);
}

/* Right-edge handling. A dot sitting in a right-aligned cell (.num), in a
   right-aligned header, or in the last stat card of a row has almost no room
   to its right, so a left-anchored 320px bubble runs off the viewport and the
   sentence is unreadable. Anchor those from the right instead. `.info.end` is
   the explicit opt-in for anywhere the markup is not a .num cell, and app.js
   adds `.flip` at runtime for anything still overflowing (narrow windows,
   zoomed text). */
.num .info > .bubble,
.info.end > .bubble,
.info.flip > .bubble {
  left: auto;
  right: -8px;
}

.info:hover > .bubble,
.info:focus-within > .bubble {
  display: block;
}

.info > .bubble b {
  color: #fff;
  display: block;
  margin-bottom: 3px;
}

.info > .bubble code {
  display: block;
  margin-top: 7px;
  padding: 6px 8px;
  background: rgba(255, 255, 255, 0.1);
  border-radius: var(--r-sm);
  font-family: var(--mono);
  font-size: 11.2px;
  color: #cfe0ff;
  white-space: pre-wrap;
}

/* -------------------------------------------------------------- tables */

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}

thead th {
  text-align: left;
  font-size: 11.5px;
  font-weight: 700;
  color: var(--ink-3);
  letter-spacing: 0.01em;
  padding: 9px 14px;
  border-bottom: 1px solid var(--line);
  background: var(--surface-2);
  white-space: nowrap;
}

thead th:first-child {
  padding-left: 20px;
}

thead th:last-child {
  padding-right: 20px;
}

thead th a {
  color: inherit;
  display: inline-flex;
  gap: 3px;
  align-items: center;
}

thead th a:hover {
  color: var(--accent-ink);
}

thead th .sort {
  color: var(--ink-4);
  font-size: 9px;
}

thead th .sort.on {
  color: var(--accent);
}

tbody td {
  padding: 11px 14px;
  border-bottom: 1px solid var(--line);
  vertical-align: middle;
}

tbody td:first-child {
  padding-left: 20px;
}

tbody td:last-child {
  padding-right: 20px;
}

tbody tr:last-child td {
  border-bottom: 0;
}

tbody tr:hover {
  background: var(--surface-2);
}

tbody tr.ours {
  background: var(--accent-soft);
}

tbody tr.ours:hover {
  background: #e0e9ff;
}

.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.muted {
  color: var(--ink-3);
}

.strong {
  font-weight: 650;
}

.trunc {
  display: block;
  max-width: 520px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.empty {
  padding: 46px 20px;
  text-align: center;
  color: var(--ink-3);
}

.empty .big {
  font-size: 15px;
  font-weight: 650;
  color: var(--ink-2);
  margin-bottom: 5px;
}

.empty .cta {
  margin-top: 14px;
}

/* --------------------------------------------------------------- chips */

.chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  border: 1px solid var(--line);
  background: var(--surface-2);
  border-radius: 99px;
  padding: 2px 9px;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--ink-2);
  white-space: nowrap;
}

.chip.sm {
  font-size: 11px;
  padding: 1px 7px;
}

.chip .n {
  color: var(--ink-3);
  font-weight: 600;
}

.chip.model-CHATGPT {
  color: #0b7a5f;
  background: #e8f7f2;
  border-color: #cbebe1;
}

.chip.model-GEMINI {
  color: #1a5fd0;
  background: #eaf1fe;
  border-color: #d3e2fd;
}

.chip.on {
  background: var(--good-soft);
  border-color: #c8e8d6;
  color: var(--good);
}

.chip.off {
  background: #f0f1f4;
  border-color: var(--line);
  color: var(--ink-4);
}

.chip.warn {
  background: var(--warn-soft);
  border-color: #f3e0bd;
  color: var(--warn);
}

.chip.bad {
  background: var(--bad-soft);
  border-color: #f6cfcd;
  color: var(--bad);
}

.chip.accent {
  background: var(--accent-soft);
  border-color: #cfdcff;
  color: var(--accent-ink);
}

.dotc {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex: none;
}

/* -------------------------------------------------------------- forms */

.field {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
}

.field > label,
.lab {
  font-size: 12.5px;
  font-weight: 650;
  color: var(--ink-2);
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

.field .schema {
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--accent-ink);
  background: var(--accent-soft);
  border-radius: 4px;
  padding: 0 5px;
  font-weight: 600;
}

.field .how {
  font-size: 11.5px;
  color: var(--ink-4);
  font-weight: 500;
}

.field .hint {
  font-size: 11.5px;
  color: var(--ink-3);
}

input[type="text"],
input[type="email"],
input[type="password"],
input[type="url"],
input[type="tel"],
input[type="date"],
input[type="time"],
input[type="search"],
input[type="number"],
input[type="datetime-local"],
select,
textarea {
  width: 100%;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  padding: 8px 10px;
  font: inherit;
  font-size: 13.5px;
  color: var(--ink);
  transition: border-color 0.12s, box-shadow 0.12s;
}

input:focus,
select:focus,
textarea:focus {
  outline: 0;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(47, 107, 255, 0.13);
}

input[readonly],
input:disabled,
textarea:disabled,
select:disabled {
  background: #f2f4f7;
  color: var(--ink-3);
  cursor: not-allowed;
}

textarea {
  resize: vertical;
  min-height: 74px;
  line-height: 1.6;
}

select {
  appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6'><path d='M1 1l4 4 4-4' fill='none' stroke='%236b7385' stroke-width='1.6' stroke-linecap='round'/></svg>");
  background-repeat: no-repeat;
  background-position: right 10px center;
  padding-right: 28px;
}

.check {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--ink-2);
  cursor: pointer;
  user-select: none;
}

.check input {
  width: 15px;
  height: 15px;
  accent-color: var(--accent);
  margin: 0;
}

/* -------------------------------------------------------------- buttons */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--ink);
  border-radius: var(--r-sm);
  padding: 8px 13px;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.12s, border-color 0.12s, opacity 0.12s;
}

.btn:hover {
  background: var(--surface-2);
  border-color: var(--ink-4);
}

.btn.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.btn.primary:hover {
  background: var(--accent-ink);
  border-color: var(--accent-ink);
}

.btn.ghost {
  border-color: transparent;
  background: transparent;
  color: var(--ink-2);
}

.btn.ghost:hover {
  background: #eef0f4;
  border-color: transparent;
}

.btn.danger {
  color: var(--bad);
  border-color: #f0cbc9;
  background: var(--bad-soft);
}

.btn.danger:hover {
  background: #fbdedc;
  border-color: #e6b3b0;
}

.btn.sm {
  padding: 5px 10px;
  font-size: 12px;
}

.btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.btnrow {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}

/* ----------------------------------------------------------- save bar */
/* The 블로그 관리 forms are long, so the 저장 button follows the viewport.
   It used to be a bare transparent .btnrow pinned at bottom:16px, which drew
   the button and its helper line straight over whatever field happened to be
   at the bottom of the screen (the 병원 대표번호 label and input, in the
   delivery screenshots). It is now an opaque bar with its own background, and
   the form reserves space for it so the last field is never trapped
   underneath. */
.savebar {
  position: sticky;
  bottom: 16px;
  z-index: 25;
  display: flex;
  gap: 12px;
  align-items: center;
  flex-wrap: wrap;
  margin-top: 20px;
  padding: 11px 16px;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-lg);
  box-shadow: 0 10px 26px -12px rgba(19, 23, 34, 0.4);
}

.savebar .muted {
  font-size: 12.5px;
}

/* Room under the last field so the bar has empty space to rest on at the end
   of the form, and so a field focused from the keyboard scrolls clear of the
   bar instead of landing underneath it. */
.savewrap {
  padding-bottom: 24px;
}

.savewrap .field,
.savewrap input,
.savewrap select,
.savewrap textarea {
  scroll-margin-bottom: 104px;
}

/* --------------------------------------------------------------- tabs */

.tabs {
  display: inline-flex;
  background: #eef0f4;
  border-radius: 9px;
  padding: 3px;
  gap: 2px;
}

.tabs a {
  padding: 6px 13px;
  border-radius: 7px;
  font-size: 12.5px;
  font-weight: 650;
  color: var(--ink-3);
}

.tabs a:hover {
  color: var(--ink);
}

.tabs a.on {
  background: var(--surface);
  color: var(--ink);
  box-shadow: 0 1px 2px rgba(19, 23, 34, 0.08);
}

/* ------------------------------------------------------------- filters */

.filters {
  display: flex;
  gap: 10px;
  align-items: flex-end;
  flex-wrap: wrap;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 13px 16px;
}

.filters .field {
  min-width: 130px;
}

.filters .field > label {
  font-size: 11px;
  color: var(--ink-3);
}

.filters .grow {
  flex: 1;
  min-width: 160px;
}

.seg {
  display: inline-flex;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  overflow: hidden;
}

.seg a {
  padding: 7.5px 12px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--ink-3);
  background: var(--surface);
  border-right: 1px solid var(--line);
}

.seg a:last-child {
  border-right: 0;
}

.seg a.on {
  background: var(--accent);
  color: #fff;
}

.seg a:not(.on):hover {
  background: var(--surface-2);
  color: var(--ink);
}

/* --------------------------------------------------------------- chart */

.chart {
  width: 100%;
  height: auto;
  display: block;
}

/* Sparse-trend state. With one measured day the plot was a flat grey band and
   two dots stuck to the right edge, which customers read as a rendering bug.
   This says the same honest thing (we have not measured enough yet) and still
   shows the one measurement that exists. It is deliberately short: it must not
   leave the dead vertical space the stretched plot did. */
.trendwait {
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-lg);
  background: var(--surface-2);
  padding: 26px 20px;
  text-align: center;
}

.trendwait .ttl {
  font-size: 14px;
  font-weight: 700;
  color: var(--ink-2);
}

.trendwait .sub {
  margin-top: 5px;
  font-size: 12.5px;
  color: var(--ink-3);
}

.trendwait .pts {
  margin-top: 14px;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  font-size: 12px;
  color: var(--ink-2);
}

.trendwait .pts > span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 5px 11px;
  font-weight: 600;
}

.trendwait .pts .on {
  background: transparent;
  border: 0;
  padding: 0 2px 0 0;
  color: var(--ink-3);
  font-weight: 500;
}

.trendwait .pts i {
  width: 10px;
  height: 3px;
  border-radius: 2px;
  display: inline-block;
}

.trendwait .pts b {
  color: var(--ink);
}

.legend {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  font-size: 12px;
  color: var(--ink-2);
  font-weight: 600;
}

.legend span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.legend i {
  width: 10px;
  height: 3px;
  border-radius: 2px;
  display: inline-block;
}

/* --------------------------------------------------------------- bars */

.barlist {
  display: flex;
  flex-direction: column;
  gap: 13px;
}

.barrow .top {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 5px;
  font-size: 13px;
}

.barrow .top .name {
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.barrow .top .n {
  margin-left: auto;
  color: var(--ink-3);
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.barrow .track {
  height: 7px;
  border-radius: 99px;
  background: #eef0f4;
  overflow: hidden;
}

.barrow .fill {
  height: 100%;
  border-radius: 99px;
  background: #8fe3bd;
  min-width: 2px;
}

/* --------------------------------------------------------------- misc */

.flash {
  border-radius: var(--r);
  padding: 11px 14px;
  font-size: 13px;
  font-weight: 600;
  border: 1px solid;
}

.flash.ok {
  background: var(--good-soft);
  border-color: #c8e8d6;
  color: #0b7040;
}

.flash.error {
  background: var(--bad-soft);
  border-color: #f6cfcd;
  color: #a92b2b;
}

.flash.info {
  background: var(--accent-soft);
  border-color: #cfdcff;
  color: var(--accent-ink);
}

/* The stand-in-engine disclosure. It sits directly on the table whose columns it
   qualifies, so it has to be readable at a glance: body-size text, real
   contrast, full width, and 'keep-all' so Korean never wraps mid-word. */
.disclosure {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding: 11px 16px;
  background: var(--warn-soft);
  border-top: 1px solid #f0dcb6;
  border-bottom: 1px solid #f0dcb6;
  color: #7a4c00;
  font-size: 13.2px;
  line-height: 1.62;
  word-break: keep-all;
}

.disclosure .tag {
  flex: none;
  margin-top: 1px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--warn);
  color: #fff;
  font-size: 11.5px;
  font-weight: 700;
  white-space: nowrap;
}

.disclosure .txt {
  flex: 1;
}

.disclosure .info > .dot {
  margin-top: 3px;
  border-color: #cf9a3c;
  color: #7a4c00;
  background: #fff;
}

.notice {
  background: var(--warn-soft);
  border: 1px solid #f3e0bd;
  color: #8a5600;
  border-radius: var(--r);
  padding: 10px 13px;
  font-size: 12.5px;
}

.pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 14px;
  font-size: 13px;
  color: var(--ink-3);
  border-top: 1px solid var(--line);
}

.pager a {
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  color: var(--ink-2);
  background: var(--surface);
}

.pager a:hover {
  background: var(--surface-2);
}

.pager .off {
  opacity: 0.35;
  pointer-events: none;
}

pre.code {
  background: #10131c;
  color: #d7dcea;
  border-radius: var(--r);
  padding: 14px 16px;
  overflow-x: auto;
  font-family: var(--mono);
  font-size: 11.8px;
  line-height: 1.65;
  margin: 0;
  white-space: pre;
  tab-size: 2;
}

pre.code.light {
  background: var(--surface-2);
  color: var(--ink-2);
  border: 1px solid var(--line);
}

.copywrap {
  position: relative;
}

.copywrap .btn {
  position: absolute;
  top: 9px;
  right: 9px;
}

.sectionhead {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 4px 0 0;
}

.sectionhead .no {
  width: 22px;
  height: 22px;
  border-radius: 7px;
  background: var(--accent);
  color: #fff;
  display: grid;
  place-items: center;
  font-size: 11.5px;
  font-weight: 750;
  flex: none;
}

.sectionhead h2 {
  font-size: 15.5px;
}

.sectionhead .note {
  color: var(--ink-3);
  font-size: 12.5px;
  font-weight: 500;
}

.meter {
  height: 8px;
  border-radius: 99px;
  background: #eef0f4;
  overflow: hidden;
}

.meter > i {
  display: block;
  height: 100%;
  border-radius: 99px;
  background: linear-gradient(90deg, #2f6bff, #6ea0ff);
}

.rowsplit {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
}

.rowsplit.c3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

/* drag-to-reorder cards (주요시술 / FAQ) */
.dragitem {
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--surface);
  padding: 14px 16px;
}

.dragitem.dragging {
  opacity: 0.45;
  border-style: dashed;
}

.dragitem.over {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(47, 107, 255, 0.12);
}

.dragitem > header {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 12px;
}

.dragitem .handle {
  cursor: grab;
  color: var(--ink-4);
  font-size: 15px;
  line-height: 1;
  user-select: none;
  padding: 2px 4px;
  border-radius: 5px;
}

.dragitem .handle:hover {
  background: #eef0f4;
  color: var(--ink-2);
}

.dragitem .idx {
  font-weight: 700;
  font-size: 13px;
}

/* auth pages */
.authwrap {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 32px 20px;
  background: radial-gradient(1100px 520px at 50% -10%, #e9efff 0%, var(--bg) 62%);
}

.authcard {
  width: 100%;
  max-width: 404px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 30px 28px;
  box-shadow: 0 12px 40px rgba(19, 23, 34, 0.07);
}

.authcard h1 {
  font-size: 21px;
  margin-bottom: 5px;
}

.authcard .lead {
  color: var(--ink-3);
  font-size: 13px;
  margin-bottom: 22px;
}

.authcard .field {
  margin-bottom: 13px;
}

.authcard .btn {
  width: 100%;
  padding: 10px;
  font-size: 14px;
}

.authcard .alt {
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
  font-size: 12.5px;
  color: var(--ink-3);
  text-align: center;
}

.authcard .alt a {
  color: var(--accent-ink);
  font-weight: 650;
}

.authbrand {
  display: flex;
  align-items: center;
  gap: 9px;
  justify-content: center;
  margin-bottom: 22px;
  font-weight: 750;
  letter-spacing: -0.03em;
  font-size: 15px;
}

.authbrand .mark {
  width: 28px;
  height: 28px;
  border-radius: 9px;
  background: linear-gradient(135deg, #2f6bff, #7aa2ff);
  color: #fff;
  display: grid;
  place-items: center;
  font-size: 12px;
  font-weight: 800;
}

/* toast (replaces window.alert: Korean in-app browsers swallow it) */
#toast {
  position: fixed;
  z-index: 200;
  left: 50%;
  bottom: 26px;
  transform: translateX(-50%) translateY(14px);
  background: var(--ink);
  color: #fff;
  border-radius: 10px;
  padding: 11px 17px;
  font-size: 13px;
  font-weight: 600;
  box-shadow: var(--shadow-pop);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s, transform 0.18s;
  max-width: min(88vw, 460px);
}

#toast.show {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* modal (replaces window.confirm / window.prompt for the same reason) */
.modal-back {
  position: fixed;
  inset: 0;
  background: rgba(19, 23, 34, 0.42);
  display: none;
  place-items: center;
  z-index: 150;
  padding: 20px;
}

.modal-back.show {
  display: grid;
}

.modal {
  background: var(--surface);
  border-radius: 14px;
  width: 100%;
  max-width: 420px;
  padding: 22px 24px;
  box-shadow: var(--shadow-pop);
}

.modal h3 {
  font-size: 16px;
  margin-bottom: 7px;
}

.modal p {
  color: var(--ink-2);
  font-size: 13px;
  margin: 0 0 18px;
  line-height: 1.6;
}

.modal .btnrow {
  justify-content: flex-end;
}

/* responsive */
@media (max-width: 1120px) {
  .grid.c4 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .grid.side,
  .grid.c3 {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (max-width: 860px) {
  .app {
    grid-template-columns: 1fr;
  }
  .sidebar {
    position: static;
    height: auto;
  }
  .grid.c2,
  .grid.c4,
  .rowsplit,
  .rowsplit.c3 {
    grid-template-columns: minmax(0, 1fr);
  }
  .page,
  .topbar {
    padding-left: 16px;
    padding-right: 16px;
  }
}

/* Scheduled-run failure bar (src/web/alerts.ts).
   Sits at the top of .page on every screen for 소유자/관리자, and only when a
   scheduled analysis produced no data at all. A frozen dashboard looks exactly
   like a quiet week, which is how a two-day outage went unnoticed; this is what
   makes the difference visible. */
.alertbar {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin: 0 0 18px;
  padding: 12px 16px;
  background: var(--bad-soft);
  border: 1px solid #f3c9c6;
  border-left: 4px solid var(--bad);
  border-radius: var(--r);
  color: #8d2b2b;
  font-size: 13.2px;
  line-height: 1.62;
  word-break: keep-all;
}

.alertbar .tag {
  flex: none;
  margin-top: 1px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--bad);
  color: #fff;
  font-size: 11.5px;
  font-weight: 700;
  white-space: nowrap;
}

.alertbar .txt {
  flex: 1;
}
