/* Dark (DESIGN.md, 暗い地): the panel follows the system unless the settings' テーマ forces light
   or dark (data-theme on <html>, set by theme.js before the first paint). Role colours turn to
   their light versions, so letters on a filled badge are dark (--on-fill). The two dark rules
   carry the same values, those of core theme.ts (DARK_TOKENS, which the cards on the page take
   too); a unit test compares them. */
:root[data-theme="dark"] {
  --ink: #e6e8ec;
  --muted: #a3abb8;
  --line: #2c323c;
  --edge: #4b5361;
  --bg: #15181d;
  --card: #1d2128;
  --card-edge: #2c323c;
  --on-fill: #15181d;
  --guide: #8b94a1;
  --hover: #272c35;
  --stop-bg: #2c2418;
  --out-bg: #301c1f;
  --accent: #a78bfa;
  --accent-bg: #2a2340;
  --S: #60a5fa;
  --V: #f87171;
  --O: #4ade80;
  --C: #fbbf24;
  --M: #9ca3af;
  --J: #2dd4bf;
  --O-dark: #4ade80;
  --C-dark: #fbbf24;
  --V-dark: #fca5a5;
  --arc: #c4b5fd;
  --tree: #4b5361;
  color-scheme: dark;
}
:root[data-theme="dark"] .diagram .scroller::-webkit-scrollbar-thumb {
  background: var(--edge);
}
:root[data-theme="dark"] .diagram .scroller::-webkit-scrollbar-track {
  background: var(--bg);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ink: #e6e8ec;
    --muted: #a3abb8;
    --line: #2c323c;
    --edge: #4b5361;
    --bg: #15181d;
    --card: #1d2128;
    --card-edge: #2c323c;
    --on-fill: #15181d;
    --guide: #8b94a1;
    --hover: #272c35;
    --stop-bg: #2c2418;
    --out-bg: #301c1f;
    --accent: #a78bfa;
    --accent-bg: #2a2340;
    --S: #60a5fa;
    --V: #f87171;
    --O: #4ade80;
    --C: #fbbf24;
    --M: #9ca3af;
    --J: #2dd4bf;
    --O-dark: #4ade80;
    --C-dark: #fbbf24;
    --V-dark: #fca5a5;
    --arc: #c4b5fd;
    --tree: #4b5361;
    color-scheme: dark;
  }
  :root:not([data-theme="light"]) .diagram .scroller::-webkit-scrollbar-thumb {
    background: var(--edge);
  }
  :root:not([data-theme="light"]) .diagram .scroller::-webkit-scrollbar-track {
    background: var(--bg);
  }
}
:root[data-theme="light"] {
  color-scheme: light;
}
html,
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font:
    13px / 1.55 -apple-system,
    "Hiragino Sans",
    "Noto Sans JP",
    sans-serif;
}
#app {
  padding: 12px 12px 28px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.detail {
  display: flex;
  flex-direction: column;
  gap: 18px;
}

