@import url("../fonts/Pretendard/pretendard.css");
@import url("../fonts/tabler-icons/tabler-icons-300-outline.css");
@import url("./tabler/tabler.css");

/* Icon font: the imported tabler-icons css serves a ~8KB project SUBSET (only the used
   glyphs) instead of the full 687KB set — see the EXMP modification note inside that file
   for the regeneration command when a new ti-* icon is introduced. */

/* Reserve the icon box BEFORE the webfont loads: a tabler glyph advances exactly 1em, so a
   fixed 1em inline-block holds the same footprint while the font is in flight — buttons and
   labels no longer shift sideways when the glyph paints. */
.ti {
  display: inline-block;
  width: 1em;
  text-align: center;
}

:root,
:host {
  /* Exmp variables */
  --exmp-font-size-body: 16px;
  --exmp-transition-time: 0.2s;
  --exmp-border-radius: 3px;
  --exmp-button-hover-bg: var(--primary-700);

  /* Shared field padding: sk-input, sk-textarea, sk-single-select, sk-multi-select */
  --exmp-form-control-padding-y: 10px;
  --exmp-form-control-padding-x: 16px;

  /* Override Tabler variables */
  --tblr-page-padding: 24px;
  --tblr-font-sans-serif: "Pretendard";
  --tblr-body-font-family: "Pretendard";
  --tblr-breadcrumb-divider: ">";
  --tblr-border-radius: var(--exmp-border-radius);
  --tblr-dropdown-item-border-radius: var(--exmp-border-radius, 3px);

  margin-left: 0;
}

/* Background scroll lock while a drawer overlay is open (toggled by sk-drawer on <html>).
   The page is PINNED IN PLACE: sk-drawer makes the body `position:fixed` and offsets it by the
   saved scroll (`body.top = -scrollY`), so the background is visually frozen exactly where it was —
   it does NOT jump to the top on open or scroll back on close; only the drawer slides in over a
   stationary page. The LNB (its own `position:fixed`) is unaffected. sk-drawer restores the real
   scroll on close (seamless, since the content was already shown at that position). */
html.exmp-scroll-locked {
  overflow: hidden;
}
html.exmp-scroll-locked body {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  width: 100%;
}

/* Use Pretendard globally except code display elements. */
body,
input,
button,
textarea,
select {
  font-family: "Pretendard";
}

pre,
code,
kbd,
samp {
  font-family: monospace;
}

/* Prevent pre-upgrade FOUC for custom elements. */
sk-layout:not(:defined),
sk-filter-bar:not(:defined),
sk-table-section:not(:defined),
sk-table-local:not(:defined),
sk-single-select:not(:defined),
sk-multi-select:not(:defined),
sk-input:not(:defined),
sk-button:not(:defined),
sk-checkbox:not(:defined),
sk-toggle:not(:defined),
sk-textarea:not(:defined),
sk-modal:not(:defined),
sk-drawer:not(:defined),
sk-bar-chart:not(:defined),
sk-line-chart:not(:defined),
sk-donut-chart:not(:defined),
sk-tabs:not(:defined),
sk-placeholder:not(:defined),
sk-badge:not(:defined),
sk-accordion:not(:defined),
sk-otp:not(:defined),
sk-date-picker:not(:defined),
sk-time-picker:not(:defined),
sk-code-editor:not(:defined),
sk-code-diff:not(:defined),
sk-product-stats:not(:defined),
sk-credit-usage-bar:not(:defined),
sk-loading:not(:defined) {
  visibility: hidden;
}

/* Keep layout height stable while sk-layout is upgrading. */
sk-layout:not(:defined) {
  display: block;
  min-height: 100vh;
}

/* Keep the filter row's footprint while sk-filter-bar is upgrading: the host is the whole filter
   card now, so without a reserve the page below it jumps up by the card's height on every load. */
sk-filter-bar:not(:defined) {
  display: block;
  min-height: 40px;
}
sk-filter-bar[card]:not(:defined) {
  min-height: 80px;
}

