/* CS2-Box box editor — dark, CS2-flavored UI. */
:root {
  --bg: #0d1117;
  --bg2: #10151c;
  --panel: #161b22;
  --panel2: #1c232e;
  --border: #2b3442;
  --border-soft: #232c38;
  --text: #e6edf3;
  --muted: #8b98a9;
  --accent: #3d8bff;
  --accent-2: #4aa3a2;
  --ok: #3fb98a;
  --warn: #e3b341;
  --err: #f0626d;
  --info: #4fc3f7;
  --g1: #9aa4af;
  --g2: #4fc3f7;
  --g3: #4b8bff;
  --g4: #b06cff;
  --g5: #ff5f8f;
  --radius: 10px;
  --mono: ui-monospace, "Cascadia Code", Consolas, "Courier New", monospace;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  /* The full background stack (cover image + dark scrim) lives in the
     "page atmosphere" section below, which wins by source order. This
     base color is the fallback while the stylesheet loads. */
  background-color: var(--bg);
  color: var(--text);
  font: 14px/1.55 -apple-system, "Segoe UI", "Microsoft YaHei", Roboto, "Helvetica Neue", Arial, sans-serif;
}

h1 { font-size: 17px; margin: 0; }
h2 { font-size: 14px; margin: 0 0 10px; color: #ffffff; letter-spacing: .3px; }
h3 { font-size: 12.5px; margin: 14px 0 6px; color: var(--muted); text-transform: uppercase; letter-spacing: .8px; }
p { margin: 6px 0; }
code {
  font-family: var(--mono);
  background: #0b0f14;
  border: 1px solid var(--border-soft);
  border-radius: 4px;
  padding: 1px 5px;
  font-size: 12px;
  word-break: break-all;
}

/* ---------- top bar ---------- */
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  padding: 12px 20px;
  background: rgba(22, 27, 34, .92);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 20;
  backdrop-filter: blur(4px);
}
.brand { display: flex; align-items: center; gap: 12px; }
.logo {
  font-size: 26px;
  color: var(--accent-2);
  text-shadow: 0 0 12px rgba(74, 163, 162, .55);
}
.brand-text p { margin: 2px 0 0; color: var(--muted); font-size: 12px; }
.topbar-controls { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ctl { display: flex; align-items: center; gap: 6px; color: var(--muted); font-size: 12px; }

/* ---------- buttons / inputs ---------- */
.btn {
  font: inherit;
  color: var(--text);
  background: var(--panel2);
  border: 1px solid var(--border);
  border-radius: 7px;
  padding: 6px 12px;
  cursor: pointer;
  transition: background .15s, border-color .15s;
}
.btn:hover { border-color: var(--accent); background: #222b38; }
.btn.small { padding: 3px 8px; font-size: 12px; border-radius: 6px; }
.btn.accent { background: #1f3b66; border-color: #2f5aa0; }
.btn.accent:hover { background: #25467c; }
.btn.danger { color: var(--err); }
.btn.danger:hover { border-color: var(--err); background: #2b1c20; }

input[type="text"], input[type="number"], input:not([type]), select, textarea {
  font: inherit;
  color: var(--text);
  background: #0d1219;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 5px 9px;
  outline: none;
  transition: border-color .15s, box-shadow .15s;
}
input:focus, select:focus, textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px rgba(61, 139, 255, .18);
}
input:disabled {
  opacity: .45;
  cursor: not-allowed;
}
input[type="checkbox"] { accent-color: var(--accent-2); }
select { cursor: pointer; }
textarea { resize: vertical; font-family: var(--mono); font-size: 12px; line-height: 1.5; }
.chk { display: inline-flex; align-items: center; gap: 6px; color: var(--muted); font-size: 12px; cursor: pointer; user-select: none; }

.grow { flex: 1; min-width: 80px; }
.w7 { width: 70px; }
.w14 { width: 150px; }
.w24 { width: 260px; }
.muted { color: var(--muted); }
.help { display: block; color: var(--muted); font-size: 11.5px; margin-top: 3px; }
.danger-input { border-color: rgba(240, 98, 109, .55) !important; }

/* ---------- layout ---------- */
.layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(360px, 460px);
  gap: 18px;
  padding: 18px 20px 10px;
  align-items: start;
}
.column { min-width: 0; }
.right { position: sticky; top: 68px; }

@media (max-width: 1180px) {
  .layout { grid-template-columns: 1fr; }
  .right { position: static; }
}

/* ---------- cards ---------- */
.card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 16px;
  margin-bottom: 14px;
}
.card-head { display: flex; justify-content: space-between; align-items: center; gap: 8px; flex-wrap: wrap; }
.head-actions { display: flex; gap: 6px; }

.grid2 {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 10px 14px;
}
.field { display: flex; flex-direction: column; gap: 4px; }
.f-label { color: var(--muted); font-size: 12px; }
.row { display: flex; gap: 10px; margin: 8px 0; align-items: flex-start; flex-wrap: wrap; }
.row.inline { align-items: center; }
.split-row { display: flex; align-items: center; gap: 12px; margin-top: 8px; }
.tacz-row { background: rgba(255,255,255,.025); border: 1px solid var(--border-soft); border-radius: 8px; padding: 10px 12px; margin-top: 12px; }

/* ---------- floating hover tooltip ---------- */
.field-tooltip {
  position: fixed;
  z-index: 9999;
  max-width: min(340px, calc(100vw - 24px));
  padding: 9px 11px;
  background: rgba(11, 15, 20, .96);
  border: 1px solid var(--accent);
  border-radius: 7px;
  color: var(--text);
  font-size: 12.5px;
  line-height: 1.55;
  box-shadow: 0 8px 22px rgba(0, 0, 0, .55);
  pointer-events: none;
  opacity: 0;
  transform: translateY(3px);
  transition: opacity .12s ease, transform .12s ease;
  white-space: normal;
  word-break: break-word;
}
.field-tooltip.show { opacity: 1; transform: translateY(0); }

.issue[data-issue-path] { cursor: pointer; }
.issue[data-issue-path]:hover { outline: 1px solid var(--border); }
.flash-highlight {
  outline: 2px solid var(--warn) !important;
  outline-offset: 2px;
  border-radius: 4px;
  animation: flash-pulse 1.1s ease-in-out 0s 2;
}
@keyframes flash-pulse {
  0%, 100% { background-color: transparent; }
  45% { background-color: rgba(184, 134, 11, .22); }
}
.tacz-row h2 { margin-bottom: 4px; }
.tacz-row .help { margin-top: 2px; }
.tacz-switch { font-size: 13px; color: var(--text); white-space: nowrap; }
.tacz-switch input { width: 16px; height: 16px; accent-color: var(--accent); }
.mini { display: inline-flex; align-items: center; gap: 5px; color: var(--muted); font-size: 12px; }
.mini.sep { color: var(--muted); }

.random-row { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 6px; }
.random-slot { display: inline-flex; flex-direction: column; gap: 3px; }
.random-slot b { font-size: 11px; color: var(--muted); font-weight: 400; }
.random-slot input { width: 90px; }

.entity-row { display: flex; gap: 8px; margin: 6px 0; }
/* Empty state for the entity list — signals "nothing here, add a row" without
   a stuck blank space. Only theme tokens, so cream / dark both adapt. */
.entity-empty {
  margin: 6px 0 8px;
  padding: 10px 12px;
  border: 1px dashed var(--border);
  border-radius: 8px;
  color: var(--muted);
  font-size: 12px;
}

/* ---------- grade cards ---------- */
.grade-card {
  background: var(--panel2);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  margin-bottom: 10px;
  padding: 10px 12px;
}
.grade-card summary {
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 10px;
  list-style: none;
  flex-wrap: wrap;
}
.grade-card summary::-webkit-details-marker { display: none; }
.grade-card summary::before { content: "▸"; color: var(--muted); transition: transform .15s; }
.grade-card[open] summary::before { transform: rotate(90deg); }
.grade-badge {
  font-size: 12px;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 10px;
  border: 1px solid currentColor;
  background: rgba(0, 0, 0, .25);
}
.g1 { color: var(--g1); }
.g2 { color: var(--g2); }
.g3 { color: var(--g3); }
.g4 { color: var(--g4); }
.g5 { color: var(--g5); }
.count-badge {
  margin-left: auto;
  background: #0b0f14;
  border: 1px solid var(--border-soft);
  border-radius: 10px;
  padding: 0 8px;
  color: var(--muted);
  font-size: 12px;
}
.grade-items { margin: 10px 0; display: flex; flex-direction: column; gap: 8px; }

.item-card {
  background: #11161f;
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  padding: 8px 10px;
}
.item-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.item-no { color: var(--muted); font-family: var(--mono); font-size: 12px; }
.item-body { margin-top: 8px; }

/* Advanced per-item data: collapsible, hidden by default until filled */
.item-adv {
  border: 1px dashed var(--border);
  border-radius: 6px;
  padding: 3px 8px;
  margin-top: 8px;
}
.item-adv summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--muted);
  font-size: 12px;
  user-select: none;
}
.item-adv summary::-webkit-details-marker { display: none; }
.item-adv summary::before { content: "▸"; transition: transform .15s; }
.item-adv[open] summary::before { transform: rotate(90deg); }
.item-adv .adv-badge {
  margin-left: auto;
  color: var(--accent);
  border: 1px solid var(--accent);
  border-radius: 9px;
  padding: 0 7px;
  font-size: 11px;
  line-height: 16px;
}
.item-adv .row { margin-top: 6px; }

/* ---------- price table ---------- */
.price-table { width: 100%; border-collapse: collapse; margin-top: 6px; }
.price-table th {
  text-align: left;
  font-size: 11.5px;
  color: var(--muted);
  font-weight: 500;
  padding: 5px 8px;
  border-bottom: 1px solid var(--border);
}
.price-table td { padding: 5px 8px; border-bottom: 1px solid var(--border-soft); vertical-align: middle; }
.price-table tr:hover td { background: rgba(255, 255, 255, .02); }
.key-cell code { display: block; }
.tiny { display: block; font-size: 10.5px; margin-top: 1px; }
.price-input { width: 110px; }
.recycle-cell { font-family: var(--mono); color: var(--accent-2); }
.status-cell { font-size: 11.5px; }
.status-ok { color: var(--ok); }
.status-warn { color: var(--warn); }
.status-muted { color: var(--muted); }
.extra-tag { font-size: 10.5px; color: var(--info); }
.add-key-row { display: flex; gap: 8px; margin-top: 10px; }

/* ---------- preview ---------- */
.preview-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 8px;
}
.tab-row { display: flex; gap: 4px; }
.tab {
  font: inherit;
  color: var(--muted);
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 7px 7px 0 0;
  padding: 6px 12px;
  cursor: pointer;
}
.tab.active { color: #fff; background: var(--panel2); border-color: var(--accent); }
.preview-actions { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.path-hint {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--accent-2);
  background: rgba(74, 163, 162, .08);
  border: 1px solid rgba(74, 163, 162, .25);
  border-radius: 6px 6px 0 0;
  padding: 5px 10px;
}
.json-preview {
  margin: 0;
  background: #0a0e13;
  border: 1px solid var(--border);
  border-top: none;
  border-radius: 0 0 var(--radius) var(--radius);
  padding: 12px 14px;
  max-height: 46vh;
  overflow: auto;
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.55;
  white-space: pre;
  color: #c9d4e0;
}

/* ---------- issues ---------- */
.issues { margin-top: 14px; }
.issue-summary { display: flex; gap: 8px; margin: 6px 0 8px; flex-wrap: wrap; }
.badge {
  font-size: 11.5px;
  border-radius: 10px;
  padding: 2px 10px;
  border: 1px solid currentColor;
  background: rgba(0, 0, 0, .2);
}
.badge.error { color: var(--err); }
.badge.warn { color: var(--warn); }
.badge.info { color: var(--info); }
.issue-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 5px; }
.issue {
  font-size: 12.5px;
  padding: 5px 10px;
  border-radius: 6px;
  border: 1px solid transparent;
  word-break: break-all;
}
.issue.error { color: var(--err); background: rgba(240, 98, 109, .07); border-color: rgba(240, 98, 109, .35); }
.issue.warn { color: var(--warn); background: rgba(227, 179, 65, .07); border-color: rgba(227, 179, 65, .35); }
.issue.info { color: var(--info); background: rgba(79, 195, 247, .06); border-color: rgba(79, 195, 247, .3); }
.issue.ok { color: var(--ok); border-color: rgba(63, 185, 138, .35); background: rgba(63, 185, 138, .06); }
.issue-path { font-family: var(--mono); font-size: 11px; opacity: .8; margin-right: 4px; }

.version-note {
  margin: 4px 0 12px;
  font-size: 12px;
  color: var(--muted);
  background: rgba(79, 195, 247, .05);
  border: 1px dashed rgba(79, 195, 247, .3);
  border-radius: 8px;
  padding: 8px 12px;
}

/* ---------- dialogs ---------- */
.dlg {
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 18px;
  width: min(560px, 92vw);
}
.dlg::backdrop { background: rgba(5, 8, 12, .65); backdrop-filter: blur(2px); }
.dlg textarea { width: 100%; margin-top: 10px; font-family: var(--mono); font-size: 12px; }
.dlg-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 12px; }
.example-list { list-style: none; margin: 6px 0 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.example-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  background: var(--panel2);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  padding: 8px 12px;
}
.example-desc { display: flex; flex-direction: column; gap: 2px; }

/* ---------- footer / toast ---------- */
.foot {
  padding: 10px 20px 22px;
  color: var(--muted);
  font-size: 12px;
  text-align: center;
  border-top: 1px solid var(--border-soft);
  margin-top: 6px;
}
.toast {
  position: fixed;
  left: 50%;
  bottom: 26px;
  transform: translateX(-50%);
  background: #1c2531;
  color: var(--text);
  border: 1px solid var(--accent);
  border-radius: 8px;
  padding: 9px 16px;
  font-size: 13px;
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s, transform .2s;
  z-index: 99;
  box-shadow: 0 6px 24px rgba(0, 0, 0, .4);
  max-width: min(560px, 90vw);
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(-6px); }
.toast.error { border-color: var(--err); }

@media print {
  .topbar, .preview-toolbar, .btn { display: none; }
}/* =====================================================================
 * Visual polish layer — dark CS2-flavored upgrade.
 * Appended on top of the base styles; same class names, no markup changes.
 * ===================================================================== */