/* header: two rows, the account (logo, name, free tier, close) and this page */
.top {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.top-row {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 30px;
}
.brand {
  display: flex;
  align-items: center;
  gap: 6px;
}
.brand .logo {
  display: block;
  width: 26px;
  height: 26px;
}
.wordmark {
  font-weight: 800;
  font-size: 14px;
  letter-spacing: 0.02em;
  color: var(--ink);
}
.spacer {
  flex: 1;
  min-width: 0;
}
button.icon {
  display: inline-grid;
  place-items: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border-color: transparent;
  background: transparent;
  color: var(--muted);
  font-size: 16px;
  line-height: 1;
}
button.icon:hover {
  background: var(--hover);
  color: var(--ink);
}
/* one focus ring for every control in the panel (the browser's blue one is not used) */
button:focus-visible,
summary:focus-visible,
a:focus-visible,
input:focus-visible,
select:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.strip {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 34px; /* the primary button's height, so the header keeps its height after 解析 */
}
.strip .wide {
  flex: 1;
  font-weight: 600;
}
/* this page's progress: purple, like the sentence position under it (the free tier is navy) */
.prog {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.prog small {
  font-size: 11px;
  font-weight: 500;
  color: var(--muted);
}
.prog .spinner {
  width: 11px;
  height: 11px;
}
.prog .check {
  color: var(--O-dark);
  font-weight: 700;
}
.prog .warn {
  color: var(--C-dark);
}
.pbar {
  position: relative;
  flex: 1;
  min-width: 24px;
  max-width: 140px;
  height: 4px;
  border-radius: 2px;
  background: var(--line);
  overflow: hidden;
}
.pbar i {
  position: absolute;
  inset: 0 auto 0 0;
  border-radius: 2px;
  background: var(--accent);
  transition: width 0.3s;
}
/* a narrow panel keeps the count and drops the bar */
@media (max-width: 330px) {
  .pbar {
    display: none;
  }
}
/* rare actions (再解析): recognisably a button, but not a primary one */
button.quiet {
  flex: none;
  height: 28px;
  padding: 0 10px;
  font-size: 12px;
  color: var(--muted);
  background: transparent;
  border-color: var(--edge);
}
button.quiet:hover:not(:disabled) {
  background: var(--hover);
  color: var(--ink);
}
/* under the header: sending stopped and can carry on (pale orange), or the free tier is out (red) */
.band {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: -8px;
  padding: 8px 8px 8px 12px;
  border-radius: 10px;
  background: var(--stop-bg);
}
/* a band 330px wide or less: the button goes under the text, so the first line stays whole */
@media (max-width: 354px) {
  .band {
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    padding: 8px 10px 10px 12px;
  }
}
.band-text {
  flex: 1;
  min-width: 0;
}
.band-text b {
  display: block;
  font-size: 13px;
}
.band-sub {
  font-size: 12px;
  color: var(--muted);
}
/* "残り 60 文", "約 2 秒" and "目安 $0.81" wrap between each other, never inside */
.band-sub .nw {
  white-space: nowrap;
}
.band .primary {
  flex: none;
  font-weight: 600;
}
.band.out {
  background: var(--out-bg);
}
.band.out b {
  color: var(--V-dark);
}
/* a new version (update-notice.ts): one line in the ink on the hover ground (news, not a stop),
   and a × instead of a button; the × stays beside the text at every width */
.band.update {
  background: var(--hover);
  color: var(--ink);
  padding-right: 6px;
}
.band.update b {
  display: inline;
}
.band.update button.icon {
  flex: none;
}
@media (max-width: 354px) {
  .band.update {
    flex-direction: row;
    align-items: center;
    gap: 10px;
    padding: 8px 6px 8px 12px;
  }
}
.top + .status {
  margin-top: -8px;
}
.loading {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--accent);
  font-weight: 600;
}

/* cards */
.difficulty {
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  height: 3px;
  background: var(--line);
}
.difficulty i {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, var(--O), var(--C), var(--V));
}
.empty {
  padding: 28px 8px;
  text-align: center;
  color: var(--muted);
}
.empty-title {
  font-size: 14px;
  color: var(--ink);
  margin-bottom: 12px;
}

.ja-full {
  font-size: 14px;
  margin: 8px 0 0;
  padding: 8px 10px;
  background: var(--bg);
  border-radius: 8px;
}

/* clause tree & grammar points */
.tree ul {
  list-style: none;
  margin: 0;
  padding-left: 14px;
  border-left: 1px dashed var(--line);
}
.tree > ul {
  padding-left: 0;
  border-left: none;
}
.tree li {
  margin: 4px 0;
}
.tree .ctype {
  font-weight: 700;
  font-size: 11px;
}
.tree .cfunc {
  color: var(--muted);
  font-size: 11px;
  margin-left: 4px;
}
.tree .marker {
  font-size: 11px;
  color: var(--accent);
  margin-left: 4px;
}
.tree .ctext {
  display: block;
  color: var(--ink);
  font-size: 12px;
}
.chips {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  margin-top: 4px;
}
.chip {
  font-size: 11px;
  padding: 0 6px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--card);
  cursor: default;
}
.chip:hover {
  border-color: var(--ink);
}