/* Filter-row descendants the component cannot reach: ::slotted() matches only the top-level slotted
   node, so the period control and the controls INSIDE a .filter-field need document rules. Shared
   here because the same two declarations were repeated in four page stylesheets. */
sk-filter-bar .dashboard-period-display,
sk-filter-bar .dashboard-quick-group {
  height: 40px;
}
.filter-field > sk-single-select,
.filter-field > sk-multi-select,
.filter-field > sk-input {
  width: 100%;
}

/* Scrollbar style. --color-neutral-300/-400 was a legacy spelling that resolved to nothing, so the
   hex fallback shipped; --neutral-300/-400 are the same values. Deliberately the RAW ramp, not a
   semantic token: a light thumb is what already renders on both themes and is the more legible one
   on a dark track — flipping it would be a design change, not a token fix (rules/05 §5.2.0). */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--neutral-300) transparent;
}
*::-webkit-scrollbar {
  width: 6px;
}
*::-webkit-scrollbar-track {
  background: transparent;
}
*::-webkit-scrollbar-thumb {
  background: var(--neutral-300);
  border-radius: 999px;
}
*::-webkit-scrollbar-thumb:hover {
  background: var(--neutral-400);
}
/* End Scrollbar style */

.btn {
  --tblr-btn-color: var(--foreground-fg-primary, #111827);
}

.dropdown-menu {
  --tblr-dropdown-link-hover-bg: var(--background-bg-primary, #f9fafb);
  --tblr-dropdown-font-size: 14px;
  border-radius: var(--exmp-border-radius);
  min-width: var(--dropdown-menu-min-width, 100%);
}

.tooltip {
  --tblr-body-font-family: "Pretendard";
  --tblr-tooltip-color: var(--foreground-fg-reverse, #fff);
  --tblr-tooltip-bg: rgba(31, 41, 55, 0.7);
  --tblr-tooltip-font-size: var(--number-12, 12px);
  --tblr-tooltip-max-width: unset;
  --tblr-tooltip-opacity: 1;
  --tblr-tooltip-padding-x: var(--spacing-spacing-8, 8px);
  --tblr-tooltip-padding-y: var(--spacing-spacing-4, 4px);
}

/*
 * Fixed-position tooltip (sk-table-local ellipsis, icons, charts, etc.).
 * Use class "overflow-tooltip" on an element positioned with JS; :root vars optional overrides.
 */
:root,
:host {
  --exmp-overflow-tooltip-bg: rgba(17, 24, 39, 0.9); /* 90% opaque — raised from 0.7 so text stays readable (content behind no longer shows through), matching the info/chart tooltip 0.9 alpha */
  --exmp-overflow-tooltip-fg: #fff;
  --exmp-overflow-tooltip-max-width: min(520px, 80vw);
  --exmp-overflow-tooltip-z-index: 100000;
  --exmp-overflow-tooltip-padding-y: 4px;
  --exmp-overflow-tooltip-padding-x: 8px;
  --exmp-overflow-tooltip-shadow: 0 8px 20px rgba(17, 24, 39, 0.24);
}

.overflow-tooltip {
  position: fixed;
  left: 0;
  top: 0;
  z-index: var(--exmp-overflow-tooltip-z-index);
  max-width: var(--exmp-overflow-tooltip-max-width);
  padding: var(--exmp-overflow-tooltip-padding-y) var(--exmp-overflow-tooltip-padding-x);
  border-radius: var(--border-radius-radius-2xs, 3px);
  background: var(--exmp-overflow-tooltip-bg);
  color: var(--exmp-overflow-tooltip-fg);
  font-family: var(--paragraph-text-s-regular-font-family, "Pretendard");
  font-size: var(--paragraph-text-s-regular-font-size, 12px);
  font-weight: var(--paragraph-text-s-regular-font-weight, 400);
  line-height: var(--paragraph-text-s-regular-line-height, 16px);
  box-shadow: var(--exmp-overflow-tooltip-shadow);
  pointer-events: none;
  white-space: pre-wrap;
  word-break: break-word;
  visibility: hidden;
}

/* Links: fg-link text color, no background/border. Hover adds only an underline (also fg-link). */
a {
  color: var(--foreground-fg-link);
  text-decoration: none;
}
a:hover {
  color: var(--foreground-fg-link);
  text-decoration: underline;
  text-decoration-color: var(--foreground-fg-link);
  background: transparent;
  border: none;
  box-shadow: none;
}

.ti {
  font-size: 20px;
}

.card {
  border-radius: var(--border-radius-radius-2xs, 3px);
  border: 1px solid var(--border-border-primary, #e5e7eb);
  background: var(--background-bg-secondary, #fff);
}

/* Heading/Heading 2 */
.heading-2 {
  color: var(--foreground-fg-secondary, #374151);
  font-size: var(--number-20, 20px);
  font-style: normal;
  font-weight: var(--font-weight-font-semibold);
}

/* Heading/Heading 3 */
.heading-3 {
  color: var(--foreground-fg-secondary, #374151);
  font-size: var(--number-14, 14px);
  font-style: normal;
  font-weight: var(--font-weight-font-regular, 400);
}

.utility-green-fg {
  color: var(--utility-green-utility-green-fg);
}

/* Error text variant — color from theme-base (--foreground-fg-error / --input-foreground-text-error) */
.text-error {
  color: var(--foreground-fg-error);
}

/* Shared logo image */
.logo-img {
  position: absolute;
  height: 24px;
  width: 131px;
  cursor: pointer;
  top: 40px;
  left: 48px;
  z-index: 2;
}

/* Shared full-height page shell */
.page-shell {
  position: relative;
  min-height: 100vh;
}

/* Shared centered page content container */
.page-center {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}

/* Shared background image */
.bg-exmp-login {
  background-image: url("../images/background.svg");
  background-size: cover;
  background-repeat: no-repeat;
  background-position: center;
  background-color: #fff;
}

/* ---- Common search input ---- */
.search-input {
  width: 300px;
}

/* ---------------------------------------------------------
   Field label + container layout
   Used by: sk-input, sk-textarea, sk-single-select
   --------------------------------------------------------- */
.label-wrapper {
  min-width: 80px;
  display: none;
  font-size: var(--number-14, 14px);
  font-style: normal;
  font-weight: var(--font-weight-font-medium, 500);
}

.label-wrapper.show {
  display: block;
  padding-top: 10px;
}

.label-text {
  color: var(--foreground-fg-primary, #111827);
}

/* Required marker. The asterisk is drawn HIGH in its em box by design, so as plain inline text its
   optical centre lands above the label's: at Pretendard the ink runs baseline+0.707em → baseline+0.310em,
   centre 0.508em, against 0.355em for 명 — 0.153em too high. Measured with canvas actualBoundingBox and
   constant across sizes and weights (0.1523–0.1533 at 12/13.5/14/16px, weight 400–600), so one em value
   serves every label. `transform` is deliberate: it moves the glyph WITHOUT touching the line box, so
   label heights and row alignment are unchanged. inline-block because transforms do not apply to
   inline boxes — components that toggle the marker set `display` inline, which still wins. */
.required-asterisk {
  color: var(--utility-red-utility-red-fg, #d63939);
  display: inline-block;
  transform: translateY(0.153em);
}

/* Label + field side-by-side container */
.input-container,
.select-container {
  display: flex;
  gap: var(--number-20, 20px);
  width: 100%;
}

/* Vertical label direction: label stacked on top of input */
.input-container.label-vertical {
  flex-direction: column;
  gap: var(--number-6, 6px);
}

.input-container.label-vertical .label-wrapper.show {
  padding-top: 0;
  min-width: unset;
  width: auto;
}

.input-wrapper {
  flex: 1;
}

.select-wrapper {
  flex: 1;
  position: relative;
}

/* ---------------------------------------------------------
   Form control shared states
   Used by: sk-input, sk-textarea, sk-table-section
   --------------------------------------------------------- */

.form-control {
  color: var(--foreground-fg-primary) !important;
  box-shadow: unset;
  border-radius: var(--border-radius-radius-2xs, 3px);
  padding: var(--exmp-form-control-padding-y, 10px) var(--exmp-form-control-padding-x, 16px) !important;
  box-sizing: border-box;
  /* Surface token (light = white, dark = neutral-800) instead of Tabler's --tblr-bg-forms, which
     gets re-pointed to white by a closer [data-bs-theme=light] rule and would stay white in our
     data-exmp-mode dark theme (default + focus states). Hover already uses --input-bg-hover. */
  background: var(--background-bg-secondary);
  /* Default border via our semantic token (not Tabler's --tblr-border-color, which is shadowed light
     by [data-bs-theme=light] and stays light in dark). Matches sk-multi-select's trigger border. */
  border: 1px solid var(--border-border-primary);
}

/* Align Tabler size variants with Exmp field padding */
.form-control.form-control-sm,
.form-control-sm {
  padding: var(--exmp-form-control-padding-y, 10px) var(--exmp-form-control-padding-x, 16px) !important;
}

.form-control.form-control-lg,
.form-control-lg {
  padding: var(--exmp-form-control-padding-y, 10px) var(--exmp-form-control-padding-x, 16px) !important;
}

/* Keep file input button flush with the updated control padding */
.form-control[type="file"]::file-selector-button {
  padding: var(--exmp-form-control-padding-y, 10px) var(--exmp-form-control-padding-x, 16px);
  margin: calc(-1 * var(--exmp-form-control-padding-y, 10px))
    calc(-1 * var(--exmp-form-control-padding-x, 16px));
  margin-inline-end: var(--exmp-form-control-padding-x, 16px);
}

.form-control:focus {
  border: var(--number-1, 1px) solid var(--border-border-brand, #4263eb);
  box-shadow: 0 0 0 3px var(--border-border-brand-light, #dde4fc);
  /* Keep the surface on focus (glow only) — Tabler's :focus sets --tblr-bg-forms (white) which
     would otherwise flash white in dark mode. Matches sk-multi-select's focus. */
  background: var(--background-bg-secondary);
}

/* Hover changes ONLY the background (like sk-multi-select's trigger) — the border stays the default
   subtle border and the text color is unchanged. */
.form-control:hover:not(:disabled):not(:focus) {
  background: var(--background-bg-hover);
}

.form-control:disabled,
.form-control.disabled {
  border-color: var(--border-border-disabled, #d1d5db);
  background: var(--background-bg-disabled, #f3f4f6);
  color: var(--foreground-fg-disabled);
}

.form-control.is-readonly {
  border-color: var(--border-border-disabled, #d1d5db);
  background: var(--background-bg-disabled, #f3f4f6);
}

.form-control::placeholder {
  color: var(--foreground-fg-tertiary) !important;
}

.form-control.is-invalid {
  background-image: unset;
  border: 1px solid var(--border-border-error) !important;
  /* The typed value turns red with the border. Without this the box was outlined red while the text
     inside stayed default-dark, so an invalid field read as "decorated" rather than wrong.
     `!important` for the same reason the border above carries one: the base `.form-control` rule
     sets `color: var(--foreground-fg-primary) !important`, which a normal declaration cannot beat
     however specific it is. */
  color: var(--foreground-fg-error) !important;
}

/* ---------------------------------------------------------
   Validation feedback
   Used by: sk-input, sk-single-select
   --------------------------------------------------------- */
.invalid-feedback {
  display: none;
  color: var(--utility-red-utility-red-fg, #d63939);
  font-size: var(--number-12, 12px);
  font-style: normal;
  font-weight: var(--font-weight-font-regular, 400);
  margin-top: var(--number-6, 6px);
}

.invalid-feedback.show {
  display: block;
}

/* ---------------------------------------------------------
   sk-tabs styles
   --------------------------------------------------------- */

/* Inner list layout */
.sk-tabs-list {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  margin-bottom: 16px;
  padding: 0;
  list-style: none;
  border-bottom: 1px solid var(--border-border-primary, #e5e7eb);
}

.sk-tabs-list .nav-item {
  border: none;
  margin: 0;
  padding: 0;
}

/* Nav-link base */
.sk-tabs-list .nav-link {
  padding: 10px;
  color: var(--foreground-fg-tertiary, #6b7280);
  font-size: 14px;
  line-height: 20px;
  font-weight: 400;
  border: none;
  border-radius: 0;
  background: transparent;
  position: relative;
  box-sizing: border-box;
  cursor: pointer;
  text-decoration: none;
  display: inline-flex;
  transition: color var(--exmp-transition-time, 0.2s);
}

/* Hover */
.sk-tabs-list .nav-link:hover {
  background-color: transparent;
  color: var(--foreground-fg-primary, #111827);
}

/* Active */
.sk-tabs-list .nav-link.active {
  /* Semantic fg (light = near-black, dark = near-white) so the selected tab stays legible in dark
     mode — the old --body-body-gray-dark fell back to #131313 (invisible on dark). */
  color: var(--foreground-fg-primary);
  font-weight: 600;
  background: none;
}

.sk-tabs-list .nav-link.active::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 2px;
  background-color: var(--foreground-fg-brand, #5e42eb);
}

/* Disabled (e.g. locked by permission) — dimmed + not-allowed cursor, hover emphasis suppressed.
   The click itself is blocked in JS (_activate). */
.sk-tabs-list .nav-link.disabled,
.sk-tabs-list .nav-link.disabled:hover {
  color: var(--foreground-fg-disabled, #9ca3af);
  cursor: not-allowed;
  opacity: 0.7;
}

/* =======================================================
   Locked pane (a permission-gated content area — the tab/screen still opens, only its content is
   replaced by a disabled notice)
   ======================================================= */
.exmp-pane-locked {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 56px 16px;
  border: 1px dashed var(--border-border-primary, #e5e7eb);
  border-radius: 8px;
  background: var(--neutral-50, #f9fafb);
}
.exmp-pane-locked-msg {
  font-size: 14px;
  line-height: 20px;
  color: var(--foreground-fg-disabled, #9ca3af);
}

/* ═══════════════════════════════════════════════════════
  Label-value info table (two-column: label | value)
   ═══════════════════════════════════════════════════════ */
.info-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  border: 1px solid var(--border-border-primary, #e5e7eb);
  border-radius: 3px;
  overflow: hidden;
}
.info-table td {
  padding: 12px;
  font-size: 14px;
  border-bottom: 1px solid var(--border-border-primary, #e5e7eb);
  line-height: 20px;
  vertical-align: middle;
  height: 44px;
  box-sizing: border-box;
}
.info-table tr:last-child td {
  border-bottom: none;
}
.info-table .info-label {
  background: var(--background-bg-primary, #f9fafb);
  color: var(--foreground-fg-tertiary, #6b7280);
  font-weight: 600;
  width: 200px;
  border-right: 1px solid var(--border-border-primary, #e5e7eb);
  text-align: left;
}
.info-table .info-value {
  color: var(--foreground-fg-primary, #111827);
  font-weight: 400;
}
.info-table .info-value .sub-text {
  display: block;
  font-size: 12px;
  color: var(--foreground-fg-tertiary, #6b7280);
  line-height: 16px;
}

/* Filled info icon (the icon font ships the outline set only).
   Masked SVG colored via currentColor. Convention: tooltip-trigger info icons
   use this FILLED icon; inline info icons followed by visible text use the
   outline `ti-info-circle` glyph. */
.exmp-icon-info-filled {
  display: inline-block;
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  background-color: currentColor;
  -webkit-mask: url("/assets/icons/info-circle-filled.svg") center / contain no-repeat;
  mask: url("/assets/icons/info-circle-filled.svg") center / contain no-repeat;
}

/* Standalone-page corner logo (auth/error shells — pages without the sk-layout LNB).
   Shared by login / change-password / error pages, hence promoted here (rules/05 §5.6). */
.exmp-standalone-logo {
  position: absolute;
  top: 24px;
  left: 24px;
  height: 30px;
  width: auto;
}

/* Period meta — reset day + last collection time, pinned to the filter card's right edge.
   Shared here rather than in the six per-page sheets: identical markup on every screen that
   carries the cycle-relative 이번달/지난달 buttons (rules/05 §5.6). margin-left:auto eats the
   slack in the filter row, so the block sits at the far right whatever precedes it. */
.exmp-period-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 6px;
  margin-left: auto;
  padding-left: 16px;
  font-size: 12px;
  font-weight: 500; /* Medium (Figma 799-77239) */
  line-height: 16px;
  white-space: nowrap;
  color: var(--foreground-fg-secondary); /* Figma 799-77239: fg-secondary text, icons a step lighter */
}
/* Meta line icons (계약 기준 filled info-circle · Update time-reload): 16px, neutral-400 (Figma 799-77239). */
.exmp-period-meta-update .ti {
  font-size: 16px;
  line-height: 1;
  color: var(--neutral-400);
}
.exmp-period-meta-update {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
/* 계약 정보 link — line 1 of the filter meta, ABOVE Update. Opens the shared 계약 기준 popover
   (assets/js/utils/contract-popover.js binds to #contractInfoBtn). It replaced the old inline
   `ⓘ 계약 기준 : 매월 N일` text on every filter-bar screen: a printed day says nothing about
   좌석/한도/환율 and is only ever right for ONE platform (the Claude screens printed 매월 1일 while
   Claude's contract resets on the 8th). Promoted here rather than to a page sheet because all 11
   filter-bar screens carry it (rules/05 §5.4).
   The negative `margin-right` cancels the button's own hover padding so the TEXT edge lines up with
   the Update line below it; the padding overhang stays inside the card. */
.exmp-period-meta-link {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-right: -6px;
  padding: 2px 6px;
  border: 0;
  border-radius: 4px;
  background: transparent;
  font: inherit;
  color: var(--foreground-fg-secondary);
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
}
.exmp-period-meta-link:hover,
.exmp-period-meta-link:focus-visible {
  background-color: var(--primary-50);
  color: var(--primary-700);
}
.exmp-period-meta-link:focus-visible {
  outline: 2px solid var(--primary-300);
  outline-offset: -2px;
}
/* The info mark stays neutral at rest (it labels a note, not an action) and joins the brand color on
   hover along with the label — matching the Update line's own `--neutral-400` icon at rest. */
.exmp-period-meta-link .exmp-icon-info-filled {
  color: var(--neutral-400);
  transition: color 0.15s ease;
}
.exmp-period-meta-link:hover .exmp-icon-info-filled,
.exmp-period-meta-link:focus-visible .exmp-icon-info-filled {
  color: var(--primary-700);
}
.exmp-period-meta-link .ti {
  font-size: 14px;
  line-height: 1;
}

/* 계약 기준 line: a filled info-circle before the reset-day text; hover/focus shows the
   contract-cycle explanation (Figma 799-77239). Kept for any screen that still prints the day
   inline — the filter-bar screens now use `.exmp-period-meta-link` above instead. */
.exmp-period-meta-reset {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.exmp-period-meta-tip {
  position: relative;
  display: inline-flex;
  align-items: center;
  cursor: default;
  outline: none;
}
.exmp-period-meta-tip .exmp-icon-info-filled {
  color: var(--neutral-400);
}
.exmp-period-meta-tip-text {
  display: none;
  position: absolute;
  top: calc(100% + 9px);
  right: 0;
  z-index: 1100;
  width: max-content;
  max-width: 280px;
  padding: 8px 10px;
  border-radius: 3px;
  background: var(--tooltip-background);
  box-shadow: var(--shadow-xs-0);
  color: var(--tooltip-foreground);
  font-size: 12px;
  font-weight: 500;
  line-height: 16px;
  text-align: left;
  white-space: normal;
}
/* Down-arrow near the icon (tooltip opens below, right-aligned so it never spills off the edge). */
.exmp-period-meta-tip-text::before {
  content: "";
  position: absolute;
  top: -7px;
  right: 5px;
  width: 0;
  height: 0;
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-bottom: 7px solid var(--tooltip-background);
}
.exmp-period-meta-tip:hover .exmp-period-meta-tip-text,
.exmp-period-meta-tip:focus .exmp-period-meta-tip-text {
  display: block;
}

/* ── Auto-fit card values (assets/js/utils/fit-value.js) ──────────────────────────────────────
   The util scales a card's value down (inline font-size) until it fits its card. This class is
   its LAST resort: applied only when even the 11px floor is too wide, it turns the value into a
   single clipped line with an ellipsis (the util also sets a title with the full value).
   `display:block` is required — text-overflow:ellipsis has no effect on a flex container, which
   is what these value elements are by default. */
.is-fit-clipped {
  display: block;
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ── Editorial hairline section eyebrow (shared) ───────────────────────────────────────────────
   The project's section-grouping grammar: NO tinted container, no radius, no box padding —
   sections sit on the surface and are told apart by whitespace plus this eyebrow, a small tracked
   label followed by a 1px rule that runs to the container's inner edge.

   Promoted here from the two 상세 drawers (rules/05 §5.4: rules shared by 2+ surfaces move to a
   shared layer) once the data-update panel, the 계약 기준 panel and the Guide 용어 page adopted the
   same grammar — five copies of one type scale would have drifted apart, and "every section title
   is identical" is the whole point of the pattern.

   Markup:
     <h3 class="exmp-eyebrow">제목<span class="exmp-eyebrow-cap">캡션</span></h3>
   The rule is a ::after flex child rather than a border on the heading, so it starts AFTER the text
   with a real gap instead of running underneath it. `letter-spacing: normal` is restated on the
   caption/badge because the 0.08em tracking is only meant for the label itself. */
.exmp-eyebrow {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 0 16px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  line-height: 18px;
  white-space: nowrap;
  color: var(--foreground-fg-tertiary);
}
.exmp-eyebrow::after {
  content: "";
  flex: 1 1 auto;
  height: 1px;
  background: var(--border-border-primary);
}
/* Optional section subtitle, right of the label and before the rule. */
.exmp-eyebrow-cap {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: normal;
  white-space: nowrap;
  color: var(--foreground-fg-tertiary);
}
/* Status chips such as 조회 전용 — sk-badge (component-first, rules/06 §6.1.0). The 12px flex gap already
   spaces it, so pull back to the 8px the design asks for. */
.exmp-eyebrow sk-badge {
  margin-left: -4px;
  font-size: 11px;
  letter-spacing: normal;
}


/* ── Outlined section with a notched title (shared) ────────────────────────────────────────────
   The alternative to .exmp-eyebrow above: instead of a title + rule, the section is an OUTLINED box
   whose title is notched into its top border.

   Built on the native <fieldset> / <legend> pair on purpose. The obvious CSS-only route — an
   absolutely positioned heading painted with the panel's own background to "erase" the border
   behind it — has to know that background, so it breaks the moment the surface differs (dark mode,
   a tinted panel, a drawer vs a modal). The browser's own legend cuts the border for real, and it
   labels the group for assistive tech at the same time.

   Markup:
     <fieldset class="exmp-fieldset"><legend class="exmp-fieldset-legend">조직 정보</legend>…</fieldset>

   ★ CURRENTLY UNUSED. Both 상세 drawers adopted it and then went back to .exmp-eyebrow above
   (user request 2026-08-28). Kept because it is a complete, verified alternative — the same
   mechanism precedent as menu-data's `hidden` group flag (rules/03 §3.1) — not because something
   renders it. Delete it if a second grouping grammar stops being wanted. */
.exmp-fieldset {
  /* A fieldset's default `min-inline-size: min-content` stops it shrinking inside a flex/grid
     parent — it would push the drawer wider than its panel. */
  min-width: 0;
  margin: 0;
  /* Vertically CENTRED content (user request 2026-08-28). The two numbers differ on purpose: the
     browser paints a fieldset's top border through the LEGEND'S VERTICAL CENTRE, so the legend's
     lower half (9px of an 18px line box) already sits inside the box and counts as top inset.
     Visible top gap = 9 + padding-top; visible bottom gap = padding-bottom. Declaring both padding
     values 20px would therefore push the content 9px DOWN, not centre it — 11 + 9 = 20 = 20 does. */
  padding: 11px 24px 20px;
  border: 1px solid var(--border-border-primary);
  border-radius: 12px;
}
.exmp-fieldset-legend {
  /* Bootstrap's reboot (via tabler.css) sets `legend { float: left; width: 100% }`. A floated,
     full-width legend still draws the notch, but the first in-flow block after it is laid out
     BESIDE the float and collapses to 0 width — the 조직명 row rendered as a sliver at the box's
     right edge. Undo both so the legend is the browser's own shrink-to-fit legend again. */
  float: none;
  width: auto;
  /* …and its 0.5rem bottom margin, so the gap under the title is the fieldset's own padding. */
  margin-bottom: 0;
  /* The legend's containing block is the fieldset's CONTENT box, so the box's own 24px left padding
     already offsets it; this margin only trims that back. -2px puts the notch 23px from the border
     — clear of the 12px corner radius, and 10px left of where it sat before (user request). */
  margin-left: -2px;
  padding: 0 8px;
  /* FIXED 18px box, laid out as a flex row. The padding-top compensation above is calculated from
     the legend's height, so a legend carrying an sk-badge must not grow taller than a plain one —
     otherwise the border line drops and that one box's content sits low (사용 현황 measured 23 vs
     20 before this). Flex + a fixed height pins it regardless of what the legend contains. */
  display: flex;
  align-items: center;
  gap: 8px;
  height: 18px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  line-height: 18px;
  white-space: nowrap;
  color: var(--foreground-fg-tertiary);
}
.exmp-fieldset-legend sk-badge {
  font-size: 11px;
  letter-spacing: normal;
}

/* ==========================================================================
   조직 트리 셀 (대시보드 조직별 크레딧/비용 표 · 조직별 좌석/비용 사용율 막대)
   Shared because ChatGPT and Claude dashboards render the identical widget;
   a per-page copy drifted the moment one of them was retuned.
   Driver: assets/js/utils/org-tree-cell.js.
   ========================================================================== */

/* Full-path tooltip for an org row. On BODY (position:fixed) on purpose: the table cell lives inside
   sk-table-local's shadow root AND inside the card's overflow box, so a tooltip drawn in place is
   clipped by the card edge. Same dark tooltip design as the project's other hover tooltips. */
.exmp-org-path-tip {
  position: fixed;
  z-index: 2000;
  max-width: 520px;
  padding: 6px 10px;
  border-radius: var(--border-radius-radius-2xs, 3px);
  background: var(--tooltip-background);
  color: var(--tooltip-foreground);
  font-size: 12px;
  font-weight: 500;
  line-height: 18px;
  white-space: nowrap;
  pointer-events: none;
}
.exmp-org-path-tip[hidden] {
  display: none;
}

/* ── Bar widget: org label as a tree ──────────────────────────────────────
   IDENTICAL to the table cell: 18px per depth and a `└` connector — no vertical guide lines (the
   first pass drew them here only; user request 2026-08-31 removed them so the two widgets read the
   same). Left-aligned, because a right-aligned label cannot show an indent. */
.dashboard-seat-label[data-depth] {
  text-align: left;
  padding-left: calc(var(--seat-depth, 0) * 18px);
  box-sizing: border-box;
}
.dashboard-seat-label[data-depth="0"] {
  font-weight: 700;
  color: var(--foreground-fg-primary);
}
/* `└` connector. Same geometry as the table cell (org-tree-cell.js): 4px left of the depth's indent
   start, 6px gap to the name, 14px in --foreground-fg-disabled. */
.dashboard-seat-glyph {
  margin-left: -4px;
  margin-right: 6px;
  font-size: 14px;
  line-height: 1;
  color: var(--foreground-fg-disabled);
}
.dashboard-seat-direct {
  margin-left: 3px;
  font-size: 11px;
  font-weight: 400;
  color: var(--foreground-fg-tertiary);
}