/* ---------- tokens ---------- */
:root {
  --accent-grad: linear-gradient(135deg, #3d8bff 0%, #6a5cff 100%);
  --accent-glow: rgba(61, 139, 255, .35);
  --panel-grad: linear-gradient(180deg, rgba(255, 255, 255, .028) 0%, rgba(255, 255, 255, 0) 42%);
  --shadow-1: 0 1px 0 rgba(255, 255, 255, .04) inset, 0 8px 20px rgba(0, 0, 0, .28);
  --shadow-2: 0 10px 30px rgba(0, 0, 0, .42);
  --radius-lg: 14px;
}

/* ---------- page atmosphere ---------- */
html, body {
  background:
    linear-gradient(rgba(13, 17, 23, 0.82), rgba(13, 17, 23, 0.9)),
    url('../img/bg.jpg') center / cover no-repeat fixed,
    radial-gradient(900px 420px at 12% -8%, rgba(61, 139, 255, .10) 0%, transparent 60%),
    radial-gradient(700px 380px at 88% -6%, rgba(106, 92, 255, .09) 0%, transparent 55%),
    radial-gradient(1200px 600px at 20% -10%, #16202e 0%, var(--bg) 55%);
  background-color: var(--bg);
  background-attachment: fixed;
}
::selection { background: rgba(61, 139, 255, .35); color: #fff; }
h2 { letter-spacing: .4px; }

/* slim dark scrollbars */
* { scrollbar-width: thin; scrollbar-color: #2b3442 #0d1117; }
*::-webkit-scrollbar { width: 9px; height: 9px; }
*::-webkit-scrollbar-track { background: #0d1117; }
*::-webkit-scrollbar-thumb { background: #2b3442; border-radius: 6px; border: 2px solid #0d1117; }
*::-webkit-scrollbar-thumb:hover { background: #3d8bff; }

/* ---------- top bar ---------- */
.topbar {
  background: linear-gradient(180deg, rgba(23, 29, 38, .96) 0%, rgba(17, 22, 29, .92) 100%);
  backdrop-filter: blur(10px) saturate(1.2);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .05) inset, 0 8px 24px rgba(0, 0, 0, .35);
}
.topbar::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -1px;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--accent-glow), rgba(106, 92, 255, .35), transparent);
  pointer-events: none;
}
.logo {
  font-size: 28px;
  background: var(--accent-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  filter: drop-shadow(0 0 10px rgba(74, 163, 162, .45));
  transition: transform .25s ease;
}
.brand:hover .logo { transform: rotate(-8deg) scale(1.08); }
.brand-text h1 {
  background: linear-gradient(90deg, #fff 0%, #b9d2ff 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  letter-spacing: .5px;
}
.topbar-controls .btn { box-shadow: none; }

/* ---------- buttons ---------- */
.btn {
  background: linear-gradient(180deg, #232c38 0%, #1a212b 100%);
  border-color: #313d4e;
  border-radius: 8px;
  box-shadow: 0 1px 0 rgba(255, 255, 255, .05) inset, 0 3px 8px rgba(0, 0, 0, .25);
  transition: transform .12s ease, box-shadow .12s ease, border-color .12s ease, background .12s ease;
}
.btn:hover {
  border-color: var(--accent);
  background: linear-gradient(180deg, #2a3a4f 0%, #1f2836 100%);
  box-shadow: 0 4px 14px rgba(61, 139, 255, .22), 0 1px 0 rgba(255, 255, 255, .06) inset;
  transform: translateY(-1px);
}
.btn:active { transform: translateY(0); box-shadow: 0 1px 4px rgba(0, 0, 0, .3); }
.btn.accent {
  background: var(--accent-grad);
  border-color: rgba(120, 140, 255, .55);
  color: #fff;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .3);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .08) inset, 0 4px 16px rgba(61, 139, 255, .28);
}
.btn.accent:hover {
  background: linear-gradient(135deg, #4d97ff 0%, #7a6bff 100%);
  box-shadow: 0 6px 20px rgba(61, 139, 255, .4), 0 0 0 1px rgba(255, 255, 255, .1) inset;
  transform: translateY(-1px);
}
.btn.danger:hover { border-color: var(--err); box-shadow: 0 4px 14px rgba(240, 98, 109, .2); }
.btn:disabled { opacity: .35; cursor: not-allowed; transform: none !important; box-shadow: none !important; }
.btn.small { border-radius: 7px; }

/* ---------- inputs ---------- */
input[type="text"], input[type="number"], input:not([type]), select, textarea {
  background: #0b0f15;
  border-color: #2c3646;
  border-radius: 7px;
  box-shadow: 0 1px 0 rgba(255, 255, 255, .03) inset;
  transition: border-color .15s ease, box-shadow .15s ease, background .15s ease;
}
input:not(:disabled):hover, select:hover, textarea:hover { border-color: #3c4a5e; }
input:focus, select:focus, textarea:focus {
  border-color: var(--accent);
  background: #0c1220;
  box-shadow: 0 0 0 3px rgba(61, 139, 255, .16), 0 0 14px rgba(61, 139, 255, .18);
}
select {
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%238b98a9' stroke-width='1.6' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 9px center;
  padding-right: 26px;
}
input[type="checkbox"] { width: 15px; height: 15px; cursor: pointer; }
input[type="checkbox"]:indeterminate { accent-color: var(--warn); }

/* ---------- cards ---------- */
.card {
  background: linear-gradient(180deg, rgba(23, 29, 38, .75) 0%, rgba(20, 25, 33, .85) 100%), var(--panel);
  border: 1px solid #2b3442;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1);
  position: relative;
}
.card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .1), transparent);
  pointer-events: none;
}
.card h2 { position: relative; padding-left: 10px; }
.card h2::before {
  content: "";
  position: absolute;
  left: 0; top: 2px; bottom: 2px;
  width: 3px;
  border-radius: 2px;
  background: var(--accent-grad);
}
.card-head h2 { margin: 0; }
.field { gap: 5px; }
.f-label { letter-spacing: .2px; }
.help { line-height: 1.5; }

/* ---------- grade cards ---------- */
.grade-card {
  background: linear-gradient(180deg, rgba(255, 255, 255, .018) 0%, rgba(0, 0, 0, .06) 100%);
  border: 1px solid var(--border-soft);
  border-left-width: 3px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, .2);
  transition: box-shadow .15s ease, border-color .15s ease;
}
.grade-card:hover { box-shadow: 0 6px 16px rgba(0, 0, 0, .3); }
.grade-card[data-grade="0"] { border-left-color: var(--g1); }
.grade-card[data-grade="1"] { border-left-color: var(--g2); }
.grade-card[data-grade="2"] { border-left-color: var(--g3); }
.grade-card[data-grade="3"] { border-left-color: var(--g4); }
.grade-card[data-grade="4"] { border-left-color: var(--g5); }
.grade-card summary { gap: 8px; padding: 2px 0; }
.grade-card summary::before {
  color: var(--muted);
  width: 14px;
  height: 14px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  border-radius: 4px;
  font-size: 10px;
  background: #0b0f14;
  transition: transform .18s ease, color .18s ease, border-color .18s ease;
}
.grade-card[open] summary::before { transform: rotate(90deg); color: var(--accent); border-color: var(--accent); }
.grade-badge {
  text-shadow: 0 1px 2px rgba(0, 0, 0, .4);
  background: rgba(0, 0, 0, .4);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .06) inset;
}
.count-badge {
  background: #0a0e13;
  border-color: #2c3646;
  font-variant-numeric: tabular-nums;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .3) inset;
}

/* ---------- item cards ---------- */
.item-card {
  background: linear-gradient(180deg, rgba(255, 255, 255, .02) 0%, rgba(0, 0, 0, .04) 100%);
  border: 1px solid #232c38;
  border-radius: 9px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, .18);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.item-card:hover {
  border-color: #34445c;
  box-shadow: 0 4px 14px rgba(0, 0, 0, .3), 0 0 0 1px rgba(61, 139, 255, .08);
}
.item-no {
  background: #0b0f14;
  border: 1px solid var(--border-soft);
  border-radius: 6px;
  padding: 1px 6px;
  font-variant-numeric: tabular-nums;
}
.item-head { gap: 7px; }

/* ---------- price table ---------- */
.price-table th {
  letter-spacing: .6px;
  text-transform: uppercase;
  border-bottom: 1px solid #333f52;
  background: linear-gradient(180deg, rgba(255, 255, 255, .03), rgba(255, 255, 255, 0));
}
.price-table tbody tr:nth-child(even) td { background: rgba(255, 255, 255, .012); }
.price-table tr { transition: background .12s ease; }
.price-table tr:hover td { background: rgba(61, 139, 255, .06); }
.status-cell { display: inline-flex; align-items: center; gap: 5px; }
.status-cell::before {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 6px currentColor;
  flex: none;
}
.key-cell { font-variant-numeric: tabular-nums; }
.price-input { transition: border-color .15s ease, box-shadow .15s ease; }
.add-key-row .btn { box-shadow: none; }

/* ---------- preview ---------- */
.preview-toolbar { margin-bottom: 10px; }
.tab {
  border-radius: 8px 8px 0 0;
  letter-spacing: .3px;
  padding: 7px 14px;
  transition: background .15s ease, color .15s ease;
}
.tab:hover { color: var(--text); background: rgba(255, 255, 255, .04); }
.tab.active {
  background: linear-gradient(180deg, var(--panel2), #141a24);
  border-color: var(--accent);
  box-shadow: 0 -2px 12px rgba(61, 139, 255, .15);
}
.path-hint {
  background: linear-gradient(90deg, rgba(74, 163, 162, .14), rgba(74, 163, 162, .04));
  border-color: rgba(74, 163, 162, .35);
  letter-spacing: .4px;
}
.json-preview {
  background: linear-gradient(180deg, #0b0f16 0%, #080b10 100%);
  border-color: #2b3442;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .35), 0 0 0 1px rgba(255, 255, 255, .03) inset;
  color: #d3dfee;
}

/* ---------- issues ---------- */
.badge {
  letter-spacing: .3px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .3) inset;
}
.issue {
  border-left: 3px solid transparent;
  padding: 6px 12px 6px 9px;
  transition: background .12s ease, transform .12s ease, border-color .12s ease;
}
.issue.error { border-left-color: var(--err); }
.issue.warn { border-left-color: var(--warn); }
.issue.info { border-left-color: var(--info); }
.issue:hover { transform: translateX(2px); filter: brightness(1.12); }
.issue.ok { text-align: center; padding: 10px; border-left-color: var(--ok); }

/* ---------- version note ---------- */
.version-note {
  background: linear-gradient(90deg, rgba(79, 195, 247, .08), rgba(79, 195, 247, .02));
  border: 1px solid rgba(79, 195, 247, .28);
  box-shadow: 0 3px 10px rgba(0, 0, 0, .2);
}

/* ---------- dialogs ---------- */
.dlg {
  border-radius: 14px;
  border-color: #354156;
  box-shadow: 0 24px 60px rgba(0, 0, 0, .55), 0 0 0 1px rgba(255, 255, 255, .05) inset;
  animation: dlg-in .18s ease;
}
@keyframes dlg-in {
  from { opacity: 0; transform: translateY(10px) scale(.98); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}
.dlg::backdrop { background: rgba(3, 6, 10, .72); backdrop-filter: blur(4px); }
.dlg h2 {
  background: var(--accent-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  letter-spacing: .5px;
}
.example-item { transition: border-color .12s ease, transform .12s ease; box-shadow: 0 2px 8px rgba(0, 0, 0, .2); }
.example-item:hover { border-color: var(--accent); transform: translateY(-1px); }

/* ---------- toast ---------- */
.toast {
  background: linear-gradient(180deg, #232e3d, #171f2b);
  border-radius: 10px;
  border-color: var(--accent);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .06) inset, 0 10px 34px rgba(0, 0, 0, .5), 0 0 22px rgba(61, 139, 255, .18);
}
.toast.error { border-color: var(--err); box-shadow: 0 0 0 1px rgba(255, 255, 255, .05) inset, 0 10px 34px rgba(0, 0, 0, .5), 0 0 22px rgba(240, 98, 109, .2); }

/* ---------- misc polish ---------- */
.tacz-row {
  background: linear-gradient(135deg, rgba(61, 139, 255, .06), rgba(106, 92, 255, .04));
  border-color: rgba(61, 139, 255, .28);
  box-shadow: 0 2px 8px rgba(0, 0, 0, .2);
}
.random-slot b {
  letter-spacing: .4px;
  text-transform: uppercase;
  font-size: 10.5px;
}
.extra-key-input { flex: 1; }
/* ---------- collapsible sections ---------- */
.col-head {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  user-select: none;
  padding: 2px 0;
}
.col-head h2 {
  margin: 0;
  flex: 1;
  letter-spacing: .4px;
  transition: color .12s ease;
}
.col-head:hover h2 { color: #ffffff; }
.col-head .head-actions { margin-left: auto; }
.col-caret {
  flex: none;
  width: 19px;
  height: 19px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  font-size: 11px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: rgba(0, 0, 0, .25);
  transition: transform .18s ease, color .18s ease, border-color .18s ease;
}
.col-caret::before { content: "▾"; line-height: 1; }
.col-head:hover .col-caret { color: var(--accent); border-color: var(--accent); }
.card.collapsed .col-caret { transform: rotate(-90deg); }
.card.collapsed .col-caret::before { content: "▸"; }
.card.collapsed .col-body { display: none; }
.card.collapsed { box-shadow: 0 2px 8px rgba(0, 0, 0, .22); }

/* ---------- page navigation links ---------- */
.page-nav .tab {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  color: var(--muted);
  border-radius: 8px 8px 0 0;
  padding: 7px 14px;
}
.page-nav .tab:hover { color: var(--text); text-decoration: none; }
.page-nav .tab.active { color: #fff; }

/* ---------- name color picker ---------- */
.name-color-row { display: flex; align-items: center; gap: 6px; }
.name-color-row input[type="color"] {
  width: 40px;
  height: 30px;
  padding: 2px;
  flex: none;
  background: #0b0f15;
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
}
.name-color-row input[type="color"]:hover { border-color: var(--accent); }

/* ---------- tutorial dialog ---------- */
.tutorial-body { line-height: 1.75; font-size: 13px; margin-top: 8px; max-height: 55vh; overflow: auto; }
.tutorial-body ol { margin: 0; padding-left: 20px; }
.tutorial-body ol > li { margin: 8px 0; }
.tutorial-body ul { margin: 4px 0 0; padding-left: 18px; }
.tutorial-body code { white-space: nowrap; }

/* =====================================================================
 * Cream glassmorphism theme — appended override layer.
 * 奶白色毛玻璃：半透明奶白组件 + backdrop blur，透出背景封面图。
 * ===================================================================== */

/* ---------- tokens ---------- */
:root {
  --bg: #f4f0e6;
  --bg2: #efe9dc;
  --panel: rgba(255, 252, 244, .68);
  --panel2: rgba(250, 245, 235, .58);
  --border: #d9d1bf;
  --border-soft: #e5decb;
  --text: #38332b;
  --muted: #8b8374;
  --accent: #2f6fdb;
  --accent-2: #248f8e;
  --ok: #2e9b71;
  --warn: #b8860b;
  --err: #d94555;
  --info: #0e9fd8;
  --g1: #6f746e;
  --g2: #0e9fd8;
  --g3: #2f6fdb;
  --g4: #8a3ff0;
  --g5: #e8386b;
  --accent-grad: linear-gradient(135deg, #2f6fdb 0%, #7a55e8 100%);
  --accent-glow: rgba(47, 111, 219, .30);
  --panel-grad: linear-gradient(180deg, rgba(255,255,255,.65) 0%, rgba(255,255,255,0) 42%);
  --shadow-1: 0 1px 0 rgba(255,255,255,.6) inset, 0 10px 28px rgba(90, 80, 60, .16);
  --shadow-2: 0 16px 40px rgba(90, 80, 60, .22);
}

/* ---------- page atmosphere ---------- */
html, body {
  background:
    linear-gradient(rgba(250, 246, 236, .30), rgba(250, 246, 236, .44)),
    url('../img/bg.jpg') center / cover no-repeat fixed,
    radial-gradient(900px 420px at 12% -8%, rgba(120, 170, 255, .16) 0%, transparent 60%),
    radial-gradient(700px 380px at 88% -6%, rgba(200, 170, 255, .12) 0%, transparent 55%),
    radial-gradient(1200px 600px at 20% -10%, #f8f4ea 0%, var(--bg) 55%);
  background-color: var(--bg);
  background-attachment: fixed;
}
::selection { background: rgba(47, 111, 219, .45); color: #fff; }
h1 { color: var(--text); }
h2 { color: #2b2620; }

/* ---------- cream scrollbars ---------- */
* { scrollbar-width: thin; scrollbar-color: #cfc6b2 #efe9dc; }
*::-webkit-scrollbar-track { background: rgba(255, 252, 244, .5); }
*::-webkit-scrollbar-thumb { background: #cfc6b2; border-radius: 6px; border: 2px solid rgba(255, 252, 244, .6); }
*::-webkit-scrollbar-thumb:hover { background: var(--accent); }

/* ---------- top bar ---------- */
.topbar {
  background: linear-gradient(180deg, rgba(255, 252, 244, .62) 0%, rgba(248, 243, 232, .56) 100%);
  backdrop-filter: blur(14px) saturate(1.5);
  -webkit-backdrop-filter: blur(14px) saturate(1.5);
  border-bottom-color: rgba(200, 190, 168, .55);
  box-shadow: 0 1px 0 rgba(255,255,255,.7) inset, 0 10px 30px rgba(90, 80, 60, .14);
}
.topbar::after { background: linear-gradient(90deg, transparent, var(--accent-glow), rgba(122, 85, 232, .30), transparent); }
.brand-text h1 {
  background: linear-gradient(90deg, #3a3529 0%, #2f6fdb 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* ---------- buttons ---------- */
.btn {
  background: linear-gradient(180deg, rgba(255, 253, 248, .80) 0%, rgba(242, 237, 224, .72) 100%);
  border-color: #d9d1bf;
  color: var(--text);
  box-shadow: 0 1px 0 rgba(255,255,255,.8) inset, 0 2px 6px rgba(90, 80, 60, .12);
}
.btn:hover {
  border-color: var(--accent);
  background: linear-gradient(180deg, #ffffff 0%, #f2efe6 100%);
  box-shadow: 0 4px 14px rgba(47, 111, 219, .18);
}
.btn.accent {
  background: var(--accent-grad);
  border-color: rgba(80, 110, 220, .6);
  color: #fff;
  text-shadow: 0 1px 2px rgba(20, 20, 40, .25);
  box-shadow: 0 0 0 1px rgba(255,255,255,.35) inset, 0 4px 14px rgba(47, 111, 219, .25);
}
.btn.accent:hover { background: linear-gradient(135deg, #3d7ef0 0%, #8662f2 100%); }
.btn.danger { color: var(--err); }
.btn.danger:hover { border-color: var(--err); background: rgba(217, 69, 85, .08); box-shadow: 0 4px 12px rgba(217, 69, 85, .15); }

/* ---------- inputs ---------- */
input[type="text"], input[type="number"], input:not([type]), select, textarea {
  background: rgba(255, 253, 248, .60);
  border-color: #d9d1bf;
  color: var(--text);
  box-shadow: 0 1px 0 rgba(255,255,255,.7) inset;
}
input:not(:disabled):hover, select:hover, textarea:hover { border-color: #b9ad94; }
input:focus, select:focus, textarea:focus {
  border-color: var(--accent);
  background: rgba(255, 255, 255, .88);
  box-shadow: 0 0 0 3px rgba(47, 111, 219, .14), 0 0 10px rgba(47, 111, 219, .12);
}
select {
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%238b8374' stroke-width='1.6' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
}
.name-color-row input[type="color"] { background: #fff; border-color: var(--border); }

/* ---------- cards ---------- */
.card {
  background: linear-gradient(180deg, rgba(255, 252, 244, .62) 0%, rgba(250, 245, 234, .50) 100%), var(--panel);
  backdrop-filter: blur(16px) saturate(1.4);
  -webkit-backdrop-filter: blur(16px) saturate(1.4);
  border-color: rgba(214, 204, 180, .7);
  box-shadow: var(--shadow-1);
}
.card::before { background: linear-gradient(90deg, transparent, rgba(255,255,255,.8), transparent); }
.card h2::before { background: var(--accent-grad); }

.grade-card {
  background: linear-gradient(180deg, rgba(255, 253, 248, .52) 0%, rgba(248, 242, 230, .42) 100%);
  backdrop-filter: blur(12px) saturate(1.35);
  -webkit-backdrop-filter: blur(12px) saturate(1.35);
  border-color: rgba(215, 205, 183, .65);
  box-shadow: 0 4px 14px rgba(90, 80, 60, .12);
}
.grade-card:hover { box-shadow: 0 6px 20px rgba(90, 80, 60, .18); }
.grade-card summary::before { background: rgba(255, 253, 248, .72); border-color: var(--border); color: var(--muted); }
.grade-card[open] summary::before { color: var(--accent); border-color: var(--accent); }
.grade-badge { background: rgba(255, 255, 255, .5); text-shadow: none; box-shadow: 0 0 0 1px rgba(255,255,255,.5) inset; }

.item-card {
  background: linear-gradient(180deg, rgba(255, 253, 248, .45) 0%, rgba(248, 243, 232, .38) 100%);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-color: rgba(210, 200, 178, .6);
  box-shadow: 0 2px 8px rgba(90, 80, 60, .1);
}
.item-card:hover { border-color: #c9bc9d; box-shadow: 0 6px 18px rgba(90, 80, 60, .16); }
.item-no { background: rgba(255, 253, 248, .66); border-color: var(--border-soft); color: var(--muted); }
.count-badge { background: rgba(255, 253, 248, .58); border-color: var(--border); color: var(--muted); box-shadow: none; }
.item-adv { border-color: rgba(200, 190, 168, .65); background: rgba(255, 253, 248, .28); }

/* ---------- price table ---------- */
.price-table th {
  color: var(--muted);
  border-bottom-color: #cfc6b2;
  background: linear-gradient(180deg, rgba(255,255,255,.45), rgba(255,255,255,0));
}
.price-table td { border-bottom-color: var(--border-soft); }
.price-table tbody tr:nth-child(even) td { background: rgba(255, 253, 248, .30); }
.price-table tr:hover td { background: rgba(47, 111, 219, .08); }

/* ---------- preview ---------- */
.tab { color: var(--muted); border-color: var(--border); background: rgba(255, 253, 248, .30); }
.tab:hover { color: var(--text); background: rgba(255, 253, 248, .48); }
.tab.active {
  color: var(--text);
  background: linear-gradient(180deg, rgba(255, 252, 244, .76), rgba(250, 246, 236, .66));
  border-color: var(--accent);
}
.page-nav .tab.active { color: var(--text); }
.path-hint { color: var(--accent-2); background: rgba(36, 143, 142, .08); border-color: rgba(36, 143, 142, .3); }
.json-preview {
  background: linear-gradient(180deg, rgba(255, 253, 248, .66) 0%, rgba(250, 246, 236, .54) 100%);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-color: #d9d1bf;
  color: #3d3f47;
  box-shadow: 0 6px 18px rgba(90, 80, 60, .14), 0 0 0 1px rgba(255,255,255,.5) inset;
}

/* ---------- issues / badges ---------- */
.badge { background: rgba(255, 255, 255, .4); box-shadow: none; }
.issue.error { background: rgba(217, 69, 85, .07); border-color: rgba(217, 69, 85, .3); }
.issue.warn { background: rgba(184, 134, 11, .08); border-color: rgba(184, 134, 11, .32); }
.issue.info { background: rgba(14, 159, 216, .07); border-color: rgba(14, 159, 216, .3); }
.issue.ok { background: rgba(46, 155, 113, .07); border-color: rgba(46, 155, 113, .3); }
.issue:hover { filter: brightness(1.03); }
.version-note { background: rgba(14, 159, 216, .07); border-color: rgba(14, 159, 216, .28); box-shadow: 0 3px 10px rgba(90, 80, 60, .1); }

/* ---------- dialogs ---------- */
.dlg {
  background: linear-gradient(180deg, rgba(255, 252, 244, .80) 0%, rgba(250, 246, 236, .70) 100%);
  backdrop-filter: blur(18px) saturate(1.35);
  -webkit-backdrop-filter: blur(18px) saturate(1.35);
  border-color: rgba(210, 200, 178, .8);
  box-shadow: 0 24px 60px rgba(70, 62, 45, .3), 0 0 0 1px rgba(255,255,255,.6) inset;
}
.dlg::backdrop { background: rgba(92, 84, 66, .4); backdrop-filter: blur(3px); }
.example-item {
  background: linear-gradient(180deg, rgba(255, 253, 248, .64), rgba(248, 243, 232, .48));
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-color: var(--border-soft);
  box-shadow: 0 2px 8px rgba(90, 80, 60, .1);
}

/* ---------- toasts ---------- */
.toast {
  background: linear-gradient(180deg, rgba(255, 253, 248, .84), rgba(248, 243, 232, .76));
  backdrop-filter: blur(14px) saturate(1.4);
  -webkit-backdrop-filter: blur(14px) saturate(1.4);
  color: var(--text);
  border-color: var(--accent);
  box-shadow: 0 0 0 1px rgba(255,255,255,.6) inset, 0 12px 34px rgba(70, 62, 45, .25);
}
.toast.error { border-color: var(--err); }

/* ---------- tooltip ---------- */
.field-tooltip {
  background: rgba(255, 253, 248, .90);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-color: var(--accent);
  color: var(--text);
  box-shadow: 0 10px 26px rgba(70, 62, 45, .22);
}

/* ---------- misc ---------- */
.tacz-row { background: linear-gradient(135deg, rgba(47,111,219,.07), rgba(122,85,232,.05)); border-color: rgba(47,111,219,.24); box-shadow: 0 2px 8px rgba(90, 80, 60, .08); }
.col-caret { background: rgba(255, 253, 248, .58); border-color: var(--border); color: var(--muted); }
.col-head:hover h2 { color: var(--text); }
code { background: rgba(255, 253, 248, .7); border-color: var(--border-soft); color: var(--text); }


/* =====================================================================
 * Liquid glass fine-tune — extra transparency, stronger blur/saturation,
 * frosted highlights and inner rims so the cover art reads through.
 * ===================================================================== */
html, body {
  background:
    linear-gradient(rgba(250, 246, 236, .16), rgba(250, 246, 236, .26)),
    url('../img/bg.jpg') center / cover no-repeat fixed,
    radial-gradient(900px 420px at 12% -8%, rgba(120, 170, 255, .16) 0%, transparent 60%),
    radial-gradient(700px 380px at 88% -6%, rgba(200, 170, 255, .12) 0%, transparent 55%),
    radial-gradient(1200px 600px at 20% -10%, #f8f4ea 0%, var(--bg) 55%);
  background-color: var(--bg);
  background-attachment: fixed;
}

.topbar {
  background: linear-gradient(180deg, rgba(255, 252, 244, .42) 0%, rgba(248, 243, 232, .34) 100%);
  backdrop-filter: blur(18px) saturate(1.8);
  -webkit-backdrop-filter: blur(18px) saturate(1.8);
  border-bottom-color: rgba(255, 255, 255, .35);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .5) inset, 0 10px 30px rgba(90, 80, 60, .12);
}

.btn {
  background: linear-gradient(180deg, rgba(255, 253, 248, .62) 0%, rgba(242, 237, 224, .52) 100%);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .7) inset, 0 2px 6px rgba(90, 80, 60, .10);
}

input[type="text"], input[type="number"], input:not([type]), select, textarea {
  background: rgba(255, 253, 248, .46);
}
input:focus, select:focus, textarea:focus {
  background: rgba(255, 255, 255, .80);
}

.card {
  background: linear-gradient(180deg, rgba(255, 252, 244, .42) 0%, rgba(250, 245, 234, .30) 100%), var(--panel);
  backdrop-filter: blur(20px) saturate(1.8);
  -webkit-backdrop-filter: blur(20px) saturate(1.8);
  border-color: rgba(255, 255, 255, .42);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .6) inset, 0 0 0 1px rgba(255, 255, 255, .14) inset, 0 12px 32px rgba(90, 80, 60, .16);
}
.card::before {
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .9), transparent);
}

.grade-card {
  background: linear-gradient(180deg, rgba(255, 253, 248, .36) 0%, rgba(248, 242, 230, .26) 100%);
  backdrop-filter: blur(14px) saturate(1.7);
  -webkit-backdrop-filter: blur(14px) saturate(1.7);
  border-color: rgba(255, 255, 255, .38);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .5) inset, 0 8px 22px rgba(90, 80, 60, .12);
}
.grade-card summary::before { background: rgba(255, 253, 248, .6); }

.item-card {
  background: linear-gradient(180deg, rgba(255, 253, 248, .30) 0%, rgba(248, 243, 232, .22) 100%);
  backdrop-filter: blur(10px) saturate(1.6);
  -webkit-backdrop-filter: blur(10px) saturate(1.6);
  border-color: rgba(255, 255, 255, .36);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .45) inset, 0 4px 14px rgba(90, 80, 60, .10);
}
.item-no { background: rgba(255, 253, 248, .55); }
.count-badge { background: rgba(255, 253, 248, .48); }
.item-adv { background: rgba(255, 253, 248, .2); }

.price-table th {
  background: linear-gradient(180deg, rgba(255, 255, 255, .35), rgba(255, 255, 255, 0));
}
.price-table tbody tr:nth-child(even) td { background: rgba(255, 253, 248, .22); }

.tab { background: rgba(255, 253, 248, .24); }
.tab:hover { background: rgba(255, 253, 248, .40); }
.tab.active {
  background: linear-gradient(180deg, rgba(255, 252, 244, .68), rgba(250, 246, 236, .56));
}

.json-preview {
  background: linear-gradient(180deg, rgba(255, 253, 248, .55) 0%, rgba(250, 246, 236, .42) 100%);
  backdrop-filter: blur(14px) saturate(1.7);
  -webkit-backdrop-filter: blur(14px) saturate(1.7);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .6) inset, 0 8px 20px rgba(90, 80, 60, .12);
}

.dlg {
  background: linear-gradient(180deg, rgba(255, 252, 244, .58) 0%, rgba(250, 246, 236, .46) 100%);
  backdrop-filter: blur(26px) saturate(1.9);
  -webkit-backdrop-filter: blur(26px) saturate(1.9);
  border-color: rgba(255, 255, 255, .5);
  box-shadow: 0 24px 60px rgba(70, 62, 45, .25), 0 0 0 1px rgba(255, 255, 255, .5) inset;
}
.example-item {
  background: linear-gradient(180deg, rgba(255, 253, 248, .5), rgba(248, 243, 232, .36));
}

.toast {
  background: linear-gradient(180deg, rgba(255, 253, 248, .68), rgba(248, 243, 232, .58));
  backdrop-filter: blur(18px) saturate(1.7);
  -webkit-backdrop-filter: blur(18px) saturate(1.7);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .5) inset, 0 12px 34px rgba(70, 62, 45, .22);
}

.field-tooltip {
  background: rgba(255, 253, 248, .88);
  backdrop-filter: blur(16px) saturate(1.6);
  -webkit-backdrop-filter: blur(16px) saturate(1.6);
}

.badge { background: rgba(255, 255, 255, .3); }
.col-caret { background: rgba(255, 253, 248, .48); }

/* =====================================================================
 * Layout fine-tune — spacing rhythm, narrow-screen behavior, dialog and
 * print polish. Appended override layer; same classes, no markup changes.
 * ===================================================================== */

/* ---------- layout: keep ultra-wide monitors comfortable ---------- */
.layout {
  max-width: 1760px;
  margin-left: auto;
  margin-right: auto;
}

/* ---------- top bar: tighter, predictable wrapping ---------- */
.topbar { gap: 10px 16px; }

@media (max-width: 1080px) {
  .topbar { padding: 10px 16px; gap: 8px 12px; }
  .topbar-controls { justify-content: flex-start; }
  .topbar-controls .btn { padding: 5px 10px; }
}

@media (max-width: 720px) {
  .topbar { padding: 8px 12px; gap: 7px 10px; }
  .brand { gap: 8px; }
  .logo { font-size: 22px; }
  .brand-text p { display: none; }            /* 副标题让位给控件 */
  .topbar-controls { gap: 5px; }
  .ctl { font-size: 11px; }
  .ctl select { padding: 4px 8px; }
  .topbar-controls .btn { padding: 4px 8px; }
}

/* ---------- cards: consistent rhythm on small screens ---------- */
@media (max-width: 720px) {
  /* 16px input text prevents iOS Safari's focus zoom */
  input[type="text"], input[type="number"], input:not([type]), select, textarea {
    font-size: 16px;
  }
  .card { padding: 12px 12px; }
  .card h2 { padding-left: 8px; }
  .version-note { margin: 4px 0 10px; padding: 7px 10px; }
  .grade-card { padding: 8px 10px; }
}

/* ---------- item rows: uniform narrow-screen packing ---------- */
@media (max-width: 720px) {
  .item-card { padding: 8px; }
  .item-head { gap: 6px; }
  .item-head select { max-width: 46%; }
  .item-head .grow { min-width: 96px; }
  .row.inline { gap: 7px; }
  .row.inline .mini { flex: 1 1 42%; }
  .row.inline .mini.sep { flex: 0 0 auto; }
  .random-slot input { width: 76px; }
  .entity-row { flex-wrap: wrap; }
  .entity-row .grow { min-width: 140px; }
  .tacz-row { padding: 9px 10px; }
}

/* ---------- price table: scroll rather than crush on narrow screens ---------- */
@media (max-width: 640px) {
  #card-prices { overflow-x: auto; }
  .price-table { min-width: 540px; }
  .price-input { width: 100%; }
  .add-key-row { flex-wrap: wrap; }
  .add-key-row .grow { min-width: 150px; }
}

/* ---------- dialogs: never taller than the viewport ---------- */
.dlg {
  max-height: min(88vh, 760px);
  overflow: auto;
}
.example-list { max-height: 58vh; overflow: auto; padding-right: 4px; }
#import-textarea { max-height: 46vh; }

/* ---------- keyboard focus affordance ---------- */
.btn:focus-visible,
.tab:focus-visible,
summary:focus-visible,
.example-item:focus-within,
.col-head:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ---------- print: flat light page, no glass ---------- */
@media print {
  html, body {
    background: #fff !important;
    background-attachment: scroll !important;
  }
  .card, .grade-card, .item-card, .json-preview, .prob-panel, .dlg,
  .example-item, .toast, .field-tooltip {
    background: #fff !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    box-shadow: none !important;
    break-inside: avoid;
  }
  .card h2 { color: #222; }
  .json-preview, .prob-panel { max-height: none; color: #222 !important; border-color: #999 !important; }
  .right { position: static !important; }
  body { color: #222; }
  .muted, .help, .f-label { color: #555; }
}

/* ---------- toast placement on small viewports ---------- */
@media (max-width: 640px) {
  .toast { bottom: 14px; max-width: calc(100vw - 24px); }
  .foot { padding: 8px 12px 16px; }
}

/* ---------- top-bar "Advanced" toggle ---------- */
.advanced-toggle {
  white-space: nowrap;
  font-size: 12.5px;
  color: var(--muted);
  padding: 4px 10px;
  border: 1px solid var(--border);
  border-radius: 7px;
  background: rgba(255, 253, 248, .42);
  transition: border-color .15s ease, color .15s ease, background .15s ease;
}
.advanced-toggle:hover { border-color: var(--accent); color: var(--text); }
.advanced-toggle input { width: 14px; height: 14px; accent-color: var(--accent); }
.advanced-toggle:has(input:checked) {
  color: var(--text);
  border-color: var(--accent);
  background: rgba(47, 111, 219, .10);
  box-shadow: 0 0 0 1px rgba(47, 111, 219, .25) inset;
}

/* ---------- advanced custom-icon row ---------- */
.icon-row { display: flex; gap: 6px; align-items: center; }
.icon-row input.grow { min-width: 0; }
.icon-row select { max-width: 160px; flex: none; }
.icon-hidden-hint {
  margin-top: 4px;
  font-size: 12px;
  color: var(--muted);
  background: rgba(184, 134, 11, .10);
  border: 1px dashed rgba(184, 134, 11, .35);
  border-radius: 7px;
  padding: 6px 10px;
  line-height: 1.5;
}

@media (max-width: 640px) {
  .icon-row { flex-wrap: wrap; }
  .icon-row select { max-width: 100%; width: 100%; }
}

/* ---------- advanced-fields badge (basic mode) ---------- */
.hidden-adv-badge {
  margin-left: 2px;
  color: var(--warn);
  border-color: rgba(184, 134, 11, .55);
  background: rgba(184, 134, 11, .10);
  font-size: 11px;
  white-space: nowrap;
}
.hidden-adv-badge:hover {
  color: #fff;
  border-color: var(--warn);
  background: rgba(184, 134, 11, .55);
  box-shadow: 0 2px 8px rgba(184, 134, 11, .25);
}
.hidden-adv-badge:focus-visible { outline: 2px solid var(--accent); }

/* ---------- view switch + probability table ---------- */
.view-switch { margin-bottom: 0; }
.view-switch .tab { font-size: 12px; padding: 4px 10px; }
.prob-panel {
  margin: 0;
  /* cream glass, mirrors .json-preview above (its dark-era colors were never
     adapted when the cream glass layer landed) */
  background: linear-gradient(180deg, rgba(255, 253, 248, .55) 0%, rgba(250, 246, 236, .42) 100%);
  backdrop-filter: blur(14px) saturate(1.7);
  -webkit-backdrop-filter: blur(14px) saturate(1.7);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .6) inset, 0 8px 20px rgba(90, 80, 60, .12);
  border: 1px solid var(--border);
  border-top: none;
  border-radius: 0 0 var(--radius) var(--radius);
  padding: 12px 14px;
  max-height: 46vh;
  overflow: auto;
  color: #3d3f47;
  font-size: 12px;
}
.prob-panel h2 { margin: 0 0 8px; font-size: 13px; color: var(--text); }
.prob-warn {
  color: var(--warn);
  background: rgba(184, 134, 11, .10);
  border: 1px dashed rgba(184, 134, 11, .35);
  border-radius: 6px;
  padding: 6px 10px;
  margin: 0 0 10px;
}
.prob-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
}
.prob-table th, .prob-table td {
  text-align: left;
  padding: 5px 8px;
  border-bottom: 1px solid rgba(60, 52, 38, .14);
  vertical-align: top;
}
.prob-table th { color: var(--muted); font-weight: 600; white-space: nowrap; }
.prob-table td:nth-child(2), .prob-table td:nth-child(3) {
  text-align: right;
  font-family: var(--mono);
  white-space: nowrap;
}
.prob-table tr.prob-grade td {
  border-top: 1px solid rgba(60, 52, 38, .20);
  color: var(--text);
  padding-top: 8px;
}
.prob-table tr.prob-grade:first-child td { border-top: none; }
.prob-table tr.prob-item td {
  color: #5f5748;
  padding-left: 22px;
}
.prob-table td.prob-item-name .prob-disabled {
  color: var(--warn);
  font-size: 11px;
}
.prob-table td.prob-item-name .prob-src-id {
  color: var(--muted);
  font-size: 11px;
  margin-left: 6px;
}
.prob-table tr.prob-empty td {
  color: var(--muted);
  font-style: italic;
  padding-left: 22px;
}
.prob-panel .help { margin: 8px 0 0; }

/* ---------- price table: never crush inside a narrow left column ---------- */
#card-prices { overflow-x: auto; }
.price-table { min-width: 560px; }

/* =====================================================================
 * Motion layer — feedback-only micro animations.
 * Everything animates transform/opacity only (no layout thrash), and the
 * whole layer collapses to instant under prefers-reduced-motion.
 * ===================================================================== */

/* undo/redo (and all buttons): enabled/disabled fades instead of a hard swap */
.btn {
  transition: transform .12s ease, box-shadow .12s ease, border-color .12s ease,
    background .12s ease, opacity .18s ease;
}

/* JSON preview: a slim accent bar on the left edge lights up for one flash
 * each time the preview is rebuilt — "the preview is in sync with your edits". */
.json-preview { position: relative; }
.json-preview::after {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
  border-radius: 0 2px 2px 0;
  background: var(--accent-2);
  opacity: 0;
  pointer-events: none;
}
.json-preview.json-sync::after { animation: json-sync-bar .45s ease-out; }
@keyframes json-sync-bar {
  0% { opacity: .85; }
  100% { opacity: 0; }
}

/* validation badges: one pulse when their count changes after a re-validate */
@keyframes badge-pulse {
  0% { transform: scale(1); }
  35% { transform: scale(1.14); }
  100% { transform: scale(1); }
}
.issue-summary .badge.badge-pulse { animation: badge-pulse .32s ease; }

/* prize-pool item cards: a newly added card slides in; a removed card is
 * collapsed in place by app.js before the splice (the list DOM is regenerated,
 * so exit animation must happen pre-rebuild). */
@keyframes item-enter {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}
.item-card.item-enter { animation: item-enter .16s ease-out; }
.item-card.item-leave {
  overflow: hidden;
  transition: height .14s ease, opacity .14s ease, margin .14s ease, padding .14s ease;
}

/* probability table: rows drift in once when the user switches to the view */
@keyframes prob-row-in {
  from { opacity: 0; transform: translateY(3px); }
  to { opacity: 1; transform: none; }
}

/* accessibility guardrail: honor the OS "reduce motion" setting for every
 * animation and transition, functional flash included. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* =====================================================================
 * File workspace sidebar (multi-draft).
 * ===================================================================== */
.filebar {
  position: sticky;
  top: 68px;
  align-self: start;
  width: 210px;
  border: 1px solid var(--border);
  border-radius: var(--radius, 10px);
  background: rgba(255, 253, 248, .42);
  backdrop-filter: blur(12px) saturate(1.5);
  -webkit-backdrop-filter: blur(12px) saturate(1.5);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .5) inset, 0 6px 18px rgba(90, 80, 60, .10);
  overflow: hidden;
  transition: width .18s ease;
}
.filebar-head {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 10px;
  border-bottom: 1px solid rgba(60, 52, 38, .12);
}
.filebar-title { font-weight: 600; font-size: 13px; flex: 1; white-space: nowrap; }
.filebar-toggle {
  border: none; background: transparent; color: var(--muted);
  cursor: pointer; font-size: 12px; padding: 2px 4px; border-radius: 4px;
  transition: transform .18s ease;
}
.filebar-toggle:hover { color: var(--text); background: rgba(60, 52, 38, .08); }
.filebar.collapsed { width: 46px; }
.filebar.collapsed .filebar-title,
.filebar.collapsed .file-list { display: none; }
.filebar.collapsed .filebar-toggle { transform: rotate(180deg); }
.filebar.collapsed .filebar-head { border-bottom: none; justify-content: center; }
.filebar.collapsed #file-add { display: none; }

.file-list { display: flex; flex-direction: column; padding: 6px; gap: 2px; max-height: 46vh; overflow: auto; }
.file-item {
  display: flex; align-items: center; gap: 4px;
  padding: 6px 8px; border-radius: 7px; cursor: pointer;
  border: 1px solid transparent;
  transition: background .12s ease, border-color .12s ease;
}
.file-item:hover { background: rgba(60, 52, 38, .07); }
.file-item.active {
  background: rgba(255, 252, 244, .72);
  border-color: rgba(60, 52, 38, .18);
  font-weight: 600;
}
.file-name {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 12.5px;
  font-family: var(--mono);
}
.file-actions { display: none; gap: 2px; }
.file-item:hover .file-actions, .file-item.active:hover .file-actions { display: inline-flex; }
.file-btn {
  border: none; background: transparent; color: var(--muted);
  cursor: pointer; font-size: 11.5px; line-height: 1;
  padding: 4px 5px; border-radius: 4px;
  transition: color .12s ease, background .12s ease;
}
.file-btn:hover { color: var(--text); background: rgba(60, 52, 38, .12); }
.file-btn.accent { color: #2f6fdb; font-weight: 700; font-size: 14px; padding: 2px 6px; }
.file-empty { color: var(--muted); font-size: 12px; padding: 10px; text-align: center; }

@media (max-width: 1180px) {
  .filebar { position: static; width: 100%; }
  .filebar.collapsed { width: 100%; }
  .file-list { max-height: 28vh; }
}
@media print {
  .filebar { display: none !important; }
}

/* =====================================================================
 * Dark theme layer — scope-qualified revival of the in-file dark base
 * + polish layers, enabled by html[data-theme="dark"] (theme toggle).
 * Appended last so it wins the cascade over the cream glass layer.
 * ===================================================================== */

html[data-theme="dark"] {
  --bg: #0d1117;
  --bg2: #10151c;
  --panel: #161b22;
  --panel2: #1c232e;
  --border: #2b3442;
  --border-soft: #232c38;
  --text: #e6edf3;
  --muted: #8b98a9;
  --accent: #3d8bff;
  --accent-2: #4aa3a2;
  --ok: #3fb98a;
  --warn: #e3b341;
  --err: #f0626d;
  --info: #4fc3f7;
  --g1: #9aa4af;
  --g2: #4fc3f7;
  --g3: #4b8bff;
  --g4: #b06cff;
  --g5: #ff5f8f;
  --radius: 10px;
  --mono: ui-monospace, "Cascadia Code", Consolas, "Courier New", monospace;

}
html[data-theme="dark"],
html[data-theme="dark"] body {
  color: var(--text);
}
html[data-theme="dark"] h2 {
  color: #ffffff;
}
html[data-theme="dark"] h3 {
  color: var(--muted);
}
html[data-theme="dark"] code {
  background: #0b0f14;
  border: 1px solid var(--border-soft);
  border-radius: 4px;
}
html[data-theme="dark"] .topbar {
  background: rgba(22, 27, 34, .92);
  border-bottom: 1px solid var(--border);
  backdrop-filter: blur(4px);
}
html[data-theme="dark"] .logo {
  color: var(--accent-2);
  text-shadow: 0 0 12px rgba(74, 163, 162, .55);
}
html[data-theme="dark"] .brand-text p {
  color: var(--muted);
}
html[data-theme="dark"] .ctl {
  color: var(--muted);
}
html[data-theme="dark"] .btn {
  color: var(--text);
  background: var(--panel2);
  border: 1px solid var(--border);
  border-radius: 7px;
}
html[data-theme="dark"] .btn:hover {
  border-color: var(--accent);
  background: #222b38;
}
html[data-theme="dark"] .btn.small {
  border-radius: 6px;
}
html[data-theme="dark"] .btn.accent {
  background: #1f3b66;
  border-color: #2f5aa0;
}
html[data-theme="dark"] .btn.accent:hover {
  background: #25467c;
}
html[data-theme="dark"] .btn.danger {
  color: var(--err);
}
html[data-theme="dark"] .btn.danger:hover {
  border-color: var(--err);
  background: #2b1c20;
}
html[data-theme="dark"] input[type="text"],
html[data-theme="dark"] input[type="number"],
html[data-theme="dark"] input:not([type]),
html[data-theme="dark"] select,
html[data-theme="dark"] textarea {
  color: var(--text);
  background: #0d1219;
  border: 1px solid var(--border);
  border-radius: 6px;
  outline: none;
}
html[data-theme="dark"] input:focus,
html[data-theme="dark"] select:focus,
html[data-theme="dark"] textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px rgba(61, 139, 255, .18);
}
html[data-theme="dark"] input[type="checkbox"] {
  accent-color: var(--accent-2);
}
html[data-theme="dark"] .chk {
  color: var(--muted);
}
html[data-theme="dark"] .muted {
  color: var(--muted);
}
html[data-theme="dark"] .help {
  color: var(--muted);
}
html[data-theme="dark"] .danger-input {
  border-color: rgba(240, 98, 109, .55) !important;
}
html[data-theme="dark"] .card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
html[data-theme="dark"] .f-label {
  color: var(--muted);
}
html[data-theme="dark"] .tacz-row {
  background: rgba(255,255,255,.025);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
}
html[data-theme="dark"] .field-tooltip {
  background: rgba(11, 15, 20, .96);
  border: 1px solid var(--accent);
  border-radius: 7px;
  color: var(--text);
  box-shadow: 0 8px 22px rgba(0, 0, 0, .55);
}
html[data-theme="dark"] .issue[data-issue-path]:hover {
  outline: 1px solid var(--border);
}
html[data-theme="dark"] .flash-highlight {
  outline: 2px solid var(--warn) !important;
  outline-offset: 2px;
  border-radius: 4px;
}
html[data-theme="dark"] .tacz-switch {
  color: var(--text);
}
html[data-theme="dark"] .tacz-switch input {
  accent-color: var(--accent);
}
html[data-theme="dark"] .mini {
  color: var(--muted);
}
html[data-theme="dark"] .mini.sep {
  color: var(--muted);
}
html[data-theme="dark"] .random-slot b {
  color: var(--muted);
}
html[data-theme="dark"] .grade-card {
  background: var(--panel2);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
}
html[data-theme="dark"] .grade-card summary::before {
  color: var(--muted);
}
html[data-theme="dark"] .grade-badge {
  border-radius: 10px;
  border: 1px solid currentColor;
  background: rgba(0, 0, 0, .25);
}
html[data-theme="dark"] .g1 {
  color: var(--g1);
}
html[data-theme="dark"] .g2 {
  color: var(--g2);
}
html[data-theme="dark"] .g3 {
  color: var(--g3);
}
html[data-theme="dark"] .g4 {
  color: var(--g4);
}
html[data-theme="dark"] .g5 {
  color: var(--g5);
}
html[data-theme="dark"] .count-badge {
  background: #0b0f14;
  border: 1px solid var(--border-soft);
  border-radius: 10px;
  color: var(--muted);
}
html[data-theme="dark"] .item-card {
  background: #11161f;
  border: 1px solid var(--border-soft);
  border-radius: 8px;
}
html[data-theme="dark"] .item-no {
  color: var(--muted);
}
html[data-theme="dark"] .item-adv {
  border: 1px dashed var(--border);
  border-radius: 6px;
}
html[data-theme="dark"] .item-adv summary {
  color: var(--muted);
}
html[data-theme="dark"] .item-adv .adv-badge {
  color: var(--accent);
  border: 1px solid var(--accent);
  border-radius: 9px;
}
html[data-theme="dark"] .price-table {
  border-collapse: collapse;
}
html[data-theme="dark"] .price-table th {
  color: var(--muted);
  border-bottom: 1px solid var(--border);
}
html[data-theme="dark"] .price-table td {
  border-bottom: 1px solid var(--border-soft);
}
html[data-theme="dark"] .price-table tr:hover td {
  background: rgba(255, 255, 255, .02);
}
html[data-theme="dark"] .recycle-cell {
  color: var(--accent-2);
}
html[data-theme="dark"] .status-ok {
  color: var(--ok);
}
html[data-theme="dark"] .status-warn {
  color: var(--warn);
}
html[data-theme="dark"] .status-muted {
  color: var(--muted);
}
html[data-theme="dark"] .extra-tag {
  color: var(--info);
}
html[data-theme="dark"] .tab {
  color: var(--muted);
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 7px 7px 0 0;
}
html[data-theme="dark"] .tab.active {
  color: #fff;
  background: var(--panel2);
  border-color: var(--accent);
}
html[data-theme="dark"] .path-hint {
  color: var(--accent-2);
  background: rgba(74, 163, 162, .08);
  border: 1px solid rgba(74, 163, 162, .25);
  border-radius: 6px 6px 0 0;
}
html[data-theme="dark"] .json-preview {
  background: #0a0e13;
  border: 1px solid var(--border);
  border-top: none;
  border-radius: 0 0 var(--radius) var(--radius);
  color: #c9d4e0;
}
html[data-theme="dark"] .badge {
  border-radius: 10px;
  border: 1px solid currentColor;
  background: rgba(0, 0, 0, .2);
}
html[data-theme="dark"] .badge.error {
  color: var(--err);
}
html[data-theme="dark"] .badge.warn {
  color: var(--warn);
}
html[data-theme="dark"] .badge.info {
  color: var(--info);
}
html[data-theme="dark"] .issue {
  border-radius: 6px;
  border: 1px solid transparent;
}
html[data-theme="dark"] .issue.error {
  color: var(--err);
  background: rgba(240, 98, 109, .07);
  border-color: rgba(240, 98, 109, .35);
}
html[data-theme="dark"] .issue.warn {
  color: var(--warn);
  background: rgba(227, 179, 65, .07);
  border-color: rgba(227, 179, 65, .35);
}
html[data-theme="dark"] .issue.info {
  color: var(--info);
  background: rgba(79, 195, 247, .06);
  border-color: rgba(79, 195, 247, .3);
}
html[data-theme="dark"] .issue.ok {
  color: var(--ok);
  border-color: rgba(63, 185, 138, .35);
  background: rgba(63, 185, 138, .06);
}
html[data-theme="dark"] .version-note {
  color: var(--muted);
  background: rgba(79, 195, 247, .05);
  border: 1px dashed rgba(79, 195, 247, .3);
  border-radius: 8px;
}
html[data-theme="dark"] .dlg {
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 12px;
}
html[data-theme="dark"] .dlg::backdrop {
  background: rgba(5, 8, 12, .65);
  backdrop-filter: blur(2px);
}
html[data-theme="dark"] .example-item {
  background: var(--panel2);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
}
html[data-theme="dark"] .foot {
  color: var(--muted);
  border-top: 1px solid var(--border-soft);
}
html[data-theme="dark"] .toast {
  background: #1c2531;
  color: var(--text);
  border: 1px solid var(--accent);
  border-radius: 8px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, .4);
}
html[data-theme="dark"] .toast.error {
  border-color: var(--err);
}
html[data-theme="dark"] {
  --accent-grad: linear-gradient(135deg, #3d8bff 0%, #6a5cff 100%);
  --accent-glow: rgba(61, 139, 255, .35);
  --panel-grad: linear-gradient(180deg, rgba(255, 255, 255, .028) 0%, rgba(255, 255, 255, 0) 42%);
  --shadow-1: 0 1px 0 rgba(255, 255, 255, .04) inset, 0 8px 20px rgba(0, 0, 0, .28);
  --shadow-2: 0 10px 30px rgba(0, 0, 0, .42);
  --radius-lg: 14px;

}
html[data-theme="dark"],
html[data-theme="dark"] body {
  background: linear-gradient(rgba(13, 17, 23, 0.82), rgba(13, 17, 23, 0.9)), url('../img/bg.jpg') center / cover no-repeat fixed, radial-gradient(900px 420px at 12% -8%, rgba(61, 139, 255, .10) 0%, transparent 60%), radial-gradient(700px 380px at 88% -6%, rgba(106, 92, 255, .09) 0%, transparent 55%), radial-gradient(1200px 600px at 20% -10%, #16202e 0%, var(--bg) 55%);
  background-color: var(--bg);
  background-attachment: fixed;
}
html[data-theme="dark"] ::selection {
  background: rgba(61, 139, 255, .35);
  color: #fff;
}
html[data-theme="dark"] * {
  scrollbar-color: #2b3442 #0d1117;
}
html[data-theme="dark"] *::-webkit-scrollbar-track {
  background: #0d1117;
}
html[data-theme="dark"] *::-webkit-scrollbar-thumb {
  background: #2b3442;
  border-radius: 6px;
  border: 2px solid #0d1117;
}
html[data-theme="dark"] *::-webkit-scrollbar-thumb:hover {
  background: #3d8bff;
}
html[data-theme="dark"] .topbar {
  background: linear-gradient(180deg, rgba(23, 29, 38, .96) 0%, rgba(17, 22, 29, .92) 100%);
  backdrop-filter: blur(10px) saturate(1.2);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .05) inset, 0 8px 24px rgba(0, 0, 0, .35);
}
html[data-theme="dark"] .topbar::after {
  background: linear-gradient(90deg, transparent, var(--accent-glow), rgba(106, 92, 255, .35), transparent);
}
html[data-theme="dark"] .logo {
  background: var(--accent-grad);
  background-clip: text;
  color: transparent;
  filter: drop-shadow(0 0 10px rgba(74, 163, 162, .45));
}
html[data-theme="dark"] .brand-text h1 {
  background: linear-gradient(90deg, #fff 0%, #b9d2ff 100%);
  background-clip: text;
  color: transparent;
}
html[data-theme="dark"] .topbar-controls .btn {
  box-shadow: none;
}
html[data-theme="dark"] .btn {
  background: linear-gradient(180deg, #232c38 0%, #1a212b 100%);
  border-color: #313d4e;
  border-radius: 8px;
  box-shadow: 0 1px 0 rgba(255, 255, 255, .05) inset, 0 3px 8px rgba(0, 0, 0, .25);
}
html[data-theme="dark"] .btn:hover {
  border-color: var(--accent);
  background: linear-gradient(180deg, #2a3a4f 0%, #1f2836 100%);
  box-shadow: 0 4px 14px rgba(61, 139, 255, .22), 0 1px 0 rgba(255, 255, 255, .06) inset;
}
html[data-theme="dark"] .btn:active {
  box-shadow: 0 1px 4px rgba(0, 0, 0, .3);
}
html[data-theme="dark"] .btn.accent {
  background: var(--accent-grad);
  border-color: rgba(120, 140, 255, .55);
  color: #fff;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .3);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .08) inset, 0 4px 16px rgba(61, 139, 255, .28);
}
html[data-theme="dark"] .btn.accent:hover {
  background: linear-gradient(135deg, #4d97ff 0%, #7a6bff 100%);
  box-shadow: 0 6px 20px rgba(61, 139, 255, .4), 0 0 0 1px rgba(255, 255, 255, .1) inset;
}
html[data-theme="dark"] .btn.danger:hover {
  border-color: var(--err);
  box-shadow: 0 4px 14px rgba(240, 98, 109, .2);
}
html[data-theme="dark"] .btn:disabled {
  box-shadow: none !important;
}
html[data-theme="dark"] .btn.small {
  border-radius: 7px;
}
html[data-theme="dark"] input[type="text"],
html[data-theme="dark"] input[type="number"],
html[data-theme="dark"] input:not([type]),
html[data-theme="dark"] select,
html[data-theme="dark"] textarea {
  background: #0b0f15;
  border-color: #2c3646;
  border-radius: 7px;
  box-shadow: 0 1px 0 rgba(255, 255, 255, .03) inset;
}
html[data-theme="dark"] input:not(:disabled):hover,
html[data-theme="dark"] select:hover,
html[data-theme="dark"] textarea:hover {
  border-color: #3c4a5e;
}
html[data-theme="dark"] input:focus,
html[data-theme="dark"] select:focus,
html[data-theme="dark"] textarea:focus {
  border-color: var(--accent);
  background: #0c1220;
  box-shadow: 0 0 0 3px rgba(61, 139, 255, .16), 0 0 14px rgba(61, 139, 255, .18);
}
html[data-theme="dark"] select {
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%238b98a9' stroke-width='1.6' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 9px center;
}
html[data-theme="dark"] input[type="checkbox"]:indeterminate {
  accent-color: var(--warn);
}
html[data-theme="dark"] .card {
  background: linear-gradient(180deg, rgba(23, 29, 38, .75) 0%, rgba(20, 25, 33, .85) 100%), var(--panel);
  border: 1px solid #2b3442;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1);
}
html[data-theme="dark"] .card::before {
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .1), transparent);
}
html[data-theme="dark"] .card h2::before {
  border-radius: 2px;
  background: var(--accent-grad);
}
html[data-theme="dark"] .grade-card {
  background: linear-gradient(180deg, rgba(255, 255, 255, .018) 0%, rgba(0, 0, 0, .06) 100%);
  border: 1px solid var(--border-soft);
  border-left-width: 3px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, .2);
}
html[data-theme="dark"] .grade-card:hover {
  box-shadow: 0 6px 16px rgba(0, 0, 0, .3);
}
html[data-theme="dark"] .grade-card[data-grade="0"] {
  border-left-color: var(--g1);
}
html[data-theme="dark"] .grade-card[data-grade="1"] {
  border-left-color: var(--g2);
}
html[data-theme="dark"] .grade-card[data-grade="2"] {
  border-left-color: var(--g3);
}
html[data-theme="dark"] .grade-card[data-grade="3"] {
  border-left-color: var(--g4);
}
html[data-theme="dark"] .grade-card[data-grade="4"] {
  border-left-color: var(--g5);
}
html[data-theme="dark"] .grade-card summary::before {
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 4px;
  background: #0b0f14;
}
html[data-theme="dark"] .grade-card[open] summary::before {
  color: var(--accent);
  border-color: var(--accent);
}
html[data-theme="dark"] .grade-badge {
  text-shadow: 0 1px 2px rgba(0, 0, 0, .4);
  background: rgba(0, 0, 0, .4);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .06) inset;
}
html[data-theme="dark"] .count-badge {
  background: #0a0e13;
  border-color: #2c3646;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .3) inset;
}
html[data-theme="dark"] .item-card {
  background: linear-gradient(180deg, rgba(255, 255, 255, .02) 0%, rgba(0, 0, 0, .04) 100%);
  border: 1px solid #232c38;
  border-radius: 9px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, .18);
}
html[data-theme="dark"] .item-card:hover {
  border-color: #34445c;
  box-shadow: 0 4px 14px rgba(0, 0, 0, .3), 0 0 0 1px rgba(61, 139, 255, .08);
}
html[data-theme="dark"] .item-no {
  background: #0b0f14;
  border: 1px solid var(--border-soft);
  border-radius: 6px;
}
html[data-theme="dark"] .price-table th {
  border-bottom: 1px solid #333f52;
  background: linear-gradient(180deg, rgba(255, 255, 255, .03), rgba(255, 255, 255, 0));
}
html[data-theme="dark"] .price-table tbody tr:nth-child(even) td {
  background: rgba(255, 255, 255, .012);
}
html[data-theme="dark"] .price-table tr:hover td {
  background: rgba(61, 139, 255, .06);
}
html[data-theme="dark"] .status-cell::before {
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 6px currentColor;
}
html[data-theme="dark"] .add-key-row .btn {
  box-shadow: none;
}
html[data-theme="dark"] .tab {
  border-radius: 8px 8px 0 0;
}
html[data-theme="dark"] .tab:hover {
  color: var(--text);
  background: rgba(255, 255, 255, .04);
}
html[data-theme="dark"] .tab.active {
  background: linear-gradient(180deg, var(--panel2), #141a24);
  border-color: var(--accent);
  box-shadow: 0 -2px 12px rgba(61, 139, 255, .15);
}
html[data-theme="dark"] .path-hint {
  background: linear-gradient(90deg, rgba(74, 163, 162, .14), rgba(74, 163, 162, .04));
  border-color: rgba(74, 163, 162, .35);
}
html[data-theme="dark"] .json-preview {
  background: linear-gradient(180deg, #0b0f16 0%, #080b10 100%);
  border-color: #2b3442;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .35), 0 0 0 1px rgba(255, 255, 255, .03) inset;
  color: #d3dfee;
}
html[data-theme="dark"] .badge {
  box-shadow: 0 1px 3px rgba(0, 0, 0, .3) inset;
}
html[data-theme="dark"] .issue {
  border-left: 3px solid transparent;
}
html[data-theme="dark"] .issue.error {
  border-left-color: var(--err);
}
html[data-theme="dark"] .issue.warn {
  border-left-color: var(--warn);
}
html[data-theme="dark"] .issue.info {
  border-left-color: var(--info);
}
html[data-theme="dark"] .issue:hover {
  filter: brightness(1.12);
}
html[data-theme="dark"] .issue.ok {
  border-left-color: var(--ok);
}
html[data-theme="dark"] .version-note {
  background: linear-gradient(90deg, rgba(79, 195, 247, .08), rgba(79, 195, 247, .02));
  border: 1px solid rgba(79, 195, 247, .28);
  box-shadow: 0 3px 10px rgba(0, 0, 0, .2);
}
html[data-theme="dark"] .dlg {
  border-radius: 14px;
  border-color: #354156;
  box-shadow: 0 24px 60px rgba(0, 0, 0, .55), 0 0 0 1px rgba(255, 255, 255, .05) inset;
}
html[data-theme="dark"] .dlg::backdrop {
  background: rgba(3, 6, 10, .72);
  backdrop-filter: blur(4px);
}
html[data-theme="dark"] .dlg h2 {
  background: var(--accent-grad);
  background-clip: text;
  color: transparent;
}
html[data-theme="dark"] .example-item {
  box-shadow: 0 2px 8px rgba(0, 0, 0, .2);
}
html[data-theme="dark"] .example-item:hover {
  border-color: var(--accent);
}
html[data-theme="dark"] .toast {
  background: linear-gradient(180deg, #232e3d, #171f2b);
  border-radius: 10px;
  border-color: var(--accent);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .06) inset, 0 10px 34px rgba(0, 0, 0, .5), 0 0 22px rgba(61, 139, 255, .18);
}
html[data-theme="dark"] .toast.error {
  border-color: var(--err);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .05) inset, 0 10px 34px rgba(0, 0, 0, .5), 0 0 22px rgba(240, 98, 109, .2);
}
html[data-theme="dark"] .tacz-row {
  background: linear-gradient(135deg, rgba(61, 139, 255, .06), rgba(106, 92, 255, .04));
  border-color: rgba(61, 139, 255, .28);
  box-shadow: 0 2px 8px rgba(0, 0, 0, .2);
}
html[data-theme="dark"] .col-head:hover h2 {
  color: #ffffff;
}
html[data-theme="dark"] .col-caret {
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 6px;
  background: rgba(0, 0, 0, .25);
}
html[data-theme="dark"] .col-head:hover .col-caret {
  color: var(--accent);
  border-color: var(--accent);
}
html[data-theme="dark"] .card.collapsed {
  box-shadow: 0 2px 8px rgba(0, 0, 0, .22);
}
html[data-theme="dark"] .page-nav .tab {
  color: var(--muted);
  border-radius: 8px 8px 0 0;
}
html[data-theme="dark"] .page-nav .tab:hover {
  color: var(--text);
}
html[data-theme="dark"] .page-nav .tab.active {
  color: #fff;
}
html[data-theme="dark"] .name-color-row input[type="color"] {
  background: #0b0f15;
  border: 1px solid var(--border);
  border-radius: 6px;
}
html[data-theme="dark"] .name-color-row input[type="color"]:hover {
  border-color: var(--accent);
}

/* filebar: dark theme */
html[data-theme="dark"] .filebar {
  background: rgba(22, 27, 34, .82);
  border-color: var(--border);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .04) inset, 0 6px 18px rgba(0, 0, 0, .35);
}
html[data-theme="dark"] .filebar-head { border-bottom-color: var(--border-soft); }
html[data-theme="dark"] .file-item:hover { background: rgba(255, 255, 255, .05); }
html[data-theme="dark"] .file-item.active {
  background: rgba(61, 139, 255, .12);
  border-color: rgba(61, 139, 255, .35);
}
html[data-theme="dark"] .file-btn:hover { color: var(--text); background: rgba(255, 255, 255, .1); }
html[data-theme="dark"] .file-btn.accent { color: var(--accent); }

/* EV column + footer rows in the probability table */
.prob-table td.prob-ev, .prob-table th.prob-ev-hint {
  text-align: right;
  font-family: var(--mono);
  white-space: nowrap;
}
.prob-table tr.prob-footer td {
  border-top: 1px solid rgba(60, 52, 38, .25);
  font-weight: 600;
}
html[data-theme="dark"] .prob-table tr.prob-footer td { border-top-color: var(--border); }

/* =====================================================================
 * Open simulator panel (box page, third view tab).
 * ===================================================================== */
.sim-panel {
  margin: 0;
  background: linear-gradient(180deg, rgba(255, 253, 248, .55) 0%, rgba(250, 246, 236, .42) 100%);
  backdrop-filter: blur(14px) saturate(1.7);
  -webkit-backdrop-filter: blur(14px) saturate(1.7);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .6) inset, 0 8px 20px rgba(90, 80, 60, .12);
  border: 1px solid var(--border);
  border-top: none;
  border-radius: 0 0 var(--radius) var(--radius);
  padding: 12px 14px;
  max-height: 46vh;
  overflow: auto;
  color: #3d3f47;
  font-size: 12px;
}
.sim-panel h2 { margin: 0 0 8px; font-size: 13px; color: var(--text); }
.sim-actions { display: flex; gap: 6px; flex-wrap: wrap; margin: 6px 0 10px; }
.sim-result-line { min-height: 20px; margin: 4px 0 8px; font-size: 13px; }
.sim-result-label { color: var(--muted); }
.sim-count { margin: 6px 0; font-size: 12px; color: var(--muted); }
.sim-count b { color: var(--text); }
.sim-stale {
  color: var(--warn);
  background: rgba(184, 134, 11, .10);
  border: 1px dashed rgba(184, 134, 11, .35);
  border-radius: 6px;
  padding: 6px 10px;
  margin: 0 0 10px;
}
.sim-strip-wrap {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: rgba(60, 52, 38, .06);
  height: 64px;
  margin-bottom: 10px;
}
.sim-strip {
  display: flex;
  align-items: stretch;
  height: 100%;
  width: max-content;
  will-change: transform;
}
.sim-cell {
  flex: 0 0 96px; /* SIM_CELL_W */
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 4px 6px;
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1.3;
  border-right: 1px solid rgba(60, 52, 38, .14);
  overflow: hidden;
}
.sim-cell span {
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  word-break: break-all;
}
.sim-cell.sim-win.hit {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  border-radius: 4px;
  background: rgba(61, 139, 255, .12);
}
.sim-marker {
  position: absolute;
  left: 50%; top: 0; bottom: 0;
  width: 2px;
  transform: translateX(-1px);
  background: var(--accent);
  opacity: .7;
  pointer-events: none;
}

/* dark theme: simulator */
html[data-theme="dark"] .sim-panel {
  background: linear-gradient(180deg, rgba(22, 27, 34, .88) 0%, rgba(17, 22, 29, .82) 100%);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .04) inset, 0 8px 20px rgba(0, 0, 0, .35);
  color: var(--text);
}
html[data-theme="dark"] .sim-strip-wrap { background: rgba(255, 255, 255, .03); border-color: var(--border); }
html[data-theme="dark"] .sim-cell { border-right-color: var(--border-soft); }

/* file workspace: the sidebar adds a third layout column (auto = collapsed rail
 * or 210px bar); appended after every earlier layer so it wins the cascade */
.layout {
  grid-template-columns: auto minmax(0, 1fr) minmax(360px, 460px);
}
@media (max-width: 1180px) {
  .layout { grid-template-columns: 1fr; }
}

/* dark theme: probability panel + table lines (the base layer carried no
 * dark .prob-panel background, so the cream one would otherwise survive) */
html[data-theme="dark"] .prob-panel {
  background: linear-gradient(180deg, rgba(22, 27, 34, .88) 0%, rgba(17, 22, 29, .82) 100%);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .04) inset, 0 8px 20px rgba(0, 0, 0, .35);
  color: var(--text);
}
html[data-theme="dark"] .prob-table th, html[data-theme="dark"] .prob-table td {
  border-bottom-color: var(--border-soft);
}
html[data-theme="dark"] .prob-panel h2 { color: var(--text); }
html[data-theme="dark"] .issues { color: var(--text); }
html[data-theme="dark"] .path-hint { color: var(--accent-2); }

/* =====================================================================
 * Motion & light layer — interaction polish.
 *
 * Appended last so it wins the cascade over every earlier layer. Purely
 * additive: no markup change, no palette re-authoring — every value below is
 * either a motion token or a light token, defined once per theme, so the
 * cream and dark themes keep their existing colours.
 *
 * Four jobs:
 *   1. Motion  — one timing/easing scale (28 ad-hoc transitions existed), and
 *                the press state the cream theme never had.
 *   2. Light   — a three-part glass rim (top highlight + edge + bottom shade)
 *                on one elevation scale, plus per-rarity glow on the badges.
 *   3. Weight  — remove the nested backdrop-filter stack on inner cards: they
 *                sit on an already-blurred parent, so a 2nd and 3rd blur cost
 *                a lot of GPU for almost no visual gain, and that is exactly
 *                what made scrolling and the new transitions stutter.
 *   4. Reach   — hover motion only where a real pointer exists.
 * ===================================================================== */

/* ---------- tokens: motion ---------- */
:root {
  --dur-1: 100ms;   /* press / micro feedback */
  --dur-2: 180ms;   /* hover, colour, layout of a control */
  --dur-3: 300ms;   /* panels, dialogs, larger surfaces */
  --ease-out: cubic-bezier(.22, .61, .36, 1);
  --ease-spring: cubic-bezier(.34, 1.3, .64, 1);   /* slight overshoot, entrances */
}

/* ---------- tokens: light (cream) ---------- */
:root {
  --rim-top: rgba(255, 255, 255, .70);   /* 1px highlight along the top edge */
  --rim-edge: rgba(255, 255, 255, .16);  /* faint inner outline all round */
  --shade-in: rgba(122, 106, 80, .055);  /* bottom inner shade — makes it read as glass */
  --elev-1: 0 1px 2px rgba(90, 80, 60, .055), 0 3px 10px rgba(90, 80, 60, .075);
  --elev-2: 0 1px 3px rgba(90, 80, 60, .07), 0 8px 22px rgba(90, 80, 60, .11);
  --elev-3: 0 2px 5px rgba(90, 80, 60, .08), 0 16px 40px rgba(90, 80, 60, .17);
  --press-in: inset 0 2px 6px rgba(122, 106, 80, .17);
  --halo: 0 0 0 3px rgba(47, 111, 219, .16), 0 6px 20px rgba(47, 111, 219, .20);
}

/* ---------- tokens: light (dark theme) ---------- */
html[data-theme="dark"] {
  --rim-top: rgba(255, 255, 255, .07);
  --rim-edge: rgba(255, 255, 255, .04);
  --shade-in: rgba(0, 0, 0, .40);
  --elev-1: 0 1px 2px rgba(0, 0, 0, .38), 0 3px 12px rgba(0, 0, 0, .30);
  --elev-2: 0 1px 3px rgba(0, 0, 0, .42), 0 9px 24px rgba(0, 0, 0, .38);
  --elev-3: 0 2px 8px rgba(0, 0, 0, .44), 0 18px 42px rgba(0, 0, 0, .46);
  --press-in: inset 0 2px 7px rgba(0, 0, 0, .52);
  /* the dark layer's own hover glow carries an inset highlight — keep it */
  --halo: 0 0 0 3px rgba(61, 139, 255, .18), 0 6px 22px rgba(61, 139, 255, .24),
          inset 0 1px 0 rgba(255, 255, 255, .06);
}

/* ---------- glass rim on one elevation scale ---------- */
/* Containers float highest, group cards next, item rows least — so the layers
   stay readable as a stack instead of all sitting on the same plane. */
.card,
.dlg,
.prob-panel,
.sim-panel {
  box-shadow:
    inset 0 1px 0 var(--rim-top),
    inset 0 0 0 1px var(--rim-edge),
    inset 0 -1px 0 var(--shade-in),
    var(--elev-3);
}
.grade-card {
  box-shadow:
    inset 0 1px 0 var(--rim-top),
    inset 0 -1px 0 var(--shade-in),
    var(--elev-2);
}
.item-card,
.example-item {
  box-shadow:
    inset 0 1px 0 var(--rim-top),
    inset 0 -1px 0 var(--shade-in),
    var(--elev-1);
}
/* dark layer carries the same components at higher specificity — mirror them */
html[data-theme="dark"] .card,
html[data-theme="dark"] .dlg,
html[data-theme="dark"] .prob-panel,
html[data-theme="dark"] .sim-panel {
  box-shadow:
    inset 0 1px 0 var(--rim-top),
    inset 0 0 0 1px var(--rim-edge),
    inset 0 -1px 0 var(--shade-in),
    var(--elev-3);
}
html[data-theme="dark"] .grade-card {
  box-shadow:
    inset 0 1px 0 var(--rim-top),
    inset 0 -1px 0 var(--shade-in),
    var(--elev-2);
}
html[data-theme="dark"] .item-card,
html[data-theme="dark"] .example-item {
  box-shadow:
    inset 0 1px 0 var(--rim-top),
    inset 0 -1px 0 var(--shade-in),
    var(--elev-1);
}

/* ---------- drop the nested blur stack ---------- */
/* .grade-card and .item-card live inside a .card that already blurs what is
   behind it, so their own blur mostly re-blurs an already-blurred result.
   Compensate the cream theme with slightly denser fills so the panels keep
   the same perceived tone without paying for a second and third blur pass. */
.grade-card,
.item-card,
.item-adv,
.tacz-row {
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.grade-card {
  background: linear-gradient(180deg, rgba(255, 253, 248, .62) 0%, rgba(248, 242, 230, .54) 100%);
}
.item-card {
  background: linear-gradient(180deg, rgba(255, 253, 248, .58) 0%, rgba(248, 243, 232, .50) 100%);
}
html[data-theme="dark"] .grade-card {
  background: linear-gradient(180deg, rgba(255, 255, 255, .035) 0%, rgba(255, 255, 255, .015) 100%);
}
html[data-theme="dark"] .item-card {
  background: linear-gradient(180deg, rgba(255, 255, 255, .04) 0%, rgba(255, 255, 255, .015) 100%);
}

/* ---------- shared motion on controls ---------- */
.btn,
.tab,
.file-item,
.file-btn,
.col-head,
.example-item,
.grade-card,
.item-card,
summary {
  transition:
    background var(--dur-2) var(--ease-out),
    background-color var(--dur-2) var(--ease-out),
    border-color var(--dur-2) var(--ease-out),
    color var(--dur-2) var(--ease-out),
    box-shadow var(--dur-2) var(--ease-out),
    transform var(--dur-1) var(--ease-out),
    opacity var(--dur-2) var(--ease-out);
}
.item-card,
.grade-card,
.example-item {
  transition:
    background var(--dur-2) var(--ease-out),
    border-color var(--dur-2) var(--ease-out),
    box-shadow var(--dur-2) var(--ease-out),
    transform var(--dur-2) var(--ease-spring);
}

/* ---------- press feedback ---------- */
/* The cream theme had no visible press state: the only :active rule came from
   the dark base layer and applied a hard black drop shadow to a light button. */
.btn:active,
html[data-theme="dark"] .btn:active {
  transform: translateY(1px);
  box-shadow: inset 0 1px 0 var(--rim-top), var(--press-in);
  transition-duration: var(--dur-1);
}
.btn.accent:active,
html[data-theme="dark"] .btn.accent:active {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .28), var(--press-in);
}

input:focus,
select:focus,
textarea:focus {
  transition: border-color var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out),
    background var(--dur-2) var(--ease-out);
}

/* ---------- rarity glow on the grade badges ---------- */
/* currentColor already carries each rarity's own hue (and its dark-theme
   variant), so one rule lights all five grades in both themes — no second set
   of hard-coded rgba values. */
.grade-badge,
html[data-theme="dark"] .grade-badge {
  transition: box-shadow var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-spring);
  box-shadow:
    inset 0 1px 0 var(--rim-top),
    0 0 0 1px color-mix(in srgb, currentColor 30%, transparent),
    0 2px 14px -3px color-mix(in srgb, currentColor 55%, transparent);
}
.grade-card:hover .grade-badge {
  transform: translateY(-1px);
  box-shadow:
    inset 0 1px 0 var(--rim-top),
    0 0 0 1px color-mix(in srgb, currentColor 42%, transparent),
    0 3px 20px -3px color-mix(in srgb, currentColor 78%, transparent);
}

/* ---------- hover: lift + focus halo, pointer devices only ---------- */
@media (hover: hover) and (pointer: fine) {
  .item-card:hover {
    transform: translateY(-1px);
    box-shadow:
      inset 0 1px 0 var(--rim-top),
      inset 0 -1px 0 var(--shade-in),
      var(--elev-2);
  }
  .grade-card:hover {
    transform: translateY(-1px);
    box-shadow:
      inset 0 1px 0 var(--rim-top),
      inset 0 -1px 0 var(--shade-in),
      var(--elev-3);
  }
  .btn:not(:disabled):hover {
    transform: translateY(-1px);
  }
  .btn:not(:disabled):active {
    transform: translateY(1px);
  }
  .file-item:hover,
  .example-item:hover {
    transform: translateY(-1px);
  }
}
/* dark layer re-states .btn.accent:hover — keep the halo consistent there */
html[data-theme="dark"] .btn:not(:disabled):hover {
  box-shadow: var(--halo);
}
.btn:not(:disabled):hover {
  box-shadow: var(--halo);
}

/* ---------- dialogs: fade the scrim in ---------- */
.dlg::backdrop {
  animation: backdrop-in var(--dur-3) var(--ease-out);
}
@keyframes backdrop-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* ---------- toast: let it settle instead of snapping ---------- */
.toast {
  transition: opacity var(--dur-3) var(--ease-out), transform var(--dur-3) var(--ease-spring);
}

/* ---------- reduced motion: keep the feedback, drop the travel ---------- */
@media (prefers-reduced-motion: reduce) {
  .btn:active,
  .btn:not(:disabled):hover,
  .item-card:hover,
  .grade-card:hover,
  .file-item:hover,
  .grade-card:hover .grade-badge {
    transform: none !important;
  }
}

/* =====================================================================
 * Motion layer II — choreography.
 *
 * Layer I gave every control one timing scale and one light model. This layer
 * gives the *page* a sense of sequence: things arrive in a deliberate order,
 * state changes animate the thing that actually changed, and the surfaces that
 * have been on screen for a while keep a low-amplitude sign of life.
 *
 * Still purely additive — no markup, no JS, no palette change. Every new
 * animation is either triggered by a class/attribute app.js already toggles
 * (`.active`, `[hidden]`, `.collapsed`, `[open]`, `.json-sync`, `.show`) or by
 * DOM insertion that already happens. Nothing here needs a new hook.
 *
 * Budget rule: only `opacity` / `transform` for entrances (compositor-only, no
 * layout), and continuous ambient motion is capped at two small elements that
 * are otherwise dead pixels (the entity empty-state, the rarity badge).
 * ===================================================================== */

:root {
  --dur-4: 460ms;                              /* first-paint surfaces */
  --stagger: 38ms;                             /* one step of a cascade */
  --topbar-cast: rgba(90, 80, 60, .22);        /* shadow cast under the bar */
}
html[data-theme="dark"] {
  --topbar-cast: rgba(0, 0, 0, .5);
}

/* ---------- 1. first paint: the page assembles itself ---------- */
/* Order is left → form → right, then top-to-bottom inside the form, so the eye
   is led through the layout once instead of meeting four panels at once.
   renderAll() only runs on structural events (load, undo/redo, file switch,
   language, import) — never on keystrokes — so this never replays mid-typing. */
@keyframes bar-drop-in {
  from { opacity: 0; transform: translateY(-10px); }
  to   { opacity: 1; transform: none; }
}
@keyframes rail-left-in {
  from { opacity: 0; transform: translateX(-12px); }
  to   { opacity: 1; transform: none; }
}
@keyframes rail-right-in {
  from { opacity: 0; transform: translateX(12px); }
  to   { opacity: 1; transform: none; }
}
@keyframes rise-in {
  from { opacity: 0; transform: translateY(9px); }
  to   { opacity: 1; transform: none; }
}

.topbar  { animation: bar-drop-in  var(--dur-3) var(--ease-out) backwards; }
.filebar { animation: rail-left-in var(--dur-4) var(--ease-out) var(--stagger) backwards; }
.right   { animation: rail-right-in var(--dur-4) var(--ease-out) calc(var(--stagger) * 2) backwards; }

#form-root > * { animation: rise-in var(--dur-4) var(--ease-out) backwards; }
#form-root > *:nth-child(1) { animation-delay: calc(var(--stagger) * 3); }
#form-root > *:nth-child(2) { animation-delay: calc(var(--stagger) * 4); }
#form-root > *:nth-child(3) { animation-delay: calc(var(--stagger) * 5); }
#form-root > *:nth-child(4) { animation-delay: calc(var(--stagger) * 6); }
#form-root > *:nth-child(5) { animation-delay: calc(var(--stagger) * 7); }
#form-root > *:nth-child(n+6) { animation-delay: calc(var(--stagger) * 8); }

#file-list .file-item { animation: rise-in var(--dur-3) var(--ease-out) backwards; }
#file-list .file-item:nth-child(1) { animation-delay: calc(var(--stagger) * 3); }
#file-list .file-item:nth-child(2) { animation-delay: calc(var(--stagger) * 4); }
#file-list .file-item:nth-child(3) { animation-delay: calc(var(--stagger) * 5); }
#file-list .file-item:nth-child(n+4) { animation-delay: calc(var(--stagger) * 6); }

/* Drop-entity rows: the list is regenerated on every add/remove, so each edit
   reads as "the row arrived" instead of an unexplained snap. */
#entity-rows .entity-row { animation: rise-in var(--dur-2) var(--ease-out) backwards; }
#entity-rows .entity-row:nth-child(1) { animation-delay: 0ms; }
#entity-rows .entity-row:nth-child(2) { animation-delay: var(--stagger); }
#entity-rows .entity-row:nth-child(n+3) { animation-delay: calc(var(--stagger) * 2); }

/* ---------- 2. tabs: the indicator travels ---------- */
/* .tab had background/text transitions but nothing that read as "this one is
   selected". `position: relative` is safe here — no tab holds positioned
   children of its own. */
.tab { position: relative; }
.tab::after {
  content: "";
  position: absolute;
  left: 9px; right: 9px; bottom: -1px;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, transparent, var(--accent), transparent);
  transform: scaleX(0);
  transform-origin: center;
  opacity: 0;
  pointer-events: none;
  transition: transform var(--dur-2) var(--ease-out), opacity var(--dur-2) var(--ease-out);
}
.tab.active::after { transform: scaleX(1); opacity: 1; }

/* ---------- 3. preview views: the new panel settles down ---------- */
/* #prob-panel / #sim-panel are display-toggled through the `hidden` attribute,
   and a display change cannot be transitioned — @starting-style is the modern
   hook for exactly that, giving the incoming panel a from-state. Browsers
   without it simply show the panel instantly. */
#prob-panel,
#sim-panel {
  transition: opacity var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out);
}
@starting-style {
  #prob-panel:not([hidden]),
  #sim-panel:not([hidden]) {
    opacity: 0;
    transform: translateY(8px);
  }
}

/* ---------- 4. collapsing a card now animates both directions ---------- */
/* `.card.collapsed .col-body { display: none }` is the existing mechanism; the
   caret gets a spring rotation, and @starting-style animates the body back in
   when the card is displayed again. (Collapse itself still snaps — there is no
   exit hook without JS, and matching the open animation is not worth a
   markup change.) */
.col-caret {
  transition: transform var(--dur-2) var(--ease-spring), color var(--dur-2) var(--ease-out),
    border-color var(--dur-2) var(--ease-out), background var(--dur-2) var(--ease-out);
}
.col-body {
  transition: opacity var(--dur-3) var(--ease-out), transform var(--dur-3) var(--ease-out);
}
@starting-style {
  .card:not(.collapsed) .col-body {
    opacity: 0;
    transform: translateY(-8px);
  }
}

/* ---------- 5. grade cards open as drawers, not as jumps ---------- */
/* <details> only gained an animatable content box recently; where it is not
   supported the whole rule is dropped and the native instant toggle remains,
   so this cannot regress the panel. */
.grade-card { interpolate-size: allow-keywords; }
.grade-card::details-content {
  block-size: 0;
  overflow: hidden;
  opacity: 0;
  transition:
    block-size var(--dur-3) var(--ease-out),
    opacity var(--dur-2) var(--ease-out),
    content-visibility var(--dur-3) allow-discrete;
}
.grade-card[open]::details-content {
  block-size: auto;
  opacity: 1;
}

/* ---------- 6. ambient life, capped at two elements ---------- */
/* The empty drop-entity state is dead pixels that are asking for input: a slow
   sheen crossing a dashed box says "write something here" without a spinner. */
.entity-empty { position: relative; overflow: hidden; }
.entity-empty::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(100deg, transparent 34%,
    color-mix(in srgb, currentColor 26%, transparent) 50%, transparent 66%);
  transform: translateX(-100%);
  animation: empty-sheen 3.8s var(--ease-out) infinite;
}
@keyframes empty-sheen {
  0%, 55% { transform: translateX(-100%); }
  100%    { transform: translateX(100%); }
}

/* Rarity badges breathe. Driven through background-position rather than a
   pseudo-element overlay, so the label never gets washed out by its own
   highlight, and currentColor keeps all five grades × both themes in one rule.
   Higher grades sweep faster — the shimmer itself carries the rarity. */
.grade-badge {
  background-image: linear-gradient(100deg, transparent 32%,
    color-mix(in srgb, currentColor 46%, transparent) 50%, transparent 68%);
  background-size: 260% 100%;
  background-repeat: no-repeat;
  animation: badge-sheen 4.6s var(--ease-out) infinite;
}
@keyframes badge-sheen {
  0%, 58% { background-position: 190% 0; }
  100%    { background-position: -90% 0; }
}
.grade-badge.g4 { animation-duration: 3.4s; }
.grade-badge.g5 { animation-duration: 2.4s; }

/* ---------- 7. toast: it springs in and shows its own remaining time ---------- */
/* The bar runs for exactly the 3200ms app.js keeps the toast on screen, so it
   reads as a countdown rather than decoration. Note the base rule centres the
   toast with translateX(-50%) — every transform here has to carry it. */
.toast { overflow: hidden; }
@keyframes toast-pop {
  from { opacity: 0; transform: translateX(-50%) translateY(12px) scale(.95); }
  to   { opacity: 1; transform: translateX(-50%) translateY(-6px) scale(1); }
}
.toast.show { animation: toast-pop var(--dur-2) var(--ease-spring) both; }
@keyframes toast-timer {
  from { width: 100%; }
  to   { width: 0; }
}
.toast.show::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  height: 2px;
  width: 100%;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  animation: toast-timer 3.2s linear both;
}
.toast.error.show::after { background: var(--err); }

/* ---------- 8. dialogs: the body cascades in behind the frame ---------- */
@keyframes dlg-row-in {
  from { opacity: 0; transform: translateY(7px); }
  to   { opacity: 1; transform: none; }
}
.dlg[open] > * { animation: dlg-row-in var(--dur-2) var(--ease-out) backwards; }
.dlg[open] > *:nth-child(1) { animation-delay: 30ms; }
.dlg[open] > *:nth-child(2) { animation-delay: 70ms; }
.dlg[open] > *:nth-child(3) { animation-delay: 110ms; }
.dlg[open] > *:nth-child(n+4) { animation-delay: 150ms; }

/* ---------- 9. JSON preview: a re-sync is visible, not silent ---------- */
/* app.js removes `.json-sync`, forces a reflow, then re-adds it — so this
   restarts on every actual content change (and only then). */
@keyframes preview-sync-pulse {
  from { opacity: .55; transform: translateY(3px); }
  to   { opacity: 1; transform: none; }
}
.json-preview.json-sync { animation: preview-sync-pulse var(--dur-3) var(--ease-out); }

/* ---------- 10. scrolling: the bar casts a shadow once you have moved ---------- */
/* Scroll-driven and only ever animating opacity, so it stays off the main
   thread. Deliberately excluded from `reduce` — a scroll-linked animation
   ignores animation-duration, so the global reduce guard could not neutralise
   it; the media query below has to do that job instead. */
.topbar::before {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 100%;
  height: 16px;
  background: linear-gradient(180deg, var(--topbar-cast), transparent);
  opacity: 0;
  pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: scroll()) {
    @keyframes topbar-cast-in {
      to { opacity: 1; }
    }
    .topbar::before {
      animation: topbar-cast-in linear both;
      animation-timeline: scroll();
      animation-range: 0 200px;
    }
  }
}

/* =====================================================================
 * Responsive layer — device adaptation.
 *
 * The old breakpoints (1180 / 1080 / 720 / 640) each patched a symptom. A
 * sweep across 21 viewports found the two structural causes behind most of
 * them, and both are fixed here rather than papered over per width:
 *
 *   1. THE TOPBAR WRAPPED, so its height was never predictable — 72px at
 *      1440, 118px at 1181, 166px on a 360px phone. The two sticky rails were
 *      pinned at a hard-coded `top: 68px`, so they slid under it: 4px eaten at
 *      every width above 1365, and 50px in the 1181–1365 band. The brand title
 *      ("CS2-Box Box Config Editor", ~280px at 22px) was the real culprit: on a
 *      320px viewport it alone was wider than the screen. So the topbar is now
 *      pinned to ONE row — the brand ellipsises, the controls become the
 *      horizontal scroller — which makes the height a constant, and the rails
 *      are offset from that same token.
 *
 *   2. THE RIGHT COLUMN WAS RIGID at minmax(360px, 460px), so it always took
 *      460: at 1181 the form was crushed to 435px (63% empty space around it
 *      was not the problem — the form was). It is now viewport-proportional, so
 *      the form keeps breathing room down to the 1180 one-column switch.
 *
 * Plus the things a per-width approach cannot express: coarse-pointer hit
 * targets, fluid page gutters, short (landscape-phone) viewports, and safe-area
 * insets. No markup change, no JS.
 * ===================================================================== */

:root {
  --gutter: clamp(12px, 1.6vw, 28px);   /* page side padding */
  /* One topbar row, measured (see the metric note below). Both rails stick
     below it, so this is load-bearing: if it is ever wrong the rails slide
     under the topbar again. Re-measure after any change to topbar padding,
     brand font size or control height.
       fine pointer   -> bar renders 72px headless, 74px with a 6px styled
                         scrollbar on the strip (Windows Chrome reserves space
                         for ::-webkit-scrollbar, headless does not)
       coarse pointer -> 75px, so 82px leaves the same headroom
     The rails then sit at +6px, i.e. 80 / 88, clear of both. */
  --topbar-h: 74px;
  --rail-top: calc(var(--topbar-h) + 6px);
}
@media (pointer: coarse) {
  :root { --topbar-h: 82px; }           /* taller hit targets grow the bar */
}

/* ---------- 1. the topbar is exactly one row wherever the rails stick ---------- */
.topbar {
  flex-wrap: nowrap;
}
.brand {
  flex: 0 1 auto;
  min-width: 140px;                     /* below this the mark stops reading */
}
.brand-text { min-width: 0; }
/* Both lines must be single-line, or the bar's height is width-dependent again:
   measured at 1280 the subtitle wrapped to two lines and drove the bar to 91px,
   while at 1440 it fitted on one and the bar was 72px — exactly the class of
   drift that made the rails slide under it. Truncate instead of wrapping. */
.brand-text h1,
.brand-text p,
#app-title {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.topbar-controls {
  flex: 1 1 auto;
  min-width: 0;
  flex-wrap: nowrap;                    /* one row; the strip scrolls instead */
  overflow-x: auto;
  overflow-y: hidden;                   /* required once the other axis scrolls */
  padding-block: 4px;                   /* room for the 3px focus halo */
  scrollbar-width: thin;
}
.topbar-controls::-webkit-scrollbar { height: 6px; }
.topbar-controls > * { flex: 0 0 auto; }/* never squash a control into illegibility */

/* Below 1181 the rails are static, so the bar no longer has to be a constant
   height — and there the strip would hide far more than we can accept: the
   first two controls alone (language + version selects) are 291px, so on a
   360px phone a scrolling strip would show only those two and push every
   button — Undo, New, Import, Examples, Share — off-screen. Reordering them
   with `order` would fix the visual order but break DOM/focus order (WCAG
   2.4.3), so instead the bar wraps again and stops being sticky: every control
   stays visible and the header scrolls away instead of taxing the viewport
   (it was 166px of a 640px screen, permanently). */
@media (max-width: 1180px) {
  .topbar { position: relative; }       /* relative, not static: keeps ::before/::after contained */
  .topbar::before { display: none; }    /* the scroll cast is pointless on a non-sticky bar */
  .topbar-controls {
    flex-wrap: wrap;
    overflow: visible;
    padding-block: 0;
  }
}

/* ---------- 2. the rails stick below the bar, not under it ---------- */
/* High specificity is deliberate: the base layer sets `top: 68px` and the dark
   layer re-states positioning, so this has to win outright. */
.filebar,
.right,
html[data-theme="dark"] .filebar,
html[data-theme="dark"] .right {
  top: var(--rail-top);
}

/* ---------- 3. the preview column follows the viewport ---------- */
.layout {
  grid-template-columns: auto minmax(0, 1fr) clamp(320px, 32vw, 460px);
  padding: var(--gutter) var(--gutter) 10px;
}
@media (max-width: 1180px) {
  .layout { grid-template-columns: 1fr; }
}

/* ---------- 4. fluid gutters: tighter on small, roomier on large ---------- */
.card {
  padding: clamp(12px, 1.1vw, 20px) clamp(12px, 1.3vw, 22px);
}
.foot {
  padding: 10px var(--gutter) max(22px, env(safe-area-inset-bottom));
}
.toast {
  bottom: max(14px, env(safe-area-inset-bottom));
}
/* 4K / ultrawide: a 1760px cap left a lot of unused room on a 2560px display */
@media (min-width: 2200px) {
  .layout { max-width: 2040px; }
}

/* ---------- 5. tablets and small laptops: stop the bar eating the screen ---------- */
@media (max-width: 1080px) {
  .brand { min-width: 120px; gap: 9px; }
  .topbar-controls { gap: 8px; }
}
@media (max-width: 720px) {
  .brand { min-width: 96px; gap: 8px; }
  .brand-text h1, #app-title { font-size: 17px; }
  .topbar-controls { gap: 6px; }
}
@media (max-width: 480px) {
  .brand { min-width: 76px; }
  .brand-text h1, #app-title { font-size: 15px; }
}

/* ---------- 6. coarse pointers: real hit targets ---------- */
/* The sweep measured every button at 27px tall — under half the 44px a thumb
   is expected to hit. Only the pointer type is targeted, so mouse users keep
   the dense layout. */
@media (pointer: coarse) {
  .btn { min-height: 42px; padding: 9px 14px; }
  .btn.small { min-height: 36px; }
  .tab { min-height: 40px; }
  .topbar-controls .btn { min-height: 40px; padding: 8px 12px; }
  input[type="text"], input[type="number"], input:not([type]), select, textarea {
    min-height: 42px;
  }
  input[type="checkbox"] { width: 19px; height: 19px; }
  .col-head { min-height: 46px; }
  .file-item { min-height: 42px; }
  .grade-card summary { min-height: 46px; }
  /* a fingertip cannot hover, so do not reserve a hover-only affordance */
  .file-item, .grade-card summary, .col-head { cursor: pointer; }
}

/* ---------- 7. short viewports (landscape phones, split windows) ---------- */
/* These were sized in vh with no upper bound, so on a 390px-tall landscape
   phone a dialog could still ask for 88vh of usable space and push its own
   action buttons off-screen. */
@media (max-height: 560px) {
  .dlg { max-height: 94vh; padding: 14px; }
  .example-list { max-height: 38vh; }
  #import-textarea { max-height: 26vh; }
  .tutorial-body { max-height: 38vh; }
  .file-list { max-height: 32vh; }
}

/* ---------- 8. very narrow: nothing may push the document sideways ---------- */
@media (max-width: 380px) {
  .row.inline .mini { flex: 1 1 100%; }   /* stack mini fields rather than squeeze */
  .random-slot input { width: 64px; }
  .price-table { min-width: 480px; }
}

/* ---------- 9. small phones: a shorter (wrapped) bar, without hiding anything ---------- */
/* The bar is already non-sticky here, so the goal is only to cut the scroll
   distance to the form. The two selects are the widest items (they alone were
   291px at desktop metrics) and they are the ones whose text fits in less room,
   so they are capped rather than shrunk proportionally. Hit targets stay at
   42px — the coarse-pointer block below deliberately is not relaxed here. */
@media (max-width: 560px) {
  .topbar { padding: 7px 12px; gap: 6px 8px; }
  .brand { min-width: 0; gap: 7px; }
  .logo { font-size: 20px; }
  .brand-text h1, #app-title { font-size: 15px; }
  #lang-select { max-width: 104px; }
  #version-select { max-width: 118px; }
  .topbar-controls { gap: 5px; }
  .topbar-controls .btn { padding-inline: 9px; }
  .ctl { font-size: 11px; gap: 4px; }
  .advanced-toggle { padding-inline: 8px; }
}