/* dictionary tooltip in the panel */
.dict-tip {
  position: fixed;
  z-index: 10;
  display: none;
  max-width: 300px;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.14);
  padding: 8px 10px;
  font-size: 12px;
  pointer-events: none;
  overflow: hidden; /* cut at max-height when it fits neither above nor below the word */
}
.dict-tip li.usage {
  list-style: none;
  margin-left: -12px;
}
.dict-tip li.usage .note {
  margin-left: 0;
}

/* footer */
footer {
  margin-top: 6px;
}
details summary {
  cursor: pointer;
  color: var(--muted);
  font-size: 12px;
}
label {
  display: block;
  margin: 6px 0;
  font-size: 12px;
}
input,
select {
  font: inherit;
  width: 100%;
  padding: 5px 7px;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: var(--card);
}
/* box | label, with the hint under the label (never beside it) */
label.check {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: 8px;
  align-items: start;
}
label.check input {
  width: auto;
  margin: 3px 0 0;
}
label.check .hint {
  grid-column: 2;
}
label .hint {
  display: block;
  margin-top: 2px;
  font-size: 11px;
  color: var(--muted);
}
.usage {
  font-size: 11px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  margin-bottom: 6px;
}

/* settings tab */
.settings-view {
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.set-card h2 + * {
  margin-top: 0;
}
.field {
  margin: 10px 0;
}
.field-label {
  font-size: 12px;
  margin-bottom: 4px;
}
.field .hint {
  display: block;
  margin-top: 3px;
  font-size: 11px;
  color: var(--muted);
}
/* the chosen value: white with a navy outline and a tick, never filled like a primary button */
.choices {
  display: flex;
  gap: 6px;
}
button.choice {
  flex: 1;
  min-width: 0;
  min-height: 30px;
  padding: 5px 4px;
  border: 1.5px solid var(--edge);
  border-radius: 8px;
  background: var(--card);
  color: var(--muted);
  font-size: 12px;
  white-space: normal;
}
button.choice:hover {
  color: var(--ink);
}
button.choice[aria-pressed="true"] {
  border-color: var(--ink);
  color: var(--ink);
  font-weight: 600;
}
button.choice[aria-pressed="true"]::before {
  content: "✓ ";
}
/* Japanese breaks between phrases (DESIGN.md, 文字): a label only where its <wbr> are, a hint
   where the browser finds a phrase (auto-phrase; elsewhere it breaks as before). */
button.choice,
.field-label {
  word-break: keep-all;
  overflow-wrap: anywhere;
}
.field .hint,
label .hint,
.hub-pos span {
  word-break: auto-phrase;
}
/* Choices whose labels carry an address (開発者向け › 接続先): always one under another. */
.choices.stack {
  flex-direction: column;
}
/* Three long choices do not fit side by side in a narrow panel: one under another. */
@media (max-width: 330px) {
  .choices.long {
    flex-direction: column;
  }
}

/* ---------- views: 解析 / 復習 / 履歴 ---------- */
/* Bottom tab bar, always on screen like a phone app. */
.tabs {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 20;
  display: flex;
  padding: 4px 8px calc(4px + env(safe-area-inset-bottom));
  background: color-mix(in srgb, var(--card) 92%, transparent);
  backdrop-filter: blur(8px);
  border-top: 1px solid var(--line);
}
.tabs .tab {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  padding: 5px 0 3px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--muted);
  font-weight: 600;
  font-size: 11px;
  cursor: pointer;
}
.tabs .tab svg {
  width: 20px;
  height: 20px;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* the open tab: navy with a bar under it (purple means position) */
.tabs .tab {
  position: relative;
}
.tabs .tab.on {
  color: var(--ink);
}
.tabs .tab.on::after {
  content: "";
  position: absolute;
  left: 18%;
  right: 18%;
  bottom: -1px;
  height: 2px;
  border-radius: 2px;
  background: var(--ink);
}
.tabs .tab:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
body {
  padding-bottom: 64px;
}
.view .view-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.view .sub-h {
  margin-top: 18px;
}
/* ---------- 履歴 ---------- */
.hist {
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.hist-top {
  display: flex;
  align-items: center;
  gap: 8px;
}
.hist-kind button {
  padding: 2px 12px;
  font-size: 12px;
}
/* what is kept and where, in a title (it was a paragraph on every visit) */
button.hist-info {
  flex: none;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 1px solid var(--edge);
  border-radius: 12px;
  background: transparent;
  color: var(--muted);
  font-size: 12px;
  cursor: help;
}
.hist-note {
  margin: -10px 0 0;
  padding: 8px 10px;
  border-radius: 8px;
  background: var(--card);
  font-size: 12px;
  line-height: 1.6;
  color: var(--muted);
}
.hist-empty {
  padding: 18px 8px;
  font-size: 12px;
  line-height: 1.6;
}
.lk-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
/* pages by the day they were last opened: 今日 / 昨日 / 今週 / それより前 */
.pg-groups {
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.pg-grp h3 {
  margin: 0 0 6px;
  font-size: 12px;
  font-weight: 700;
  color: var(--muted);
}
.pg-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-radius: 12px;
  background: var(--card);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.07);
}
.pg {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 10px 6px 10px 12px;
  border-top: 1px solid var(--line);
}
.pg:first-child {
  border-top: 0;
}
.pg-main {
  flex: 1;
  min-width: 0;
  display: grid;
  gap: 3px;
}
.pg-title {
  min-height: 24px;
  font-family: var(--serif);
  font-size: 13px;
  font-weight: 700;
  line-height: 1.4;
  color: var(--ink);
  text-decoration: none;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  overflow-wrap: anywhere;
}
.pg-title:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}
.pg-meta {
  font-size: 11px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}
.pg-del {
  flex: none;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  font-size: 15px;
  line-height: 1;
  color: var(--muted);
  cursor: pointer;
}
.pg-del:hover {
  background: var(--hover);
  color: var(--ink);
}
/* words: the frequent ones first, then the rest by day in the pages' groups; a row is the word and
   its meaning on one line, nothing else (the rest is in the detail, one open under its row) */
.lk-hot-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.lk-row {
  display: flex;
  align-items: center;
  min-height: 40px;
  border-top: 1px solid var(--line);
}
.lk-row:first-child {
  border-top: 0;
}
.pg-list > .lk-row {
  padding: 0 12px;
}
.lk-word {
  font-family: var(--serif);
  font-size: 14px;
  font-weight: 700;
  color: var(--ink);
}
/* the word and its meaning are the button that opens the detail */
button.lk-row-btn {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 8px 0;
  border: 0;
  background: none;
  text-align: left;
  color: inherit;
  cursor: pointer;
}
button.lk-row-btn .lk-word {
  flex: none;
  max-width: 60%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
button.lk-row-btn:hover .lk-word,
button.lk-row-btn[aria-expanded="true"] .lk-word {
  text-decoration: underline;
  text-underline-offset: 3px;
}
.lk-mean-s {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12px;
  color: var(--muted);
}
.lk-words .view-head {
  margin-bottom: 8px;
}
.lk-words .view-head h2 {
  margin: 0;
  font-size: 11px;
  color: var(--muted);
  letter-spacing: 0.06em;
}
.lk-detail {
  display: grid;
  gap: 6px;
  padding: 10px 12px;
  border-radius: 10px;
  background: var(--bg);
}
.lk-detail-row {
  padding-bottom: 8px;
}
.pg-list > .lk-detail-row {
  padding: 0 8px 8px;
}
.lk-dh {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: 8px;
  min-width: 0;
}
.lk-dh .lk-mean {
  margin: 0;
  font-size: 13px;
  color: var(--ink);
  overflow-wrap: anywhere;
}
.lk-when {
  font-size: 11px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.lk-dict {
  font-size: 12px;
  color: var(--ink);
}
.lk-ctx {
  margin: 0;
  font-family: var(--serif);
  font-size: 13px;
  color: var(--ink);
  line-height: 1.5;
}
.lk-ctx mark {
  background: none;
  color: inherit;
  font-weight: 700;
  text-decoration: underline 2px;
  text-underline-offset: 3px;
}
.lk-more summary {
  font-size: 11px;
}
.lk-more .lk-ctx {
  margin-top: 6px;
}
.lk-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}
.lk-foot button {
  min-height: 28px;
  font-size: 12px;
}
.lk-del:hover {
  color: var(--V-dark);
}

/* ---------- sign-in and the free tier ---------- */
.signin form {
  display: flex;
  gap: 6px;
  margin-top: 8px;
}
.signin input {
  flex: 1;
  min-width: 0;
}
.signin .link {
  margin-top: 8px;
  padding: 0;
  border: 0;
  background: none;
  font-size: 12px;
  color: var(--muted);
  text-decoration: underline;
  cursor: pointer;
}
/* the terms box: ticked before the code is sent (or to go on after the terms changed) */
.signin .agree {
  margin-top: 10px;
  font-size: 13px;
}
.signin .agree a,
.rum-notice a {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.signin form.agree-form {
  flex-direction: column;
  align-items: stretch;
  gap: 10px;
}
.signin form.agree-form .agree {
  margin-top: 0;
}
/* under the label, in line with its text (the box and the gap of label.check) */
.signin .agree > .hint {
  display: block;
  margin: 2px 0 0 21px;
  font-size: 11px;
  color: var(--muted);
}
/* the primary button before the box is ticked (or the address typed): no navy fill, so it does
   not read as the next thing to press, and the label still reads (--muted on --line, 4.8:1 light,
   5.6:1 dark). aria-disabled keeps it focusable; forced colours draw it GrayText (core.css). */
.signin button.primary[aria-disabled="true"] {
  background: var(--line);
  border-color: var(--line);
  color: var(--muted);
  cursor: default;
}
/* what the button still needs, under it */
.signin .go-hint {
  margin: 6px 0 0;
  font-size: 11px;
  color: var(--muted);
}
.signin form.agree-form .go-hint {
  margin-top: -4px;
}
.note.error {
  color: var(--V);
}

/* ---------- the notice for 動作の記録 (until the reader picks send or not) ---------- */
.rum-notice .rum-what {
  margin: 8px 0 0;
  padding-left: 18px;
  font-size: 12px;
  color: var(--muted);
}
.rum-notice .rum-what li + li {
  margin-top: 2px;
}
.rum-choose {
  display: flex;
  gap: 8px;
  margin-top: 10px;
}
.rum-choose button {
  min-height: 30px;
  min-width: 72px;
}
/* free-tier gauge beside the logo: a short bar per limit (日 over 月) that fills with what is used */
.quota {
  display: inline-grid;
  grid-template-columns: auto 44px auto; /* one grid for both rows, so the bars line up */
  align-items: center;
  column-gap: 4px;
  row-gap: 4px;
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.q-row {
  --q: var(--ink); /* navy while there is plenty left */
  display: contents;
}
.q-row.warn {
  --q: var(--C);
  --q-text: var(--C-dark); /* the bar's orange is 3.2:1 as text; this is 4.7:1 */
}
.q-row.out {
  --q: var(--V);
  --q-text: var(--V-dark);
}
.q-key {
  color: var(--muted);
}
.q-bar {
  position: relative;
  height: 6px;
  border-radius: 3px;
  background: var(--line);
  overflow: hidden;
}
.q-bar i {
  position: absolute;
  inset: 0 auto 0 0;
  border-radius: 3px;
  background: var(--q);
}
/* used up: the whole bar striped, so it reads without the colour */
.q-row.out .q-bar {
  background: repeating-linear-gradient(135deg, var(--V) 0 3px, color-mix(in srgb, var(--V) 30%, var(--card)) 3px 6px);
}
.q-val {
  color: var(--q-text, var(--q));
}
.account {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin: 6px 0;
  font-size: 12px;
}

/* ---------- before analysis: what the button does, and today's review ---------- */
.intro-line {
  margin: -8px 0 0;
  font-size: 12px;
  color: var(--muted);
}
.intro-sample {
  margin: 4px 0 10px;
  font-family: var(--serif);
  font-size: 15px;
}
.intro-sample span {
  border-bottom: 2px solid var(--c);
  padding-bottom: 1px;
}
.steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 8px;
  counter-reset: step;
}
.steps li {
  display: grid;
  grid-template-columns: 20px 1fr;
  gap: 8px;
  font-size: 13px;
  counter-increment: step;
}
.steps li::before {
  content: counter(step);
  display: grid;
  place-items: center;
  height: 20px;
  border-radius: 6px;
  background: var(--bg);
  color: var(--muted);
  font-size: 11px;
  font-weight: 700;
}
.today-row {
  display: flex;
  align-items: center;
  gap: 10px;
}
.today-row .rv-sub {
  flex: 1;
}

/* the undo toast (core.css) sits above the tab bar */
:root {
  --undo-bottom: calc(64px + env(safe-area-inset-bottom));
}
.steps.plain li {
  grid-template-columns: 10px 1fr;
}
.steps.plain li::before {
  content: "・";
  height: auto;
  background: none;
}

/* the reader asked for less motion: nothing slides or fades (core.css does its own) */
@media (prefers-reduced-motion: reduce) {
  .pbar i {
    transition: none;
  }
}

/* ---------- このページ: the hub (a map of the page beside its sentences) ---------- */
/* The hub fills the panel's height; its list scrolls by itself, the map stays beside it. */
#app.fill {
  height: 100vh;
  padding-bottom: calc(64px + 12px + env(safe-area-inset-bottom));
  overflow: hidden;
}
body:has(#app.fill) {
  padding-bottom: 0;
}
#app.fill > .hub {
  flex: 1;
  min-height: 0;
}
.hub {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.hub-keys,
.hub-pagekeys {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 6px;
  font-size: 11px;
  color: var(--muted);
}
.hub-keys span,
.hub-pagekeys span {
  margin-right: 4px;
  white-space: nowrap;
}
kbd {
  font:
    600 11px / 1 -apple-system,
    "Hiragino Sans",
    sans-serif;
  padding: 2px 4px;
  border: 1px solid var(--edge);
  border-bottom-width: 2px;
  border-radius: 4px;
  background: var(--card);
  color: var(--ink);
}
/* the rows' 詳 / 訳 marks, drawn as under the numbers */
.hub-marks {
  display: flex;
  flex-wrap: wrap;
  gap: 2px 10px;
  margin: 0;
  font-size: 11px;
  color: var(--muted);
}
.hub-marks span {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  white-space: nowrap;
}
.hub-marks .mk {
  font-style: normal;
  color: color-mix(in srgb, var(--accent) 70%, var(--muted));
}
.hub-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 2px 10px;
  margin: 0;
  font-size: 11px;
  color: var(--muted);
}
.hub-legend span {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  white-space: nowrap;
}
.hub-legend .sw {
  display: inline-block;
  width: 12px;
  height: 2px;
  background: var(--muted);
}
.hub-legend .sw.pending {
  height: 0;
  background: none;
  border-top: 2px dotted var(--guide);
}
.hub-legend .sw.failed {
  background: var(--V);
}
.hub-legend .sw.win {
  width: 10px;
  height: 8px;
  background: none;
  border: 1.5px solid var(--accent);
  border-radius: 2px;
}
.hub-body {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr);
  gap: 8px;
}
.hub-map {
  position: relative;
  height: 100%;
  min-height: 120px;
  background: var(--card);
  border-radius: 8px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.07);
  cursor: pointer;
}
.hub-map .m {
  position: absolute;
  left: 6px;
  right: 6px;
  height: 2px;
  border-radius: 1px;
  background: var(--muted);
}
.hub-map .m.pending {
  background: none;
  border-top: 2px dotted var(--guide);
}
.hub-map .m.failed {
  background: var(--V);
}
.hub-map .m.head {
  left: 3px;
  right: 3px;
  height: 3px;
  background: var(--ink);
}
/* the selected sentence: this sentence's place, purple as in the list. It runs past the purple
   frame of the part on screen, edged with the card's colour, so it reads apart from the frame. */
.hub-map .m.sel {
  left: 0;
  right: 0;
  height: 4px;
  border-radius: 0;
  background: var(--accent);
  box-shadow: 0 0 0 1.5px var(--card);
  z-index: 2;
}
.hub-win {
  position: absolute;
  left: 1px;
  right: 1px;
  min-height: 6px;
  /* 2px: a 1.5px border is drawn 1px wide on a 1x screen */
  border: 2px solid var(--accent);
  border-radius: 4px;
  pointer-events: none;
}
/* the list's column: the position line ("5 / 14 文目を開いています") over the list */
.hub-col {
  position: relative;
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
/* The position line and the ? for the list's and the map's key (the card's 記号の見方 button). */
.hub-top {
  display: flex;
  align-items: center;
  gap: 4px;
  min-height: 28px;
}
.hub-top .hub-pos {
  flex: 1;
  min-width: 0;
}
/* The key floats over the list, under the ?, as wide as the column at most, and above the list's
   sticky headings (.hub-h, z-index 2). With .c-pop to outweigh the shared key's own z-index. */
.c-pop.hub-help {
  z-index: 3;
  top: 32px;
  right: 0;
  width: min(300px, 100%);
  display: grid;
  gap: 8px;
}
.c-pop.hub-help[hidden] {
  display: none;
}
/* On the dark ground --line hardly shows (1.1-1.4:1): the key's edge is --edge, so it reads as
   laid over the list. */
:root[data-theme="dark"] .c-pop.hub-help {
  border-color: var(--edge);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .c-pop.hub-help {
    border-color: var(--edge);
  }
}
.hub-pos {
  display: flex;
  align-items: baseline;
  gap: 6px;
  margin: 0;
  font-size: 11px;
  color: var(--muted);
}
.hub-pos b {
  white-space: nowrap;
  font-size: 12px;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.hub-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  display: flex;
  flex-direction: column;
  padding: 0 2px 2px;
}
.hub-list:focus {
  outline: none;
}
.hub-group {
  display: flex;
  flex-direction: column;
  margin-bottom: 14px;
}
/* a section's heading: the UI typeface (the sentences are in the English one), underlined, with
   the numbers of its sentences. It stays at the top of the list while its sentences scroll. */
.hub-h {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 4px 0;
  border-bottom: 1px solid var(--ink);
  background: var(--bg);
}
.hub-h b {
  font-size: 12px;
  font-weight: 700;
  line-height: 1.35;
}
/* the heading is a button: the page scrolls to it (no card) */
.hub-jump {
  min-width: 0;
  min-height: 24px;
  white-space: normal;
  padding: 2px 0;
  border: 0;
  border-radius: 4px;
  background: none;
  color: var(--ink);
  text-align: left;
  cursor: pointer;
}
.hub-jump:hover b {
  text-decoration: underline;
}
/* a heading read as a sentence: its row says so (it is also the section's title above) */
.hub-tag {
  display: inline-block;
  margin-right: 6px;
  padding: 0 5px;
  border: 1px solid var(--edge);
  border-radius: 4px;
  font:
    11px / 16px -apple-system,
    "Hiragino Sans",
    "Noto Sans JP",
    sans-serif;
  color: var(--muted);
  vertical-align: 1px;
}
.hub-h .hub-range {
  flex: none;
  margin-left: auto;
  font-size: 11px;
  color: var(--muted);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
/* one sentence: its number in the page, then the sentence; a thin rule between sentences */
.hub-row {
  position: relative;
  /* flex, not grid: a grid row costs several times more layout on a page of thousands */
  display: flex;
  gap: 6px;
  padding: 8px 6px 8px 0;
  border-bottom: 1px solid var(--line);
  cursor: pointer;
  /* rows out of sight are not laid out (pages of thousands of sentences) */
  content-visibility: auto;
  contain-intrinsic-size: auto 56px;
}
.hub-n {
  flex: none;
  width: max(22px, calc(var(--hub-n, 14px) + 4px));
  padding-top: 1px;
  font-size: 11px;
  color: var(--muted);
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.hub-row:hover {
  background: var(--hover);
}
.hub-t {
  font: 13px / 1.45 var(--serif);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.hub-row.pending .hub-t {
  color: var(--muted);
}
.hub-m {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  margin-top: 2px;
  font-size: 11px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.hub-m .wait::before {
  content: "";
  display: inline-block;
  width: 14px;
  margin-right: 6px;
  vertical-align: middle;
  border-top: 1.5px dotted var(--guide);
}
.hub-m .fail {
  color: var(--V-dark);
}
/* the row's analysis on its way: the shared spinner (core.css), small, then what is done */
.hub-m .busy {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.hub-m .busy .spinner {
  width: 10px;
  height: 10px;
}
.hub-m .busy.deep {
  color: var(--accent);
  font-weight: 600;
}
/* deep is back, the translation made: a quiet 詳 / 訳 under the row's number (both: 詳訳 on one
   line, which fits the number's narrowest column; a second line would grow a one-line row when
   訳 arrives and move its buttons). Explained in the list's ? key. */
.hub-row.deep-done .hub-n::after {
  content: "詳";
}
.hub-row.tr-done .hub-n::after {
  content: "訳";
}
.hub-row.deep-done.tr-done .hub-n::after {
  content: "詳訳";
}
.hub-row.deep-done .hub-n::after,
.hub-row.tr-done .hub-n::after {
  display: block;
  white-space: nowrap;
  margin-top: 1px;
  font-size: 11px;
  line-height: 1;
  color: color-mix(in srgb, var(--accent) 70%, var(--muted));
}
.hub-main {
  flex: 1;
  min-width: 0;
}
/* the chosen sentence (its card is the one on the page): this sentence's place, in purple. The
   box holds the option and, after it, its translation and buttons. */
.hub-sel {
  margin: 4px 0;
  border-radius: 8px;
  background: var(--accent-bg);
  box-shadow: inset 0 0 0 1.5px var(--accent);
}
.hub-row.sel {
  content-visibility: visible;
  cursor: default;
  border-bottom: 0;
}
.hub-row.sel .hub-n {
  color: var(--accent);
  font-weight: 700;
}
.hub-row.sel:hover {
  background: none;
}
/* under the sentence, in line with its text (after the numbers' column) */
.hub-extra {
  padding: 0 8px 10px calc(max(22px, calc(var(--hub-n, 14px) + 4px)) + 6px);
}
.hub-row.sel .hub-t {
  display: block;
}
.hub-extra .ja-line {
  margin-top: 6px;
}
.hub-extra .deep-chip {
  margin-top: 6px;
}
.hub-extra .btn-row {
  margin-top: 6px;
}
.hub-extra .btn-row button {
  font-size: 12px;
  padding: 4px 10px;
  min-height: 28px;
}
/* the row the arrow keys are on, while the list has the focus */
.hub-list:focus-visible .hub-row.active {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
.hub-pv {
  list-style: none;
  margin: 0;
  padding: 0;
}
.hub-pv li {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 3px 0;
}
.hub-pv b {
  flex: 1;
  min-width: 0;
  font: 700 13px / 1.35 var(--serif);
}
.hub-pv span {
  flex: none;
  font-size: 11px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.hub-pv-note,
.hub-pv-none {
  margin: 6px 0 0;
  font-size: 12px;
  color: var(--muted);
}
