/* The study app at /app/study/: the site's tokens, laid out for a desk. */
:root {
  --paper: #F8F3E9;
  --card: #FFFFFF;
  --sunk: #EFE7D8;
  --ink: #1A1A18;
  --muted: #4A4842;
  --link: #8E1528;
  --red: #D0020F;
  --on-red: #FFFFFF;
  --rule: #B3A08E;
  --edge: #9A7874;
  --good: #1D6B3C;
  --good-wash: #DCEFE1;
  --bad: #A3121E;
  --bad-wash: #F6DCDA;
  --jp: "Mojiya JP", "Noto Sans JP", "Hiragino Sans", "Yu Gothic", sans-serif;
  color-scheme: light;
}
:root[data-theme="dark"] {
  --paper: #0E1526;
  --card: #16203A;
  --sunk: #121A2E;
  --ink: #F0E7D6;
  --muted: #C7C0B1;
  --link: #F0E7D6;
  --rule: #333F60;
  --edge: #4E5A7E;
  --good: #8FD4A5;
  --good-wash: #1F3A28;
  --bad: #F2A39C;
  --bad-wash: #4A2220;
  color-scheme: dark;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper: #0E1526;
    --card: #16203A;
    --sunk: #121A2E;
    --ink: #F0E7D6;
    --muted: #C7C0B1;
    --link: #F0E7D6;
    --rule: #333F60;
    --edge: #4E5A7E;
    --good: #8FD4A5;
    --good-wash: #1F3A28;
    --bad: #F2A39C;
    --bad-wash: #4A2220;
    color-scheme: dark;
  }
}

@font-face {
  font-family: "Mojiya JP";
  src: url("/fonts/notosansjp.ttf") format("truetype");
  font-display: swap;
}

/* The face a character is taught in: Klee One, the 教科書体 the stroke diagram is drawn to (ADR-479).
   The lesson and character heroes and Home's next lesson, as on the phone; everything else stays --jp. */
@font-face {
  font-family: "Mojiya Teaching";
  src: url("/fonts/kleeone.ttf") format("truetype");
  font-display: swap;
}
:root .glyph-hero, .home-actions .big-jp { font-family: "Mojiya Teaching", var(--jp); }
h2 .count { font-weight: 700; font-variant-numeric: tabular-nums; }

* { box-sizing: border-box; }
html, body { margin: 0; min-height: 100%; }
/* A phone: no grey tap flash (the pressed states below say it instead), and the
   text keeps its size when the phone turns (ADR-437). */
html { -webkit-tap-highlight-color: transparent; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
button, .btn, .choices button, .tiles button, .jacket, .glyph-tile, a.tile, .rail nav a, .list a, .list .row-link, .act, .chip, .seg-btn { touch-action: manipulation; }
body {
  background: var(--paper);
  color: var(--ink);
  font: 17px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif;
}
a { color: var(--link); }
:focus-visible { outline: 2px solid var(--red); outline-offset: 3px; }
[hidden] { display: none !important; }
.jp, [lang="ja"] { font-family: var(--jp); }
.visually-hidden {
  position: absolute !important;
  /* !important because a more specific rule (.radios legend's width: 100%)
     otherwise widens it past the viewport and the page pans sideways. */
  width: 1px !important; height: 1px !important;
  margin: 0 !important; padding: 0 !important;
  overflow: hidden; clip: rect(0 0 0 0);
  white-space: nowrap;
}
.skip {
  position: absolute; left: 12px; top: 0; z-index: 10;
  transform: translateY(-120%);
  background: var(--card); color: var(--ink);
  padding: 8px 12px; border: 1px solid var(--edge); border-radius: 8px;
}
.skip:focus { transform: none; top: 12px; }
.boot { padding: 24px; color: var(--muted); font-size: 16px; white-space: pre-wrap; }
p.boot { min-height: 100vh; min-height: 100dvh; margin: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 18px; text-align: center; }
p.boot::before {
  content: ""; width: 64px; height: 60px; background: var(--ink);
  -webkit-mask: url("/mark.svg") center / contain no-repeat; mask: url("/mark.svg") center / contain no-repeat;
}
@media (prefers-reduced-motion: no-preference) { p.boot::before { animation: breathe 1.6s ease-in-out infinite; } }
@keyframes breathe { 50% { opacity: 0.45; transform: scale(0.96); } }

/* Shell: a rail on a desk, a bar on a narrow window. */
.shell {
  display: grid;
  grid-template-columns: 232px minmax(0, 1fr);
  min-height: 100vh;
  min-height: 100dvh;
  padding-left: env(safe-area-inset-left); padding-right: env(safe-area-inset-right);
}
.rail {
  position: sticky; top: 0;
  height: 100vh;
  height: 100dvh;
  display: flex; flex-direction: column; gap: 4px;
  padding: 20px 14px;
  border-right: 1px solid var(--rule);
  overflow-y: auto;
}
.brand {
  display: flex; align-items: center; gap: 10px;
  padding: 4px 10px 18px;
  color: var(--ink); text-decoration: none; font-weight: 500;
}
.brand .mark {
  display: block; width: 28px; height: 26px; flex: none;
  background: var(--ink);
  -webkit-mask: url("/mark.svg") center / contain no-repeat;
  mask: url("/mark.svg") center / contain no-repeat;
}
.rail nav ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.rail nav a {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  min-height: 44px; padding: 8px 12px; border-radius: 8px;
  color: var(--muted); text-decoration: none; font-size: 16px;
}
@media (hover: hover) and (pointer: fine) { .rail nav a:hover { background: var(--sunk); color: var(--ink); } }
.rail nav a:active { background: var(--sunk); color: var(--ink); }
.rail nav a[aria-current="page"] { background: var(--card); color: var(--ink); font-weight: 500; box-shadow: inset 3px 0 0 var(--red); }
.count {
  min-width: 26px; padding: 0 7px; border-radius: 12px;
  background: var(--red); color: var(--on-red);
  font-size: 13px; line-height: 22px; text-align: center; font-weight: 500;
}
/* Account line, Sign out and theme share one left edge, the nav icons' own;
   the site's links close the rail. */
/* Upgrade and Support Mojiya, set apart under the sections by a rule. */
.rail nav li:not(.extra) + li.extra { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--rule); }
.rail .foot { margin-top: auto; display: flex; flex-direction: column; gap: 4px; padding: 12px 12px 0; font-size: 14px; }
.rail .foot a { color: var(--muted); }
.rail .foot .who { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; padding: 12px 0 0; border-top: 1px solid var(--rule); color: var(--muted); }
.rail .foot .who .line { display: flex; align-items: center; gap: 10px; max-width: 100%; min-width: 0; color: var(--ink); }
.rail .foot .who .line .icon { width: 20px; height: 20px; color: var(--muted); }
.rail .foot .who .line span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rail .foot .btn { align-self: flex-start; justify-content: flex-start; padding-inline: 0; min-height: 32px; }
.rail .foot .links { display: flex; flex-wrap: wrap; gap: 2px 14px; margin-top: 4px; padding: 10px 0 14px; border-top: 1px solid var(--rule); font-size: 13px; }

main { min-width: 0; padding: 32px clamp(20px, 4vw, 56px) 64px; }
main:focus { outline: none; }
.page { max-width: 1080px; margin: 0 auto; }
.narrow { max-width: 680px; margin: 0 auto; }

h1 { font-size: clamp(1.4rem, 1.1rem + 1.4vw, 1.875rem); line-height: 1.2; font-weight: 600; letter-spacing: -0.02em; margin: 0 0 6px; }
h2 { font-size: clamp(1.1rem, 1rem + 0.4vw, 1.25rem); line-height: 1.3; font-weight: 500; margin: 28px 0 10px; }
h3 { font-size: 17px; font-weight: 500; margin: 0 0 6px; }
p { margin: 0 0 10px; }
.lede { color: var(--muted); margin: 0 0 22px; max-width: 42em; }
.muted { color: var(--muted); }
.small { font-size: 14px; }

/* Controls */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 44px; padding: 10px 18px;
  font: inherit; font-size: 16px; font-weight: 500;
  color: var(--ink); background: var(--card);
  border: 1px solid var(--edge); border-radius: 8px;
  cursor: pointer; text-decoration: none;
}
@media (hover: hover) and (pointer: fine) { .btn:hover { border-color: var(--ink); } }
.btn.primary { background: var(--red); color: var(--on-red); border-color: var(--red); }
@media (hover: hover) and (pointer: fine) { .btn.primary:hover { text-decoration: underline; } }
.btn.quiet { background: transparent; border-color: transparent; color: var(--link); padding-inline: 8px; }
/* Sign in with Google as Google's branding guidelines draw it (ADR-480): light fill, stroke and label, and the dark set under the dark theme. */
.btn.google { background: #FFFFFF; color: #1F1F1F; border: 1px solid #747775; border-radius: 4px; padding-inline: 12px; gap: 10px; font-size: 14px; font-weight: 500; }
.btn.google img { width: 20px; height: 20px; }
.btn.google .g-dark { display: none; }
:root[data-theme="dark"] .btn.google { background: #131314; color: #E3E3E3; border-color: #8E918F; }
:root[data-theme="dark"] .btn.google .g-light { display: none; }
:root[data-theme="dark"] .btn.google .g-dark { display: inline; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .btn.google { background: #131314; color: #E3E3E3; border-color: #8E918F; }
  :root:not([data-theme="light"]) .btn.google .g-light { display: none; }
  :root:not([data-theme="light"]) .btn.google .g-dark { display: inline; }
}
@media (hover: hover) and (pointer: fine) { .btn.quiet:hover { text-decoration: underline; } }
.btn.good { background: var(--good); border-color: var(--good); color: var(--paper); }
.btn.bad { background: var(--bad); border-color: var(--bad); color: var(--paper); }
.btn[disabled], .btn[aria-disabled="true"] { opacity: 0.45; cursor: not-allowed; }
.btn.wide { width: 100%; }
kbd {
  font: 12px/1 ui-monospace, monospace;
  padding: 3px 6px; border-radius: 4px;
  border: 1px solid var(--edge); color: var(--muted); background: var(--paper);
}
.row { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }
.row.end { justify-content: flex-end; }
.spread { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; justify-content: space-between; }

input[type="text"], input[type="search"], select, textarea {
  font: inherit; color: var(--ink); background: var(--card);
  border: 1px solid var(--edge); border-radius: 8px;
  min-height: 44px; padding: 8px 12px;
}
input[type="text"]:focus, input[type="search"]:focus, select:focus, textarea:focus { border-color: var(--ink); }

/* Cards and panels */
.card {
  background: var(--card); border: 1px solid var(--edge); border-radius: 12px;
  padding: 18px 20px;
}
.grid { display: grid; gap: 16px; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
.figures { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); margin: 0 0 24px; }
.figure { background: var(--card); border: 1px solid var(--edge); border-radius: 12px; padding: 14px 16px; }
.figure .value { display: block; font-size: 30px; line-height: 1.1; font-weight: 500; }
.figure .label { display: block; color: var(--muted); font-size: 14px; margin-top: 4px; }
.figure .note { display: block; color: var(--muted); font-size: 13px; margin-top: 2px; }

.home-actions { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); margin-bottom: 28px; }
.home-actions .card { display: flex; flex-direction: column; gap: 10px; }
.home-actions .card .btn { align-self: flex-start; }
.big-jp { font-family: var(--jp); font-size: 56px; line-height: 1; }

.bars { display: flex; flex-direction: column; gap: 10px; }
.bar-row { display: grid; grid-template-columns: 110px minmax(0, 1fr) 120px; gap: 12px; align-items: center; font-size: 15px; }
.meter { height: 10px; background: var(--sunk); border-radius: 8px; overflow: hidden; position: relative; }
.meter span { display: block; height: 100%; background: var(--red); }
.meter span.met { position: absolute; left: 0; top: 0; background: var(--edge); opacity: 0.6; }
.fc-bars { display: flex; gap: 4px; margin: 8px 0 4px; }
.fc-col { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; padding: 0; border: 0; background: none; font: inherit; color: inherit; cursor: pointer; }
.fc-total { height: 16px; font-size: 12px; font-weight: 500; line-height: 16px; white-space: nowrap; }
.fc-bar { width: 100%; height: 90px; display: flex; flex-direction: column; justify-content: flex-end; }
.fc-stack { display: flex; flex-direction: column; border-radius: 3px 3px 0 0; overflow: hidden; min-height: 3px; }
.fc-seg { display: block; flex-basis: 0; min-height: 0; }
.fc-stack.empty { background: color-mix(in srgb, var(--ink) 12%, transparent); }
.fc-hour { font-size: 10px; color: var(--muted); white-space: nowrap; }
.fc-hour.on { color: var(--ink); font-weight: 600; }
.fc-col[aria-pressed="true"] .fc-bar { outline: 2px solid var(--ink); outline-offset: 1px; }
.fc-legend { margin: 4px 0 8px; }
.fc-head { font-size: 14px; font-weight: 500; margin-bottom: 4px; }
.fc-key { display: flex; flex-wrap: wrap; gap: 4px 12px; font-size: 13px; color: var(--muted); }
.fc-pool { display: inline-flex; align-items: center; gap: 6px; }
.fc-pool strong { color: var(--ink); font-weight: 500; }
.fc-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
/* A supporter bar's sheen sweeps the filled length every 3.2 s (ADR-425). The reduced-motion
   rules below match `*`, which no pseudo-element is, so the sweep runs only where motion is
   allowed (and in the off twin); otherwise the sheen rests off the bar's left end. */
.meter.leaf span { position: relative; overflow: hidden; }
.meter.leaf span::after { content: ""; position: absolute; top: -50%; bottom: -50%; left: -30%; width: 25%; background: rgba(255, 255, 255, 0.22); transform: skewX(-25deg); }
@media (prefers-reduced-motion: no-preference) { :root:not([data-reduce-motion="on"]) .meter.leaf span::after { animation: leaf-sheen 3.2s linear infinite; } }
:root[data-reduce-motion="off"] .meter.leaf span::after { animation: leaf-sheen 3.2s linear infinite; }
@keyframes leaf-sheen { to { left: 110%; } }

/* Lists */
.list { list-style: none; margin: 0; padding: 0; }
.list > li { border-top: 1px solid var(--rule); }
.list > li:last-child { border-bottom: 1px solid var(--rule); }
.list a, .list button.rowlink {
  display: flex; align-items: center; gap: 14px; width: 100%;
  min-height: 52px; padding: 10px 6px;
  color: inherit; text-decoration: none; text-align: left;
  font: inherit; background: none; border: 0; cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .list a:hover, .list button.rowlink:hover { background: var(--sunk); } }
/* A link drawn as a button (a dictionary's Homepage) sits in its row beside the real buttons, not on a full-width line of its own. */
.list a.btn { display: inline-flex; width: auto; min-height: 44px; padding: 10px 18px; font-size: 16px; font-weight: 500; }
.list a.btn.quiet { padding-inline: 8px; }
@media (hover: hover) and (pointer: fine) { .list a.btn.quiet:hover { background: transparent; } }
.list .lead { font-size: 17px; font-weight: 500; min-width: 10em; }
.list .lead[lang="ja"] { font-family: var(--jp); font-size: 26px; font-weight: 400; min-width: 2.4em; text-align: center; }
.list .text { flex: 1; min-width: 0; }
.list .text .sub { display: block; color: var(--muted); font-size: 14px; }
.list .tail { color: var(--muted); font-size: 14px; white-space: nowrap; }
/* A finished lesson wears the dye, as the phone's finished discs do (ADR-404). */
.list .tail.learned { color: var(--red); font-weight: 500; }
.tag { display: inline-block; font-size: 12px; padding: 1px 8px; border-radius: 12px; border: 1px solid var(--edge); color: var(--muted); }
.tag.lock { border-color: var(--edge); }

.tiles-grid { display: grid; gap: 8px; grid-template-columns: repeat(auto-fill, minmax(64px, 1fr)); }
.tiles-grid a, .tiles-grid button {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  aspect-ratio: 1; border-radius: 12px; border: 1px solid var(--edge);
  background: var(--card); color: var(--ink); text-decoration: none; cursor: pointer;
  font: inherit; font-family: var(--jp); font-size: 28px;
}
.tiles-grid .met { background: var(--good-wash); }
.tiles-grid .seen { background: var(--sunk); }
.tiles-grid [aria-current="true"] { outline: 2px solid var(--red); }

/* Two panes: a list and its detail, side by side on a desk. */
main { container-type: inline-size; }
.panes { display: grid; grid-template-columns: minmax(220px, 300px) minmax(0, 1fr); gap: 24px; align-items: start; }
@container (max-width: 640px) {
  .panes { grid-template-columns: 1fr; }
  .panes > .pane-list { max-height: 50vh; }
  .panes > .pane-detail { position: static; }
}
.panes > .pane-list { max-height: calc(100vh - 160px); max-height: calc(100dvh - 160px); overflow-y: auto; border: 1px solid var(--edge); border-radius: 12px; background: var(--card); }
.panes > .pane-list .list > li:first-child { border-top: 0; }
.panes > .pane-list:has(> .filters) { padding: 12px 14px; }
.panes > .pane-detail { position: sticky; top: 24px; }
.filters { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin: 0 0 16px; }
.filters input[type="search"] { flex: 1; min-width: 0; }
.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  min-height: 36px; padding: 6px 14px; border-radius: 12px;
  border: 1px solid var(--edge); background: var(--card); color: var(--ink);
  font: inherit; font-size: 15px; cursor: pointer;
}
.chip[aria-pressed="true"] { background: var(--ink); color: var(--paper); border-color: var(--ink); }

/* Facts */
.facts { display: grid; grid-template-columns: fit-content(40%) minmax(0, 1fr); gap: 6px 18px; margin: 0; }
.facts dt { color: var(--muted); font-size: 14px; padding-top: 2px; }
.facts dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
/* fact() wraps each pair in a div (valid in a dl); the grid lays out the
   dt and dd, not the wrapper, so a long dd wraps in its column instead of
   widening the max-content one off the card (ADR-403). */
.facts > div { display: contents; }
.glyph-hero { font-family: var(--jp); font-size: clamp(4rem, 16vw, 7.5rem); line-height: 1; margin: 6px 0 10px; }
.strokes { width: min(280px, 100%); aspect-ratio: 1; border: 1px solid var(--rule); border-radius: 12px; background: var(--card); }
.strokes svg { display: block; width: 100%; height: 100%; }
.strokes path { fill: none; stroke: var(--ink); stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.strokes text { fill: var(--red); font: 8px system-ui, sans-serif; }
.strokes .guide { stroke: var(--rule); stroke-width: 0.5; stroke-dasharray: 2 2; }
.strokes path.shadow { stroke: var(--rule); opacity: 0.45; }
.replay { margin-top: 4px; }
@media (prefers-reduced-motion: no-preference) {
  .strokes.play path.ink { stroke-dasharray: 1; stroke-dashoffset: 1; animation: write 0.55s ease-in-out forwards; animation-delay: calc(var(--i) * 0.62s + 0.2s); }
  .strokes.play text.num { opacity: 0; animation: arrive-num 0.2s ease-out forwards; animation-delay: calc(var(--i) * 0.62s + 0.2s); }
}
@media (prefers-reduced-motion: reduce) { :root:not([data-reduce-motion="off"]) .replay { display: none; } }
@keyframes write { to { stroke-dashoffset: 0; } }
@keyframes arrive-num { to { opacity: 1; } }
.sentence { padding: 14px 16px; border-radius: 12px; background: var(--sunk); margin: 0 0 12px; }
.sentence .ja { font-family: var(--jp); font-size: 22px; line-height: 2; }
.sentence .en { color: var(--muted); }
ruby rt { font-size: 0.5em; color: var(--muted); }

/* The study card */
.study-bar {
  display: flex; align-items: center; gap: 16px;
  max-width: 720px; margin: 0 auto 18px;
}
.study-bar .title { flex: 1; min-width: 0; }
.study-bar .title strong { display: block; font-weight: 500; }
.study-bar .title span { color: var(--muted); font-size: 14px; }
.progress { height: 6px; background: var(--sunk); border-radius: 3px; overflow: hidden; max-width: 720px; margin: 0 auto 26px; }
.progress span { display: block; height: 100%; background: var(--red); transition: width 0.2s; }
.study { width: 100%; max-width: 720px; margin: 0 auto; display: flex; flex-direction: column; align-items: center; gap: 14px; text-align: center; min-width: 0; }
.study .kind { color: var(--muted); font-size: 14px; letter-spacing: 0.02em; }
.study .prompt-glyph { font-family: var(--jp); font-size: clamp(4rem, 18vw, 7rem); line-height: 1.05; }
.study .prompt-word { font-family: var(--jp); font-size: clamp(2rem, 8vw, 3.5rem); line-height: 1.2; }
.study .prompt-text { font-size: clamp(1.15rem, 1rem + 1vw, 1.625rem); font-weight: 500; }
.study .ask { color: var(--muted); font-size: 15px; }
.study .counters { color: var(--muted); font-size: 14px; }
.choices { display: grid; gap: 10px; width: 100%; max-width: 560px; grid-template-columns: 1fr 1fr; }
.choices button {
  display: flex; align-items: center; gap: 12px; text-align: left;
  min-height: 56px; padding: 10px 14px; border-radius: 12px;
  border: 1px solid var(--edge); background: var(--card); color: var(--ink);
  font: inherit; cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .choices button:hover:not([disabled]) { border-color: var(--ink); } }
.choices button kbd { flex: none; }
.choices button.out { opacity: 0.4; text-decoration: line-through; cursor: default; }
.choices button.right { background: var(--good-wash); border-color: var(--good); }
.slots { display: flex; gap: 8px; justify-content: center; font-family: var(--jp); font-size: 40px; }
.slots span { min-width: 1.4em; padding: 2px 6px; border-bottom: 2px solid var(--edge); }
.slots span.fixed { border-bottom-color: transparent; color: var(--muted); }
.slots span.filled { border-bottom-color: var(--good); }
.tiles { display: grid; gap: 8px; grid-template-columns: repeat(auto-fill, minmax(72px, 1fr)); width: 100%; max-width: 420px; }
.tiles button {
  aspect-ratio: 1; border-radius: 12px; border: 1px solid var(--edge);
  background: var(--card); color: var(--ink); cursor: pointer;
  font-family: var(--jp); font-size: 30px; position: relative;
}
.tiles button small { position: absolute; left: 6px; top: 4px; font: 11px system-ui, sans-serif; color: var(--muted); }
.tiles button.out { opacity: 0.3; cursor: default; }
.tiles button.wrong { border-color: var(--bad); background: var(--bad-wash); }
.cloze { font-family: var(--jp); font-size: 26px; line-height: 2.1; }
.cloze .gap { display: inline-block; min-width: 3em; border-bottom: 2px solid var(--ink); padding: 0 4px; line-height: 1.4; }
.cloze .hit { background: var(--good-wash); color: var(--good); border-radius: 4px; padding: 0 2px; }
.cloze .miss { background: var(--bad-wash); color: var(--bad); border-radius: 4px; padding: 0 2px; }
.cloze .letter-miss { color: var(--bad); text-decoration: underline; }
.english { color: var(--muted); font-size: 18px; }
.english mark { background: var(--bad-wash); color: var(--bad); border-radius: 3px; padding: 0 2px; }
.english mark.authored { background: transparent; color: var(--link); font-weight: 500; }
.layer { font-size: 17px; }
.answer-field { display: flex; gap: 8px; width: 100%; max-width: 480px; min-width: 0; }
.answer-field input { flex: 1; min-width: 0; font-size: 20px; text-align: center; }
.answer-field input.right { border-color: var(--good); background: var(--good-wash); color: var(--good); }
.answer-field input.wrong { border-color: var(--bad); background: var(--bad-wash); color: var(--bad); }
.notice { color: var(--muted); }
.reveal { width: 100%; border-top: 1px solid var(--rule); padding-top: 14px; display: flex; flex-direction: column; align-items: center; gap: 8px; }
.verdict { width: 100%; max-width: 480px; display: flex; flex-direction: column; gap: 8px; }
.rank { color: var(--muted); font-size: 15px; }
.rank .up { color: var(--good); font-weight: 500; }
.rank .down { color: var(--bad); font-weight: 500; }
.grades { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; width: 100%; max-width: 560px; }
.grades .btn { flex-direction: column; gap: 2px; }
.grades .btn small { font-weight: 400; font-size: 12px; opacity: 0.85; }
/* The phone's grade row (Feedback.kt FEEDBACK_LIGHT and FEEDBACK_DARK): four hues chosen at one
   lightness within each scheme, so one ink serves all four. The colour-blind scheme copies them. */
:root { --g-again: #B3261E; --g-hard: #8C6D1F; --g-good: #2E6B4F; --g-easy: #3A5A9B; --g-ink: #FFFFFF; }
:root[data-theme="dark"] { --g-again: #FFB4AB; --g-hard: #EBC66E; --g-good: #8FD5AE; --g-easy: #B0C7FF; --g-ink: #16191A; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { --g-again: #FFB4AB; --g-hard: #EBC66E; --g-good: #8FD5AE; --g-easy: #B0C7FF; --g-ink: #16191A; }
}
.grades .btn[data-grade] { color: var(--g-ink); border-color: transparent; }
.grades .btn[data-grade="again"] { background: var(--g-again); }
.grades .btn[data-grade="hard"] { background: var(--g-hard); }
.grades .btn[data-grade="good"] { background: var(--g-good); }
.grades .btn[data-grade="easy"] { background: var(--g-easy); }
.keys { color: var(--muted); font-size: 13px; margin-top: 8px; }
.keys kbd { margin: 0 2px; }

.receipt { max-width: 720px; margin: 0 auto; }
.receipt .figures { grid-template-columns: repeat(4, 1fr); }
.receipt .row-hit { color: var(--good); }
.receipt .row-miss { color: var(--bad); }

/* Dictionary and the side panel */
.hits { list-style: none; padding: 0; margin: 0; }
.hits li { border-top: 1px solid var(--rule); padding: 12px 4px; }
.hits .word { font-family: var(--jp); font-size: 24px; font-weight: 500; }
.hits .reading { color: var(--muted); font-family: var(--jp); }
.sense { margin: 4px 0 0; }
.side {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 20;
  width: min(440px, 100%); padding: 20px 22px; overflow-y: auto;
  background: var(--card); border-left: 1px solid var(--edge);
  box-shadow: -12px 0 32px rgba(0, 0, 0, 0.12);
}
.side .close { position: absolute; right: 12px; top: 12px; }
.pad svg { display: block; width: min(320px, 80vw); aspect-ratio: 1; border: 1px solid var(--edge); border-radius: 12px; background: var(--card); touch-action: none; cursor: crosshair; }
.pad .guide { stroke: var(--rule); stroke-width: 0.5; stroke-dasharray: 2 2; }
.pad .ink, .pad .drawn { fill: none; stroke: var(--ink); stroke-width: 3.5; stroke-linecap: round; stroke-linejoin: round; }
.pad .pending { fill: none; stroke: var(--edge); stroke-width: 3; stroke-linecap: round; opacity: 0.55; }
.pad .live { fill: none; stroke: var(--red); stroke-width: 3.5; stroke-linecap: round; stroke-linejoin: round; }
.pad-bar { display: flex; align-items: center; gap: 12px; justify-content: center; }
.candidates { display: flex; flex-wrap: wrap; gap: 6px; }
.candidates button { font-family: var(--jp); font-size: 26px; min-width: 48px; min-height: 48px; border-radius: 8px; border: 1px solid var(--edge); background: var(--card); color: var(--ink); cursor: pointer; }

/* Forms */
.form { display: flex; flex-direction: column; gap: 4px; max-width: 720px; }
.form fieldset { border: 1px solid var(--rule); border-radius: 12px; padding: 14px 18px 16px; margin: 0 0 18px; }
.form legend { padding: 0 6px; font-weight: 500; }
.form .field { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 4px 18px; align-items: center; padding: 10px 0; border-top: 1px solid var(--rule); }
.form .field:first-of-type { border-top: 0; }
.form .field .help { grid-column: 1 / -1; color: var(--muted); font-size: 14px; }
.form label { font-weight: 400; }
.switch { width: 22px; height: 22px; accent-color: var(--red); }

.empty { padding: 28px; text-align: center; color: var(--muted); border: 1px dashed var(--edge); border-radius: 12px; }
.note-line { padding: 12px 16px; border-left: 3px solid var(--edge); background: var(--sunk); border-radius: 0 8px 8px 0; margin: 0 0 16px; }

/* Interface font, colour-blind verdicts and larger furigana, from Settings. */
@font-face { font-family: "Mojiya UI Manrope"; src: url("/fonts/ui/manrope.ttf") format("truetype"); font-display: swap; }
@font-face { font-family: "Mojiya UI Jakarta"; src: url("/fonts/ui/jakarta.ttf") format("truetype"); font-display: swap; }
@font-face { font-family: "Mojiya UI Hanken"; src: url("/fonts/ui/hanken.ttf") format("truetype"); font-display: swap; }
@font-face { font-family: "Mojiya UI Inter"; src: url("/fonts/ui/inter.ttf") format("truetype"); font-display: swap; }
:root[data-ui-font="manrope"] body { font-family: "Mojiya UI Manrope", system-ui, sans-serif; }
:root[data-ui-font="jakarta"] body { font-family: "Mojiya UI Jakarta", system-ui, sans-serif; }
:root[data-ui-font="hanken"] body { font-family: "Mojiya UI Hanken", system-ui, sans-serif; }
:root[data-ui-font="inter"] body { font-family: "Mojiya UI Inter", system-ui, sans-serif; }
:root[data-colorblind] { --good: #1F5FA8; --good-wash: #DCE8F6; --bad: #A84C00; --bad-wash: #F8E3D2; }
:root[data-colorblind][data-theme="dark"] { --good: #9CC4F2; --good-wash: #1E3048; --bad: #F4B27A; --bad-wash: #4A2E18; }
@media (prefers-color-scheme: dark) {
  :root[data-colorblind]:not([data-theme="light"]) { --good: #9CC4F2; --good-wash: #1E3048; --bad: #F4B27A; --bad-wash: #4A2E18; }
}
:root[data-large-ruby] ruby rt { font-size: 0.68em; }

.good-ink { color: var(--good); }
.bad-ink { color: var(--bad); }
.notice.bad-ink { color: var(--bad); min-height: 1.5em; }

/* The phone's look: paper cards, the rail's drawn icons, the place behind Home. */
/* Flat, as the phone's Panel is (ADR-479): a hairline carries the edge, and the drop shadow that
   sat under every card is gone — paper does not float. --lift stays a name so a future floating
   surface can set its own. */
:root { --lift: none; --tile: var(--card); }
.card, a.tile, .figure, .word-card, .badge, .panes > .pane-list { border-color: color-mix(in srgb, var(--edge) 45%, transparent); box-shadow: var(--lift); }
.card { border-radius: 12px; }
.btn { border-radius: 999px; transition: transform 160ms cubic-bezier(0.23, 1, 0.32, 1), background-color 0.15s, border-color 0.15s, box-shadow 0.15s; }
.btn.primary { box-shadow: 0 2px 0 color-mix(in srgb, var(--red) 60%, #000); font-weight: 600; }
@media (hover: hover) and (pointer: fine) { .btn.primary:hover { text-decoration: none; filter: brightness(1.06); } }
.btn:active:not([disabled]) { transform: scale(0.97); box-shadow: none; transition-duration: 120ms; }
/* A press, on the other things the thumb holds (ADR-437). */
.choices button, .tiles button, .jacket { transition: transform 160ms cubic-bezier(0.23, 1, 0.32, 1), border-color 0.15s; }
.choices button:active:not([disabled]), .tiles button:active:not([disabled]), .jacket:active { transform: scale(0.97); transition-duration: 120ms; }
.chip { transition: background-color 0.15s, color 0.15s; }
.figure .value { font-size: 34px; font-weight: 600; letter-spacing: -0.01em; }
.home-actions .card { min-height: 190px; }
.home-actions .big-jp { width: 84px; height: 84px; display: grid; place-items: center; border-radius: 12px; background: var(--paper); border: 1px solid color-mix(in srgb, var(--edge) 45%, transparent); font-size: 52px; }

.rail nav a { gap: 12px; justify-content: flex-start; transition: background-color 0.15s, color 0.15s; }
.rail nav a .label { flex: 1; }
.rail nav a[aria-current="page"] { box-shadow: none; background: color-mix(in srgb, var(--red) 10%, var(--card)); color: var(--ink); font-weight: 600; }
.rail nav a[aria-current="page"] .icon { color: var(--red); }
.icon { display: inline-flex; flex: none; width: 24px; height: 24px; color: inherit; }
.icon svg { width: 100%; height: 100%; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; overflow: visible; }
.icon svg text { fill: currentColor; stroke: none; font-family: var(--jp); }

/* The streak strip: seven hanko under their dates (StreakHanko). */
.streak { text-align: center; }
.week { list-style: none; margin: 14px 0 12px; padding: 0; display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; }
.week li { display: flex; flex-direction: column; align-items: center; gap: 6px; font-size: 13px; color: var(--muted); }
.week li.lit { color: var(--ink); }
.hanko { display: inline-flex; width: 34px; height: 34px; color: #D15C4E; }
main h1[tabindex="-1"]:focus { outline: none; }
:root[data-theme="dark"] .hanko { color: #E2786A; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .hanko { color: #E2786A; } }
.hanko svg { width: 100%; height: 100%; }
.hanko .hk-frame { fill: none; stroke: var(--edge); stroke-width: 2.1; }
.hanko.stamped .hk-frame { stroke: currentColor; }
.hanko .hk-pad { fill: currentColor; }
.meter { height: 12px; border-radius: 8px; }
.meter span { border-radius: 8px; transition: width 0.4s ease; }

/* The place behind Home. Day is the wide drawing on a desk where there is
   one; night and a narrow window take the phone's tall poster. Tiles keep
   their fill unless Home transparency is on: 0.78 by day, 0.72 at night,
   the phone's paperAlpha. */
.backdrop { position: fixed; inset: 0; z-index: -1; display: none; background: var(--paper) var(--place-v) center bottom / cover no-repeat; }
:root[data-papered] .backdrop { display: block; }
@media (min-width: 801px) and (min-aspect-ratio: 1/1) { .backdrop { background-image: var(--place-w); } }
:root[data-theme="dark"] .backdrop { background-image: var(--place-n); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .backdrop { background-image: var(--place-n); } }
/* The wide night drawing on a desk, after the tall night rules it overrides. */
@media (min-width: 801px) and (min-aspect-ratio: 1/1) {
  :root[data-theme="dark"] .backdrop { background-image: var(--place-nw); }
}
@media (min-width: 801px) and (min-aspect-ratio: 1/1) and (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .backdrop { background-image: var(--place-nw); }
}
:root[data-papered] body { background: transparent; }
:root[data-papered] .rail { background: color-mix(in srgb, var(--paper) 88%, transparent); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); }
:root[data-papered] main .card, :root[data-papered] main .note-line { background: var(--paper); }
:root[data-papered] main .figure { background: var(--card); }
:root[data-papered] main h1 { text-shadow: 0 1px 12px color-mix(in srgb, var(--paper) 90%, transparent); }
:root[data-papered] main > .page > .spread .lede { display: inline-block; padding: 2px 10px; margin-left: -10px; border-radius: 8px; background: color-mix(in srgb, var(--paper) 80%, transparent); }
:root[data-papered="through"] main .card { background: color-mix(in srgb, var(--paper) 78%, transparent); }
:root[data-papered][data-theme="dark"] main .card { background: #2A3554; }
:root[data-papered="through"][data-theme="dark"] main .card { background: rgba(42, 53, 84, 0.72); }
@media (prefers-color-scheme: dark) {
  :root[data-papered]:not([data-theme="light"]) main .card { background: #2A3554; }
  :root[data-papered="through"]:not([data-theme="light"]) main .card { background: rgba(42, 53, 84, 0.72); }
}

/* A lesson's introduction: the character, then its writing. */
.lesson-intro { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 24px 36px; align-items: start; padding: 26px 28px; text-align: left; }
.lesson-intro .who { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
.lesson-intro .glyph-hero { margin: 0; font-size: clamp(5rem, 14vw, 8.5rem); }
.lesson-intro .prompt-text { margin: 0 0 12px; font-size: 22px; font-weight: 600; }
.lesson-intro .facts { grid-template-columns: repeat(2, max-content); gap: 12px 40px; }
.lesson-intro .facts > div { display: block; }
.lesson-intro .facts dt { font-size: 13px; }
.lesson-intro .facts dd[lang="ja"], .lesson-intro .facts dd .jp { font-size: 19px; }
.lesson-intro .how { display: flex; flex-direction: column; align-items: center; }
.lesson-intro .strokes { width: 260px; }
@container (max-width: 640px) { .lesson-intro { grid-template-columns: 1fr; } .lesson-intro .how { align-items: flex-start; } }

/* A book reads as a page, not a stack of sentence boxes. */
.book { max-width: 44rem; margin: 18px auto 0; padding: clamp(24px, 5vw, 56px) clamp(20px, 6vw, 72px); background: var(--card); border-radius: 12px; box-shadow: var(--lift); border: 1px solid color-mix(in srgb, var(--edge) 35%, transparent); }
.book .sentence { background: none; padding: 0; margin: 0 0 1.05em; border-radius: 0; font-size: inherit; line-height: inherit; }
.book .tap:focus-visible { background: color-mix(in srgb, var(--red) 14%, transparent); }
@media (hover: hover) and (pointer: fine) { .book .tap:hover { background: color-mix(in srgb, var(--red) 14%, transparent); } }

/* The shelf: jackets three-by-two at their smallest, progress along the foot. */
.jackets { list-style: none; margin: 0 0 24px; padding: 0; display: grid; gap: 18px 16px; grid-template-columns: repeat(auto-fill, minmax(min(132px, 30%), 1fr)); }
.jackets li { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.jacket { position: relative; display: block; width: 100%; aspect-ratio: 2 / 3; padding: 0; overflow: hidden; border-radius: 12px; border: 1px solid color-mix(in srgb, var(--edge) 45%, transparent); background: color-mix(in srgb, var(--red) 12%, var(--card)); box-shadow: var(--lift); cursor: pointer; font: inherit; color: var(--ink); }
.jacket img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.jacket .caption { position: absolute; left: 0; right: 0; bottom: 6px; padding: 6px 8px 8px; font-size: 12px; line-height: 1.3; color: #fff; background: rgba(0, 0, 0, 0.55); text-align: left; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.jacket .plain { position: absolute; inset: 0; display: grid; place-items: center; padding: 12px; font-family: var(--jp); font-size: 15px; line-height: 1.4; text-align: center; overflow: hidden; }
.jacket .strip { position: absolute; left: 0; right: 0; bottom: 0; height: 6px; background: rgba(0, 0, 0, 0.18); }
.jacket .strip span { display: block; height: 100%; background: var(--red); }
@media (hover: hover) and (pointer: fine) { .jacket:hover { transform: translateY(-2px); } }
@media (prefers-reduced-motion: no-preference) { .jacket { transition: transform 0.15s ease; } }
.jackets .under { display: flex; flex-wrap: wrap; gap: 0 4px; }
.jackets .under .btn { min-height: 32px; padding: 2px 6px; font-size: 13px; }
.volumes { margin: 0 0 18px; }

/* The subtitle line on the picture, as the phone draws it, and study play.
   Size and colour are inline from the Subtitles settings; it sits above the
   native controls, and only the words and the show button take the pointer. */
.screen { position: relative; margin: 0 0 12px; }
.cue { position: absolute; left: 16px; right: 16px; bottom: 56px; display: flex; flex-direction: column; align-items: center; gap: 4px; text-align: center; line-height: 1.5; color: #fff; pointer-events: none; }
.cue .sentence { background: none; padding: 0 0.3em; margin: 0; font-size: inherit; border-radius: 8px; pointer-events: auto; }
.cue.border .sentence { text-shadow: -0.07em -0.07em 0 #000, 0.07em -0.07em 0 #000, -0.07em 0.07em 0 #000, 0.07em 0.07em 0 #000, 0 -0.07em 0 #000, 0 0.07em 0 #000, -0.07em 0 0 #000, 0.07em 0 0 #000; }
.cue mark.reader-mark { color: #1b1b1b; text-shadow: none; background: #ffd54a; border-radius: 3px; box-shadow: 0 0 0 2px #ffd54a; }
.translation-line { margin: 0 0 8px; min-height: 1.5em; color: var(--muted); text-align: center; }
.watch-extras .row { align-items: center; }
.transcript { list-style: none; margin: 8px 0 12px; padding: 0; max-height: 260px; overflow-y: auto; }
.transcript li.on { background: color-mix(in srgb, currentColor 10%, transparent); border-radius: 8px; }
.transcript-line { display: block; width: 100%; text-align: left; padding: 6px 8px; border: 0; background: none; color: inherit; font: inherit; border-radius: 8px; cursor: pointer; }
.transcript-line:hover { background: color-mix(in srgb, currentColor 6%, transparent); }
/* A transcript row: the time seeks, the words beside it are looked up (the phone's Transcript). */
.transcript-row { display: flex; align-items: flex-start; gap: 8px; }
.transcript-row .transcript-time { flex: none; width: auto; min-width: 52px; }
.transcript-words { flex: 1 1 auto; min-width: 0; padding: 6px 0; }
.transcript-words .sentence { margin: 0; }
/* The shelf's film tile: how far it was watched along the foot. */
.vframe .strip { position: absolute; left: 0; right: 0; bottom: 0; height: 4px; background: rgba(0, 0, 0, 0.35); }
.vframe .strip span { display: block; height: 100%; background: var(--red); }
.cue.dim .sentence { background: rgba(0, 0, 0, 0.55); }
.cue .hidden-line { min-width: 12em; font-size: 1rem; background: var(--sunk); border-style: dashed; color: var(--muted); pointer-events: auto; }
.radios > .row { flex-basis: 100%; gap: 8px; }
.subtitle-size { min-width: 2ch; text-align: center; font-variant-numeric: tabular-nums; }
.watch-study { margin-top: 18px; display: flex; flex-direction: column; gap: 14px; }

/* A quiz theme from the Shop: the card's column becomes the wallpaper. */
.study.themed { padding: 28px clamp(16px, 4vw, 36px) 32px; border-radius: 12px; box-shadow: var(--lift); }
.study.themed .choices button, .study.themed .tiles button, .study.themed input { background: var(--card); color: var(--ink); border-color: var(--edge); }

/* Motion: a page arrives, an answer lands. Off under reduced motion. */
@media (prefers-reduced-motion: no-preference) {
  main > * { animation: arrive 0.22s ease-out both; }
  /* The answer controls and the revealed answer fade in once the card settles. */
  .arrive { animation: arrive-soft 180ms cubic-bezier(0.23, 1, 0.32, 1) both; animation-delay: calc(60ms + var(--i, 0) * 30ms); }
  .answer-field input.right, .choices button.right, .kana-field.good { animation: land-right 0.45s ease-out; }
  .answer-field input.wrong, .choices button.wrong, .tiles button.wrong, .kana-field.bad { animation: land-wrong 0.35s ease-out; }
}
@keyframes arrive-soft { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes arrive { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes land-right { 0% { transform: scale(1); } 35% { transform: scale(1.035); } 100% { transform: scale(1); } }
@keyframes land-wrong { 0%, 100% { transform: translateX(0); } 20% { transform: translateX(-5px); } 45% { transform: translateX(4px); } 70% { transform: translateX(-2px); } }

/* Page heads, tiles and rows */
.page.wide { max-width: 1280px; }
.page-head { margin: 0 0 22px; }
.page-head > .btn.quiet { margin: 0 0 6px -8px; }
.page-head.intro { text-align: center; }
.page > .card, .page > section.card { margin: 0 0 18px; }
.card > h2:first-child, .card > h3:first-child { margin-top: 0; }
.tiles-list, ul.tiles-list { list-style: none; padding: 0; margin: 0 0 24px; display: grid; gap: 14px; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
a.tile {
  display: flex; gap: 16px; align-items: center; height: 100%;
  padding: 16px 18px; border: 1px solid var(--edge); border-radius: 12px;
  background: var(--card); color: var(--ink); text-decoration: none;
}
@media (hover: hover) and (pointer: fine) { a.tile:hover { border-color: var(--ink); } }
.tile-glyph { font-size: 44px; line-height: 1; color: var(--red); min-width: 1.2em; text-align: center; }
.tile-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.tile-body strong { font-weight: 500; }
.list a.row-link, .list button.row-link, .list .row-link {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px 14px; width: 100%;
  min-height: 52px; padding: 10px 8px;
  color: inherit; text-decoration: none; text-align: left;
  font: inherit; background: none; border: 0; cursor: pointer;
}
.list .row-link > .text { flex: 1 1 12em; min-width: 0; }
@media (hover: hover) and (pointer: fine) { .list .row-link:hover { background: var(--sunk); } }
.list .row-link[aria-current="true"] { background: var(--sunk); box-shadow: inset 3px 0 0 var(--red); }
.list .row-link.off { cursor: default; color: var(--muted); }
@media (hover: hover) and (pointer: fine) { .list .row-link.off:hover { background: none; } }
.sets .lead, .badges .lead, .credits .lead { font-family: inherit; font-size: 17px; font-weight: 500; min-width: 10em; text-align: left; }
.sets .row-link { flex-wrap: wrap; }
/* A row's name over its line: inline, "Bronze" ran into "Given · its set…". */
.sets .row-link > .text { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }
/* A supporter tier already given: said, not offered at its price again. */
.owned { padding: 4px 12px; border-radius: 8px; background: var(--good-wash); color: var(--good); font-size: 14px; font-weight: 500; }
.owned::before { content: "✓ "; }
.list.plain > li { padding: 10px 6px; }
.tag.ready { border-color: var(--good); color: var(--good); }
.locked { opacity: 0.6; }
.actions { display: flex; flex-wrap: wrap; gap: 12px; justify-content: center; margin: 20px auto 0; max-width: 720px; }
.detail { display: flex; flex-direction: column; align-items: flex-start; gap: 14px; }
.detail > * { max-width: 100%; }
.detail > .card, .detail > .sentence-card, .detail > ul, .detail > ol, .detail > dl, .detail > .list, .detail > .notice { align-self: stretch; }
.detail > .prompt-word { font-size: 48px; line-height: 1.3; }
.detail > h2.prompt-text { margin: 0; }
.detail .intro { display: flex; gap: 22px; align-items: center; flex-wrap: wrap; }
.lesson { max-width: 720px; margin: 0 auto; display: flex; flex-direction: column; gap: 16px; }
.lesson .intro { text-align: center; }
.lesson .label, h2.label, .label { color: var(--muted); font-size: 14px; font-weight: 500; letter-spacing: 0.02em; margin: 0 0 8px; }

/* Heat: untouched, learning, then the known steps. */
.glyph-grid { list-style: none; padding: 0; margin: 0; display: grid; gap: 6px; grid-template-columns: repeat(auto-fill, minmax(56px, 1fr)); }
.glyph-tile {
  display: flex; align-items: center; justify-content: center; width: 100%;
  aspect-ratio: 1; border-radius: 8px; border: 1px solid var(--edge);
  background: var(--card); color: var(--ink); cursor: pointer;
  font: inherit; font-family: var(--jp); font-size: 26px;
}
.tile-face { display: flex; flex-direction: column; align-items: center; line-height: 1.1; }
.tile-romaji { font-family: var(--sans, inherit); font-size: 11px; opacity: 0.7; }
@media (hover: hover) and (pointer: fine) { .glyph-tile:hover { border-color: var(--ink); } }
.glyph-tile[aria-current="true"], .glyph-tile[aria-pressed="true"] { outline: 2px solid var(--red); outline-offset: 1px; }
.heat-learning { background: var(--sunk); }
.heat-1 { background: color-mix(in srgb, var(--good-wash) 45%, var(--card)); }
.heat-2 { background: color-mix(in srgb, var(--good-wash) 70%, var(--card)); }
.heat-3, .heat-4, .heat-5 { background: var(--good-wash); }
.heat-6, .heat-7, .heat-8 { background: var(--good-wash); border-color: var(--good); }
/* The four known steps of the browser's tiles and its key, each its own colour (red to green,
   as the phone's ramp), and the step again as a width under the glyph: a red-green dichromat
   loses the two coldest, and width is a channel nobody loses. */
.glyph-tile, .heat-swatch { position: relative; }
.glyph-tile.heat-1, .heat-swatch.heat-1 { background: var(--bad-wash); }
.glyph-tile.heat-2, .heat-swatch.heat-2 { background: color-mix(in srgb, var(--bad-wash) 40%, var(--good-wash)); }
.glyph-tile.heat-3, .heat-swatch.heat-3 { background: color-mix(in srgb, var(--good-wash) 65%, var(--card)); }
.glyph-tile.heat-4, .heat-swatch.heat-4 { background: var(--good-wash); border-color: var(--good); }
.glyph-tile[class*=" heat-1"]::after, .glyph-tile[class*=" heat-2"]::after, .glyph-tile[class*=" heat-3"]::after, .glyph-tile[class*=" heat-4"]::after {
  content: ""; position: absolute; bottom: 5px; left: 50%; height: 3px; border-radius: 2px; background: currentColor; transform: translateX(-50%);
}
.glyph-tile.heat-1::after { width: 17.5%; }
.glyph-tile.heat-2::after { width: 35%; }
.glyph-tile.heat-3::after { width: 52.5%; }
.glyph-tile.heat-4::after { width: 70%; }
.heat-legend { display: flex; flex-wrap: wrap; gap: 6px 12px; align-items: center; margin: 8px 0 12px; font-size: 13px; color: var(--muted); }
.heat-swatch-row { display: inline-flex; align-items: center; gap: 6px; }
.heat-swatch { display: inline-block; width: 18px; height: 14px; border-radius: 4px; border: 1px solid var(--edge); background: var(--card); }
.heat-swatch.heat-learning { background: var(--sunk); }
.heat-ramp { display: inline-flex; }
.heat-ramp .heat-swatch { border-radius: 0; width: 20px; }
.heat-ramp .heat-swatch:first-child { border-radius: 4px 0 0 4px; }
.heat-ramp .heat-swatch:last-child { border-radius: 0 4px 4px 0; }
.heat-key { margin-top: 24px; }
.heat-key ul { padding-left: 18px; margin: 0 0 8px; }
.dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; border: 1px solid var(--edge); flex: none; }
.dot.on { background: var(--red); border-color: var(--red); }

/* Pitch and grammar structure */
.pitch { display: inline-flex; gap: 1px; font-family: var(--jp); font-size: 20px; }
.pitch .mora { padding: 2px 1px 0; border-top: 2px solid transparent; }
.pitch .mora.high { border-top-color: var(--red); }
.pitch .pitch-name { font-family: inherit; font-size: 13px; align-self: flex-end; margin-left: 8px; white-space: nowrap; }
.pitch .mora.falls { border-right: 2px solid var(--red); }
.structure { padding: 12px 14px; border-radius: 12px; background: var(--sunk); display: flex; flex-direction: column; gap: 6px; }
.structure-line { font-family: var(--jp); font-size: 20px; display: flex; flex-wrap: wrap; gap: 4px; align-items: baseline; }
[class^="tok-"] { padding: 0 3px; border-radius: 4px; }
.tok-fixed { color: var(--red); font-weight: 500; }
.tok-alternative { color: var(--red); border-bottom: 1px dotted var(--red); }
.tok-slot { color: var(--muted); font-family: inherit; font-size: 15px; border: 1px dashed var(--edge); }
.tok-gap { color: var(--muted); }

/* Yokubi prose, parsed (ADR-444): the phone's headings, examples, asides and tables */
.yokubi { white-space: pre-line; display: flex; flex-direction: column; gap: 10px; }
.yokubi p, .yokubi ul { margin: 0; }
.yokubi-heading { margin: 4px 0 0; font-size: 17px; }
.yokubi-pre { font-family: var(--jp); font-size: 17px; white-space: pre-wrap; padding: 10px 14px; border-radius: 12px; background: var(--sunk); }
.yokubi-callout { padding: 10px 14px; border-radius: 12px; background: var(--sunk); display: flex; flex-direction: column; gap: 8px; }
.yokubi-table { border-collapse: collapse; background: var(--sunk); border-radius: 8px; overflow: hidden; width: 100%; }
.yokubi-table th, .yokubi-table td { padding: 6px 10px; text-align: left; white-space: normal; }

/* Kana */
.kana-learn { max-width: 720px; margin: 0 auto; display: flex; flex-direction: column; align-items: center; gap: 12px; text-align: center; }
.kana-card { padding: 12px 14px; border: 1px solid var(--edge); border-radius: 12px; background: var(--card); }

/* Word and sentence cards in a lesson */
.word-card, .sentence-card { padding: 16px 18px; border: 1px solid var(--edge); border-radius: 12px; background: var(--card); text-align: left; }
.word-card .prompt-word { font-size: 40px; }
.sentence-card { background: var(--sunk); border-color: var(--rule); }
.sentence-card [lang="ja"] { font-size: 22px; line-height: 2; }
.tap { cursor: pointer; border-radius: 3px; }
.tap.gform, mark.gform { color: var(--red); font-weight: 600; background: none; }
.tap:focus-visible { background: color-mix(in srgb, var(--red) 12%, transparent); }
@media (hover: hover) and (pointer: fine) { .tap:hover { background: color-mix(in srgb, var(--red) 12%, transparent); } }

/* Receipt */
.split { display: flex; height: 8px; border-radius: 4px; overflow: hidden; background: var(--sunk); margin: 0 0 16px; }
.split .hit { background: var(--good); }
.split .miss { background: var(--bad); }
.receipt-rows .row-link, .receipt-rows > li { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; padding: 10px 6px; }
.receipt-rows .mark { font-weight: 700; width: 1.2em; text-align: center; }
.receipt-rows .asked { flex: 1 1 100%; padding-left: 2.4em; }
.receipt-rows .asked mark.hit { background: var(--good-wash); color: var(--good); }
.receipt-rows .asked mark.miss { background: var(--bad-wash); color: var(--bad); }
.receipt .chips { margin: 0 0 16px; }
.study-bar .title h1 { font-size: 20px; margin: 0; font-weight: 500; }
.study .prompt { display: flex; flex-direction: column; align-items: center; gap: 8px; }
ol.choices { list-style: none; margin: 0; padding: 0; }
ol.choices > li { display: flex; }
ol.choices > li > button { flex: 1; }
.choices button.wrong { background: var(--bad-wash); border-color: var(--bad); }
.kana-field { width: 100%; max-width: 420px; min-width: 0; font-size: 22px !important; text-align: center; font-family: var(--jp); }
.kana-field.good { border-color: var(--good); background: var(--good-wash); color: var(--good); }
.kana-field.bad { border-color: var(--bad); background: var(--bad-wash); color: var(--bad); }

/* Dictionary */
.search-row { display: flex; gap: 10px; align-items: center; margin: 0 0 16px; }
.search-row input[type="search"] { flex: 1; min-width: 0; font-size: 20px; }
.search-row .btn[aria-pressed="true"] { background: var(--ink); color: var(--paper); border-color: var(--ink); }
#dict-tools:not(:empty) { margin: 0 0 16px; }
.pane-list > .notice, .pane-list > p, .pane-list > h2, .pane-list > .card { margin: 12px 14px; }
.hits .row-link .lead { font-size: 22px; min-width: 0; }
.hits .row-link { flex-wrap: wrap; }
.hits .row-link .text { flex: 1 1 100%; color: var(--muted); font-size: 15px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.entry { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }
.entry .prompt-word { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 12px; font-family: var(--jp); font-size: 44px; line-height: 1.3; margin: 0; font-weight: 500; }
.entry > .senses, .entry > .chips, .entry > .card { align-self: stretch; }
.entry .prompt-word .reading { font-size: 22px; font-weight: 400; color: var(--muted); }
.entry .prompt-word:focus { outline: none; }
ol.senses { margin: 0; padding-left: 1.4em; display: flex; flex-direction: column; gap: 8px; }
ol.senses .chips { gap: 4px; margin-top: 4px; }
.handwriting { display: flex; flex-direction: column; gap: 10px; align-items: flex-start; }
.candidates .glyph-tile { width: 52px; }
.parts .part-grid { display: flex; flex-direction: column; max-height: 320px; overflow-y: auto; padding: 4px; }
.part-row { display: flex; gap: 12px; align-items: flex-start; padding: 6px 0; border-top: 1px solid var(--rule); }
.part-row:first-child { border-top: none; padding-top: 0; }
.part-set { display: flex; flex-wrap: wrap; gap: 4px; min-width: 0; }
.part-grid .part { font-family: var(--jp); font-size: 20px; min-width: 40px; min-height: 40px; border-radius: 8px; border: 1px solid var(--edge); background: var(--card); color: var(--ink); cursor: pointer; }
.part-grid .part.on { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.part-grid .part.dim { opacity: 0.3; cursor: default; }
/* A label, not a control: no box, the muted ink, and level with the first row of parts. */
.part-grid .part-count { flex: none; width: 4.5rem; min-height: 40px; display: inline-flex; align-items: center; color: var(--muted); font-size: 13px; }
.parts .candidates { margin: 0 0 10px; }
.side-bar { display: flex; align-items: center; gap: 8px; margin: 0 0 14px; padding-right: 44px; }

/* Settings */
.settings { display: flex; flex-direction: column; gap: 14px; max-width: 760px; }
.radios { border: 0; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.radios legend { font-weight: 500; margin: 0 0 8px; width: 100%; }
.radio { display: inline-flex; align-items: center; gap: 8px; min-height: 40px; padding: 6px 14px; border: 1px solid var(--edge); border-radius: 12px; background: var(--card); cursor: pointer; }
.radio input { accent-color: var(--red); margin: 0; }
.radio:has(input:checked) { border-color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); }
.radio:has(input:focus-visible) { outline: 2px solid var(--red); outline-offset: 2px; }
.radios.paces { flex-direction: column; }
.radio.pace { border-radius: 12px; padding: 10px 14px; }
.radio.pace > span { display: flex; flex-direction: column; gap: 2px; }
/* Settings previews: each choice shows itself, as the phone's Settings does. */
.radio .swatch { width: 14px; height: 14px; border-radius: 50%; flex: none; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ink) 18%, transparent); }
.radios.themes .radio { flex-direction: column; align-items: stretch; gap: 6px; border-radius: 12px; padding: 8px; flex: 1 1 0; min-width: 0; max-width: 200px; }
.radios.themes .radio input { position: absolute; opacity: 0; pointer-events: none; }
.radios.themes .radio .name { text-align: center; }
.radios.themes .radio:has(input:checked) { border-color: var(--red); box-shadow: inset 0 0 0 1px var(--red); }
.theme-thumb { display: flex; flex-direction: column; gap: 6px; height: 64px; padding: 8px; border-radius: 8px; overflow: hidden; }
.theme-thumb.light, .theme-thumb .half.light { background: #F8F3E9; }
.theme-thumb.dark, .theme-thumb .half.dark { background: #0E1526; }
.theme-thumb.light { box-shadow: inset 0 0 0 1px #E4D9C6; }
.theme-thumb .tile { display: block; height: 22px; border-radius: 8px; }
.theme-thumb.light .tile, .theme-thumb .half.light .tile { background: #FFFFFF; }
.theme-thumb.dark .tile, .theme-thumb .half.dark .tile { background: #16203A; }
.theme-thumb .bar { display: block; width: 42%; height: 10px; border-radius: 8px; }
.theme-thumb.light .bar { background: #1E3566; }
.theme-thumb.dark .bar { background: #9EB0DC; }
.theme-thumb.system { flex-direction: row; gap: 0; padding: 0; box-shadow: inset 0 0 0 1px #E4D9C6; }
.theme-thumb .half { flex: 1; padding: 8px 0 8px 8px; }
.theme-thumb .half.dark { padding: 8px 8px 8px 0; }
.theme-thumb .half.light .tile { border-radius: 5px 0 0 5px; }
.theme-thumb .half.dark .tile { border-radius: 0 5px 5px 0; }
.radios.places .radio { flex: 0 1 132px; max-width: 132px; }
.place-thumb { display: block; aspect-ratio: 16 / 9; border-radius: 8px; background: var(--paper) var(--t) center / cover no-repeat; box-shadow: inset 0 0 0 1px var(--edge); }
:root[data-theme="dark"] .place-thumb { background-image: var(--tn); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .place-thumb { background-image: var(--tn); } }
.radios.faces .radio[data-face="manrope"] .name { font-family: "Mojiya UI Manrope", sans-serif; }
.radios.faces .radio[data-face="jakarta"] .name { font-family: "Mojiya UI Jakarta", sans-serif; }
.radios.faces .radio[data-face="hanken"] .name { font-family: "Mojiya UI Hanken", sans-serif; }
.radios.faces .radio[data-face="inter"] .name { font-family: "Mojiya UI Inter", sans-serif; }
.radios.faces .radio[data-face="system"] .name { font-family: system-ui, sans-serif; }
.settings-preview { margin: 4px 0 6px; }
.settings-preview.verdicts { display: flex; flex-direction: column; gap: 4px; }
.verdict-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 6px; }
/* The preview's own class: `.verdict` is the quiz's answer box, and the
   preview's 42px height on it overlapped every answer screen (ADR-403). */
.verdict-sample { display: flex; align-items: center; justify-content: center; height: 42px; border-radius: 12px; font-weight: 500; }
.settings-preview.furigana { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; align-items: end; text-align: center; }
.settings-preview.furigana .sample { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.settings-preview.furigana .word { font-family: var(--jp); font-size: 28px; line-height: 1.6; }
.settings-preview.furigana .word rt { font-size: 0.5em; }
.settings-preview.furigana .word.large rt { font-size: 0.68em; }
.marker-sample { font-family: var(--jp); font-size: 18px; margin: 0; }
/* The wash's 2px ring spills past the word, so the sample leaves it room. */
.marker-sample .reader-mark { padding: 0; margin: 0 4px; }
.tint-sample { font-family: var(--jp); font-size: 32px; line-height: 1.7; }
/* Home transparency over the chosen place: the tiles take Home's own fills
   (the papered rules above), solid and see-through side by side. */
.settings-preview.see-through, .settings-preview.anki-styles { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; align-items: start; text-align: center; }
.settings-preview.see-through .sample, .settings-preview.anki-styles .sample { display: flex; flex-direction: column; align-items: center; gap: 4px; min-width: 0; }
.see-through .scene { width: 100%; height: 110px; border-radius: 12px; display: flex; align-items: center; justify-content: center; background: var(--paper) var(--t) center 75% / cover no-repeat; box-shadow: inset 0 0 0 1px var(--edge); }
.see-through .scene.chosen, .anki-styles .anki-card.chosen { outline: 2px solid var(--red); outline-offset: -2px; }
:root[data-theme="dark"] .see-through .scene { background-image: var(--tn); }
.see-through .tile { margin: 0 14px; flex: 1; padding: 12px 0; border-radius: 12px; font-weight: 500; background: var(--paper); }
.see-through .tile.through { background: color-mix(in srgb, var(--paper) 78%, transparent); }
:root[data-theme="dark"] .see-through .tile { background: #2A3554; }
:root[data-theme="dark"] .see-through .tile.through { background: rgba(42, 53, 84, 0.72); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .see-through .scene { background-image: var(--tn); }
  :root:not([data-theme="light"]) .see-through .tile { background: #2A3554; }
  :root:not([data-theme="light"]) .see-through .tile.through { background: rgba(42, 53, 84, 0.72); }
}
/* Rich and Simple: the card's back on Anki's white day face, in the note
   type's own inks (AnkiNoteType.CSS), whatever the app's theme. */
.anki-card { width: 100%; box-sizing: border-box; background: #fff; color: #1f1c18; border-radius: 12px; padding: 6px; font-size: 12px; }
/* The card's one panel (AnkiNoteType.CSS .mj-panel, ADR-489): paper, a soft edge. */
.anki-panel { box-sizing: border-box; background: #faf8f4; border: 1px solid rgba(0, 0, 0, 0.12); border-radius: 8px; padding: 10px 8px; display: flex; flex-direction: column; align-items: center; gap: 4px; }
.anki-card hr { width: 100%; border: 0; border-top: 1px solid rgba(0, 0, 0, 0.15); margin: 2px 0; }
.anki-word { font-family: var(--jp); font-size: 22px; line-height: 1.6; }
.anki-word rt { font-size: 0.5em; }
.anki-line { font-family: var(--jp); font-size: 12px; }
.anki-line b { color: #2e9d4e; }
.anki-reading { font-family: var(--jp); font-size: 13px; }
.anki-mined { width: 100%; box-sizing: border-box; background: rgba(127, 127, 127, 0.1); border-radius: 8px; padding: 6px; display: flex; flex-direction: column; align-items: center; gap: 2px; }
.anki-en { font-size: 10px; opacity: 0.75; }
.anki-gloss { width: 100%; text-align: left; font-size: 11px; display: flex; flex-direction: column; gap: 3px; }
.anki-chip { display: inline-block; font-size: 9px; font-weight: bold; color: #fff; background: #5a5a5a; border-radius: 3px; padding: 0 3px; margin-right: 3px; }
.anki-example { margin-left: 10px; background: rgba(127, 127, 127, 0.1); padding: 2px 5px; font-family: var(--jp); font-size: 10px; }
.anki-play { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border-radius: 50%; background: rgba(17, 17, 17, 0.12); font-size: 8px; }
.toggle { display: flex; gap: 14px; align-items: flex-start; }
.toggle .switch { margin-top: 3px; flex: none; }
.toggle label { display: flex; flex-direction: column; gap: 2px; cursor: pointer; }
.toggle label strong { font-weight: 500; }
/* A ticked Anki note type's own questions, under its box (ADR-272). */
.anki-type { margin-left: 2.4em; display: flex; flex-direction: column; gap: 8px; }
.specimens > li { display: flex; align-items: center; gap: 16px; padding: 8px 6px; }
.specimen { font-size: 32px; min-width: 2.4em; }

/* Profile, stats and the shop */
.badges { list-style: none; padding: 0; margin: 0; display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); }
.badge { display: flex; flex-direction: column; gap: 6px; padding: 14px 16px; border: 1px solid var(--edge); border-radius: 12px; background: var(--card); }
.badge.earned { border-color: var(--good); }
.badge strong { font-weight: 500; }
.chart { display: flex; align-items: flex-end; gap: 3px; height: 96px; margin: 8px 0 4px; }
.chart .col { flex: 1 1 0; min-width: 0; background: var(--red); border-radius: 2px 2px 0 0; }
.chart .col.none { background: var(--sunk); }
table.rates { width: 100%; border-collapse: collapse; margin: 0 0 10px; }
table.rates th, table.rates td { padding: 6px 4px; border-top: 1px solid var(--rule); text-align: left; font-weight: 400; }
table.rates td:nth-child(2) { text-align: right; width: 4em; }
table.rates td:nth-child(3) { text-align: right; width: 11em; }
.credits > li { padding: 12px 6px; }
.credits > li p { margin: 2px 0; }
.credits > li p.notice { white-space: pre-line; overflow-wrap: anywhere; }
/* A credit's licence and source are inline links in one line, not the list's full-width row links. */
.list.credits a { display: inline; width: auto; min-height: 0; padding: 0; color: var(--link); text-decoration: underline; }
.intro .glyph-hero { color: var(--red); }
/* The announcer sits at the end of the page; pinned to the top its 1px no longer adds a scroll to a page that fits. */
.visually-hidden[role="status"] { top: 0; left: 0; }
.freq { display: flex; flex-wrap: wrap; gap: 4px 12px; color: var(--link); font-size: 13px; font-weight: 500; margin: 2px 0 6px; }
a.glyph-hero { display: inline-block; text-decoration: none; }
@media (hover: hover) and (pointer: fine) { a.glyph-hero:hover { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 8px; } }

@media (max-width: 800px) {
  /* One column: the bar takes its own height and main the rest, rather than
     the two sharing 100vh and the bar stretching on a short page (ADR-403). */
  .shell { grid-template-columns: 1fr; grid-template-rows: auto 1fr; }
  .rail {
    position: sticky; top: 0; z-index: 5; height: auto;
    flex-direction: row; align-items: center; flex-wrap: nowrap; gap: 4px 8px;
    padding: 8px 12px; border-right: 0; border-bottom: 1px solid var(--rule);
    background: var(--paper);
  }
  .brand { padding: 4px 6px; flex: none; }
  /* The phone's tab bar: every section along the bottom, the brand and the
     theme along the top. */
  .rail nav {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 6;
    background: color-mix(in srgb, var(--paper) 94%, transparent);
    backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
    border-top: 1px solid var(--rule);
    padding: 4px calc(4px + env(safe-area-inset-right)) calc(4px + env(safe-area-inset-bottom)) calc(4px + env(safe-area-inset-left));
  }
  .rail nav ul { display: grid; grid-template-columns: repeat(8, minmax(0, 1fr)); gap: 0; }
  /* The bar keeps the phone's eight; Account and the paywall lead to these. */
  .rail nav li.extra { display: none; }
  .rail nav a[data-holds] { background: color-mix(in srgb, var(--red) 10%, var(--card)); color: var(--ink); font-weight: 600; }
  .rail nav a[data-holds] .icon { color: var(--red); }
  .rail nav a {
    flex-direction: column; justify-content: center; align-items: center; gap: 2px;
    min-height: 54px; padding: 6px 2px; border-radius: 12px;
    font-size: 11px; position: relative; white-space: nowrap;
  }
  .rail nav a[aria-current="page"] { box-shadow: none; }
  .rail nav a .label { flex: none; max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
  .rail nav a .count { position: absolute; top: 2px; right: 50%; transform: translateX(22px); min-width: 18px; line-height: 16px; font-size: 10px; padding: 0 4px; }
  .rail { justify-content: space-between; }
  /* A filter on the bar would make it the fixed tab bar's containing block. */
  :root[data-papered] .rail { backdrop-filter: none; -webkit-backdrop-filter: none; background: var(--paper); }
  main { padding-bottom: 96px !important; }
  .rail .foot {
    display: flex; flex-direction: row; flex: none;
    margin: 0; padding: 0 0 0 4px; gap: 0;
  }
  .rail .foot a, .rail .foot .links { display: none; }
  /* The tab bar's Account holds it on a narrow window; the top bar has no room. */
  .rail .foot .who { display: none; }
  #study-theme { font-size: 0; min-width: 44px; min-height: 44px; padding-inline: 10px; }
  #study-theme::after { content: "Theme"; font-size: 14px; font-weight: 500; }
  main { padding: 20px 16px 48px; }
  .panes { grid-template-columns: 1fr; }
  .panes > .pane-list { max-height: 50vh; }
  .panes > .pane-detail { position: static; }
  .choices { grid-template-columns: 1fr; }
  .receipt .figures { grid-template-columns: 1fr 1fr; }
  .bar-row { grid-template-columns: minmax(4.5em, 80px) minmax(0, 1fr) minmax(4em, 90px); }
  .list .lead, .sets .lead { min-width: 0; }
  .home-actions, .tiles-list, ul.tiles-list { grid-template-columns: 1fr; }
  .study-bar { gap: 8px; }
}
@media (max-width: 400px) {
  .grades { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 520px) {
  .rail nav a .label { position: absolute !important; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .rail nav a { min-height: 50px; }
}
.book { font-size: 1.35rem; line-height: 1.9; }
.book .para { margin: 0 0 1.1em; }
.film { display: block; width: 100%; max-height: 70vh; background: #111; border-radius: 12px; }
/* A touch screen: a sideways swipe replays a line, so the film takes sideways drags and leaves vertical ones to scroll the page (P62). */
@media (pointer: coarse) { .film { touch-action: pan-y; } }
.plate { width: min(100%, 280px); height: auto; border-radius: 8px; }
.live-frame { display: block; width: 100%; aspect-ratio: 16 / 9; min-height: 200px; height: auto; background: #111; border: 0; border-radius: 12px; }
.frame { display: block; width: 100%; height: 70vh; min-height: 240px; border: 1px solid var(--rule); border-radius: 12px; background: var(--card); }
/* A relayed page (ADR-388) is drawn as the site would be: its own colours
   on white, tall enough to read in, under the toolbar. */
.web-page { height: calc(100dvh - 240px); min-height: 360px; background: #fff; color-scheme: light; }
.web-hint { align-items: center; gap: 8px; }
.web-hint p { margin: 0; }
.address { width: min(100%, 40rem); min-height: 44px; font: inherit; padding: 8px 12px; border: 1px solid var(--edge); border-radius: 8px; background: var(--card); color: var(--ink); }
.still { width: 160px; height: 90px; object-fit: cover; border-radius: 8px; background: var(--sunk); flex: none; }
/* 藍, the phone's default dye (App.kt LIGHT/DARK). The site's brand red stays
   on the marketing pages; here every accent, Indigo included, is a dye. */
:root[data-accent="ai"] { --red: #1E3566; --link: #1E3566; }
:root[data-accent="asagi"] { --red: #1E4A52; --link: #1E4A52; }
:root[data-accent="murasaki"] { --red: #4A2C54; --link: #4A2C54; }
:root[data-accent="suo"] { --red: #5C2436; --link: #5C2436; }
:root[data-accent="matsuba"] { --red: #2F4A38; --link: #2F4A38; }
:root[data-accent="uguisu"] { --red: #4A5820; --link: #4A5820; }
:root[data-accent="sakura"] { --red: #7E3642; --link: #7E3642; }
:root[data-theme="dark"][data-accent="asagi"] { --red: #6BB8B0; --link: #6BB8B0; --on-red: #0E1526; }
:root[data-theme="dark"][data-accent="murasaki"] { --red: #C4A0D4; --link: #C4A0D4; --on-red: #0E1526; }
:root[data-theme="dark"][data-accent="suo"] { --red: #E498A4; --link: #E498A4; --on-red: #0E1526; }
:root[data-theme="dark"][data-accent="matsuba"] { --red: #8FBC8F; --link: #8FBC8F; --on-red: #0E1526; }
:root[data-theme="dark"][data-accent="uguisu"] { --red: #B8C86A; --link: #B8C86A; --on-red: #0E1526; }
:root[data-theme="dark"][data-accent="sakura"] { --red: #F0B8C0; --link: #F0B8C0; --on-red: #0E1526; }
:root[data-theme="dark"][data-accent="ai"] { --red: #9EB0DC; --link: #9EB0DC; --on-red: #0E1526; }
/* The same night dyes when the theme follows a dark system; these once applied
   only to an explicit dark pick, so a dark system showed the cream-ground dye. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"])[data-accent="ai"] { --red: #9EB0DC; --link: #9EB0DC; --on-red: #0E1526; }
  :root:not([data-theme="light"])[data-accent="asagi"] { --red: #6BB8B0; --link: #6BB8B0; --on-red: #0E1526; }
  :root:not([data-theme="light"])[data-accent="murasaki"] { --red: #C4A0D4; --link: #C4A0D4; --on-red: #0E1526; }
  :root:not([data-theme="light"])[data-accent="suo"] { --red: #E498A4; --link: #E498A4; --on-red: #0E1526; }
  :root:not([data-theme="light"])[data-accent="matsuba"] { --red: #8FBC8F; --link: #8FBC8F; --on-red: #0E1526; }
  :root:not([data-theme="light"])[data-accent="uguisu"] { --red: #B8C86A; --link: #B8C86A; --on-red: #0E1526; }
  :root:not([data-theme="light"])[data-accent="sakura"] { --red: #F0B8C0; --link: #F0B8C0; --on-red: #0E1526; }
}

/* Reduced motion: the system's ask, or the user's own Reduce animations (ADR-455),
   which wins either way. `off` re-enables the no-preference rules above under a
   system that asks for less; keep the "off twin" lines in step with them. */
@media (prefers-reduced-motion: reduce) {
  :root:not([data-reduce-motion="off"]) * { transition: none !important; animation: none !important; }
}
:root[data-reduce-motion="on"] * { transition: none !important; animation: none !important; }
:root[data-reduce-motion="on"] .replay { display: none; }
/* off twin */
:root[data-reduce-motion="off"] p.boot::before { animation: breathe 1.6s ease-in-out infinite; }
:root[data-reduce-motion="off"] .strokes.play path.ink { stroke-dasharray: 1; stroke-dashoffset: 1; animation: write 0.55s ease-in-out forwards; animation-delay: calc(var(--i) * 0.62s + 0.2s); }
:root[data-reduce-motion="off"] .strokes.play text.num { opacity: 0; animation: arrive-num 0.2s ease-out forwards; animation-delay: calc(var(--i) * 0.62s + 0.2s); }
:root[data-reduce-motion="off"] .jacket { transition: transform 0.15s ease; }
:root[data-reduce-motion="off"] main > * { animation: arrive 0.22s ease-out both; }
:root[data-reduce-motion="off"] .arrive { animation: arrive-soft 180ms cubic-bezier(0.23, 1, 0.32, 1) both; animation-delay: calc(60ms + var(--i, 0) * 30ms); }
:root[data-reduce-motion="off"] .answer-field input.right, :root[data-reduce-motion="off"] .choices button.right, :root[data-reduce-motion="off"] .kana-field.good { animation: land-right 0.45s ease-out; }
:root[data-reduce-motion="off"] .answer-field input.wrong, :root[data-reduce-motion="off"] .choices button.wrong, :root[data-reduce-motion="off"] .tiles button.wrong, :root[data-reduce-motion="off"] .kana-field.bad { animation: land-wrong 0.35s ease-out; }

/* Art: coin, medals, cosmetics (ported from the phone) */
/* A mon figure: the coin at 0.95 of the text beside it, as MonAmount sizes it. */
.mon-amount { display: inline-flex; align-items: center; gap: 0.3em; white-space: nowrap; vertical-align: middle; }
.mon-amount > .coin { width: 0.95em; height: 0.95em; flex: none; }
.mon-amount.big { font-size: 22px; font-weight: 600; }
.figure .value .mon-amount { vertical-align: baseline; }
/* Achievements: a section per category, medals in a grid that never runs wider than its card. */
.medal-set .spread h3 { margin: 0; }
.medals { list-style: none; margin: 12px 0 0; padding: 0; display: grid; gap: 16px 12px; grid-template-columns: repeat(auto-fill, minmax(min(120px, 100%), 1fr)); }
.medal-cell { display: flex; flex-direction: column; align-items: center; gap: 4px; text-align: center; min-width: 0; }
.medal-hit { all: unset; box-sizing: border-box; display: flex; flex-direction: column; align-items: center; gap: 4px; cursor: pointer; width: 100%; }
.medal-hit:focus-visible { outline: 2px solid var(--red); outline-offset: 2px; border-radius: 8px; }
.badge-dialog { max-width: min(92vw, 360px); text-align: center; border: 1px solid var(--edge); border-radius: 12px; background: var(--card); color: var(--ink); }
.badge-dialog::backdrop { background: rgba(0, 0, 0, 0.4); }
/* The medal is a block, which text-align cannot centre, and .medal's 84px would win over the 128 the dialog draws it at. */
.badge-dialog .medal { width: 128px; height: 128px; margin: 8px auto; }
.badge-dialog .row { justify-content: center; }
.medal-cell strong { font-weight: 500; font-size: 15px; line-height: 1.3; overflow-wrap: anywhere; }
.medal-cell .small { overflow-wrap: anywhere; }
.medal { display: block; width: 84px; height: 84px; flex: none; }
/* The ghost: BadgeMedallion's colour matrix — grey, then 0.5 x + 0.36 per channel, at 80% — as CSS filters. */
.medal.ghost, .ghosted { filter: grayscale(1) contrast(0.41) brightness(1.22) opacity(0.8); }
/* A supporter tier's card (ADR-472): its coin and status, one action, and the four rewards. */
.tier { display: flex; flex-direction: column; gap: 12px; }
/* The rewards row is drawn by the Shop's card and the Support page's rows alike, so it is not scoped to .tier. */
.rewards { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
.reward { display: flex; flex-direction: column; align-items: center; gap: 4px; text-align: center; background: none; border: 0; padding: 4px 0; font: inherit; color: inherit; cursor: pointer; border-radius: 8px; width: 100%; }
.rewards.plain .reward { cursor: default; }
.reward .small { overflow-wrap: anywhere; }
.sets .row-link > .rewards { flex-basis: 100%; }
.tier .head { display: flex; align-items: center; gap: 14px; }
.tier .head .text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
/* Shop tiles: the swatch, then the name and price, then the action. */
.swatch { display: inline-block; flex: none; line-height: 0; border-radius: 8px; overflow: hidden; }
.swatch svg { display: block; }
.shop .row-link .sub .mon-amount { font-size: 14px; }

/* Lookup: the phone's sheet, as a panel */
/* The entry (Entry.kt): word, actions, source line, first sense, then closed sections. */
.entry { max-width: 100%; min-width: 0; overflow-wrap: anywhere; }
.entry > .acts, .entry > .source-line, .entry > .sense-block, .entry > p.gloss, .entry > details.more { align-self: stretch; }
.entry > p.gloss, .entry .sense-body > p.gloss { margin: 0; font-size: 18px; }
.entry .derivation { color: var(--link); font-size: 15px; }
.entry-card { padding: 20px 22px; }
.side .entry .prompt-word { font-size: 34px; }
/* The action row: icon and words on every button, so nothing is named only for a screen reader. */
.acts { display: flex; flex-wrap: wrap; gap: 6px; }
.act {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%;
  min-height: 40px; padding: 6px 12px;
  font: inherit; font-size: 14px; font-weight: 500; text-align: left; text-decoration: none;
  color: var(--ink); background: var(--card);
  border: 1px solid color-mix(in srgb, var(--edge) 60%, transparent); border-radius: 12px;
  cursor: pointer; transition: background-color 0.15s, border-color 0.15s, color 0.15s;
}
@media (hover: hover) and (pointer: fine) { .act:hover { border-color: var(--ink); } }
.act[aria-pressed="true"] { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.act.on:not([aria-pressed]) { color: var(--good); border-color: var(--good); }
.act[aria-disabled="true"] { cursor: default; }
@media (hover: hover) and (pointer: fine) { .act[aria-disabled="true"]:hover { border-color: var(--good); } }
.act .glyph { width: 18px; height: 18px; flex: none; }
.act .glyph text { font-family: var(--jp); }
/* The source and its frequency on one line. */
.source-line { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 10px; }
.source-line .freq { margin: 0; }
.source-name { color: var(--muted); font-size: 12px; font-weight: 600; letter-spacing: 0.04em; }
/* One sense: its number, then the gloss with its part of speech, pills and notes. */
.sense-block { display: flex; gap: 8px; }
.sense-block > .n { color: var(--muted); font-size: 18px; flex: none; }
.sense-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.sense-block + .sense-block { margin-top: 10px; }
/* The sense the tap's particle proved (ADR-423), washed in the lookup marker as a mark in the reader is. */
.sense-block.here { background: color-mix(in srgb, var(--mark-ink, var(--red)) var(--mark-a, 18%), transparent); border-left: 3px solid var(--mark-ink, var(--red)); padding: 6px 8px 6px 11px; border-radius: 3px; }
.sense-block.here .here-label { align-self: flex-end; }
.pills { display: flex; flex-wrap: wrap; gap: 4px 6px; }
.pill { font-size: 12px; padding: 1px 10px; border-radius: 999px; background: var(--sunk); color: var(--muted); }
.note { font-style: italic; }
/* A definition with Japanese in it: a click on a character offers that word. */
.gloss-tap { cursor: pointer; border-radius: 3px; }
@media (hover: hover) and (pointer: fine) { .gloss-tap:hover { text-decoration: underline dotted var(--edge); text-underline-offset: 4px; } }
ruby.gloss-tap:focus-visible { background: color-mix(in srgb, var(--red) 12%, transparent); text-decoration: none; }
@media (hover: hover) and (pointer: fine) { ruby.gloss-tap:hover { background: color-mix(in srgb, var(--red) 12%, transparent); text-decoration: none; } }
/* The closed sections: a disclosure each, the sheet's "Show …" rows. */
details.more { border-top: 1px solid var(--rule); }
details.more > summary {
  display: flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 2px;
  color: var(--link); font-weight: 500; cursor: pointer; list-style: none;
}
details.more > summary::-webkit-details-marker { display: none; }
details.more > summary::before {
  content: ""; flex: none; width: 7px; height: 7px;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: rotate(-45deg); transition: transform 0.15s;
}
details.more[open] > summary::before { transform: rotate(45deg); }
@media (hover: hover) and (pointer: fine) { details.more > summary:hover { text-decoration: underline; } }
.more-body { display: flex; flex-direction: column; gap: 10px; padding: 2px 0 14px; min-width: 0; }
.more-body > .label { margin: 6px 0 0; }
.more-body .list .lead[lang="ja"] { font-size: 22px; min-width: 0; }
.more-body .sentence-card { margin: 0; }
/* Conjugations: a form, then its affirmative and negative. */
table.conj { width: 100%; border-collapse: collapse; font-size: 15px; table-layout: fixed; }
table.conj caption { text-align: left; font-weight: 500; margin: 0 0 4px; }
table.conj th, table.conj td { padding: 5px 4px; border-top: 1px solid var(--rule); text-align: left; vertical-align: top; overflow-wrap: anywhere; }
table.conj thead th { border-top: 0; color: var(--muted); font-size: 12px; font-weight: 500; }
table.conj tbody th { color: var(--muted); font-weight: 400; font-size: 13px; width: 36%; }
table.conj td { font-family: var(--jp); }
/* The kanji in the word: the character, which opens its page, beside its meanings and readings. */
.kanji-brief { display: flex; gap: 14px; align-items: flex-start; }
.kanji-brief > div { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.kanji-brief .facts dd { overflow-wrap: anywhere; }
.glyph-link { flex: none; font-family: var(--jp); font-size: 40px; line-height: 1.1; color: var(--link); text-decoration: none; }
@media (hover: hover) and (pointer: fine) { a.glyph-link:hover { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 6px; } }
span.glyph-link { color: var(--muted); }
/* Imported dictionaries: each one's answer under its name. */
.imported { display: flex; flex-direction: column; gap: 4px; }
.imported .dict-name { color: var(--link); font-size: 14px; font-weight: 600; }
.imported .term { font-family: var(--jp); font-size: 18px; font-weight: 500; margin-top: 6px; }
.imported .term-tags { color: var(--link); font-size: 12px; }
.imported p.gloss { margin: 0; }
.imported .btn { align-self: flex-start; }
.pane-list > .card.imported { margin: 12px 14px; }
/* The tapped line, the word marked where the reader's wash was. */
.page-line { font-size: 17px; line-height: 1.8; margin: 0; }
.page-line mark { background: color-mix(in srgb, var(--mark-ink, var(--red)) var(--mark-a, 18%), transparent); color: inherit; border-radius: 3px; padding: 0 1px; }
/* The panel: title, span nudge and Close on one line; sources as tinted cards under it. */
.side .side-bar { flex-wrap: wrap; padding-right: 0; gap: 8px 10px; }
.side .side-bar > h2 { flex: 1 1 auto; margin: 0; font-size: 18px; }
.seg { display: inline-flex; border: 1px solid var(--edge); border-radius: 12px; overflow: hidden; background: var(--card); }
.seg-btn { min-height: 36px; padding: 4px 12px; font: inherit; font-size: 14px; color: var(--ink); background: transparent; border: 0; cursor: pointer; }
.seg-btn + .seg-btn { border-left: 1px solid var(--edge); }
@media (hover: hover) and (pointer: fine) { .seg-btn:hover { background: var(--sunk); } }
/* The pressed states the hover gate and the cleared tap flash leave to :active. */
.list a:active, .list button.rowlink:active, .list .row-link:active, .seg-btn:active { background: var(--sunk); }
.list .row-link.off:active { background: none; }
a.tile:active, .glyph-tile:active, .act:active { border-color: var(--ink); }
.seg-btn:focus-visible { outline-offset: -2px; }
.side .source { margin: 0 0 12px; padding: 14px 16px; border: 1px solid var(--rule); border-radius: 12px; background: var(--sunk); min-width: 0; }
.side .source .pill, .side .source .act { background: var(--card); }
.side .source .act[aria-pressed="true"] { background: var(--ink); }
.side .source .sentence-card { background: var(--card); }
.side .source details.more { border-top-color: color-mix(in srgb, var(--rule) 70%, transparent); }
.side > .btn.quiet { margin: 0 0 12px -8px; }
.side > details.more { margin: 0 0 12px; }
.gloss-prompt { display: flex; flex-direction: column; gap: 8px; margin: 0 0 12px; padding: 12px 14px; border-left: 3px solid var(--red); border-radius: 0 10px 10px 0; background: var(--sunk); }
.gloss-prompt .prompt-word { font-family: var(--jp); font-size: 28px; line-height: 1.2; }
@media (max-width: 400px) {
  .side { padding: 16px 14px; }
  .side .entry .prompt-word, .entry-card .entry .prompt-word { font-size: 30px; }
  .entry-card { padding: 16px 14px; }
  .side .source { padding: 12px; }
  .act { padding: 6px 10px; }
}
.entry .sentence-card { padding: 12px 16px; }
.entry .sentence-card .sentence { padding: 0; margin: 0 0 4px; background: none; }
.entry .sentence-card p { margin: 0 0 4px; }

/* Reader: ttsu-style settings */
/* The stage carries the phone's reader rows as variables (BookReader.kt);
   the viewport is the page, and in a paged book CSS columns one viewport
   wide (or tall, down) are the pages it steps through. */
.reader-page { max-width: min(1760px, 100%); }
/* Back, the title and the chapter count on one line: the page is the book. */
.reader-page .page-head { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; margin-bottom: 6px; }
.reader-page .page-head h1 { font-size: 20px; margin: 0; min-width: 0; overflow-wrap: anywhere; }
.reader-page .page-head .lede { margin: 0 0 0 auto; flex: none; font-size: 14px; }
@media (min-width: 801px) {
  :root[data-reading] main { padding: 14px clamp(16px, 2.5vw, 40px) 20px; }
  :root[data-reading] .reader-bar { margin-bottom: 8px; }
  :root[data-reading] .reader-stage { padding-block: 12px; }
  :root[data-reading] .reader-foot { margin-top: 8px; }
  :root[data-reading] .reader-viewport { --rd-page-h: clamp(300px, calc(100dvh - 232px), 1400px); }
  .reader-page .page-head > .btn.quiet { margin-bottom: 0; }
}
/* While a book is open the rail folds to its icons (Shell.reading), where
   there is a pointer to open it again: a touch window keeps the whole rail,
   which is how its theme and Sign out stay reachable. The grid track is 60px
   and a hover, or focus that arrived by keyboard, widens the rail itself over
   the page, so the book never reflows under the pointer. A mouse click that
   leaves focus on a button does not hold it open. */
@media (min-width: 801px) and (hover: hover) and (pointer: fine) {
  :root[data-reading] .shell { grid-template-columns: 60px minmax(0, 1fr); }
  :root[data-reading] .rail {
    width: 60px; padding-inline: 8px; z-index: 5; background: var(--paper);
    overflow-x: hidden; transition: width 0.18s ease, padding 0.18s ease, box-shadow 0.18s ease;
  }
  :root[data-reading] .rail:hover, :root[data-reading] .rail:focus-within:has(:focus-visible) {
    width: 232px; padding-inline: 14px; box-shadow: 8px 0 28px color-mix(in srgb, var(--ink) 16%, transparent);
  }
  /* Folded: icons only. The labels and the foot stay for screen readers and
     for Tab (which opens the rail), clipped as at 520px rather than removed. */
  :root[data-reading] .rail:not(:hover):not(:focus-within:has(:focus-visible)) .brand { font-size: 0; gap: 0; justify-content: center; padding-inline: 0; }
  :root[data-reading] .rail:not(:hover):not(:focus-within:has(:focus-visible)) nav a { position: relative; justify-content: center; padding-inline: 0; }
  :root[data-reading] .rail:not(:hover):not(:focus-within:has(:focus-visible)) nav a .label { position: absolute !important; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  :root[data-reading] .rail:not(:hover):not(:focus-within:has(:focus-visible)) nav a .count { position: absolute; top: 2px; right: auto; left: calc(50% + 8px); min-width: 15px; padding: 0 3px; font-size: 9px; line-height: 15px; }
  :root[data-reading] .rail:not(:hover):not(:focus-within:has(:focus-visible)) .foot { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; padding: 0; }
}
.reader-notice:empty { display: none; }
.reader-bar { flex-wrap: wrap; align-items: center; gap: 8px; margin: 0 0 14px; }
.reader-bar .reader-open { margin-left: auto; }
.reader-shell { display: flex; gap: 20px; align-items: flex-start; min-width: 0; }
.reader-stage {
  --rd-bg: var(--card); --rd-ink: var(--ink); --rd-soft: var(--muted);
  order: 1; flex: 1 1 auto; min-width: 0;
  padding: clamp(16px, 3vw, 32px) var(--rd-margin, 20px);
  background: var(--rd-bg); color: var(--rd-ink);
  border-radius: 12px; box-shadow: var(--lift);
  border: 1px solid color-mix(in srgb, var(--edge) 35%, transparent);
}
.reader-stage[data-tone="sepia"] { --rd-bg: #F3E9D2; --rd-ink: #3A2E20; --rd-soft: #6B5A45; }
.reader-stage[data-tone="night"] { --rd-bg: #111318; --rd-ink: #D8D2C4; --rd-soft: #9C968A; }
.reader-stage rt { color: var(--rd-soft); }
/* A width of its own: set vertical-rl, the viewport's width is its block size and would otherwise follow its text. */
.reader-viewport { --rd-page-h: clamp(300px, calc(100dvh - 250px), 1400px); width: 100%; height: var(--rd-page-h); overflow: hidden; outline-offset: 6px; border-radius: 4px; }
.reader-stage[data-paging="scroll"] .reader-viewport { overflow-y: auto; overscroll-behavior: contain; }
.reader-stage[data-flow="down"] .reader-viewport { writing-mode: vertical-rl; }
.reader-stage[data-flow="down"][data-paging="scroll"] .reader-viewport { overflow-x: auto; overflow-y: hidden; }
.reader-stage[data-paging="paged"] .reader-viewport { touch-action: pan-y pinch-zoom; }
.reader-book { font-family: var(--rd-face, var(--jp)); font-size: var(--rd-size, 20px); line-height: var(--rd-leading, 1.95); color: inherit; overflow-wrap: anywhere; }
.reader-stage[data-flow="across"][data-paging="scroll"] .reader-book { max-width: 52em; margin: 0 auto; }
.reader-stage[data-flow="down"] .reader-book { writing-mode: vertical-rl; padding-top: var(--rd-top, 0); }
.reader-stage[data-paging="paged"] .reader-book { column-fill: auto; }
.reader-book .rp { margin-block: 0 var(--rd-gap, 0.6em); }
.reader-book .rp.indent { text-indent: 1em; }
/* No hover wash: a run is a whole paragraph when the book carries no furigana,
   so hovering one word lit the sentence. The tap marks the word it finds. */
.reader-book .tap { border-radius: 3px; cursor: pointer; }
@media (hover: hover) and (pointer: fine) { .reader-book .tap:hover { background: none; } }
.reader-book .tap:focus-visible { background: color-mix(in srgb, var(--red) 14%, transparent); }
.reader-book .tap:focus-visible { outline-offset: 1px; }
.reader-book mark.reader-mark { color: inherit; background: color-mix(in srgb, var(--mark-ink, var(--red)) var(--mark-a, 26%), transparent); border-radius: 3px; box-shadow: 0 0 0 2px color-mix(in srgb, var(--mark-ink, var(--red)) var(--mark-a, 26%), transparent); }
/* A word washed in pieces (ADR-497): no piece's shadow overlaps the next, the
   cross-line breadth comes from padding instead, and only the word's ends round. */
.reader-book mark.reader-mark.join { box-shadow: none; border-radius: 0; padding-block: 2px; }
.reader-book mark.reader-mark.join.head { border-start-start-radius: 3px; border-end-start-radius: 3px; }
.reader-book mark.reader-mark.join.tail { border-start-end-radius: 3px; border-end-end-radius: 3px; }
.reader-book .plate { display: block; width: auto; max-width: 100%; max-height: 100%; margin: 0 auto; break-inside: avoid; }
/* The wash sits on the drawing itself: the frame is exactly the picture's box. */
.reader-book .plate-frame { position: relative; width: fit-content; max-width: 100%; margin: 0 auto; break-inside: avoid; writing-mode: horizontal-tb; line-height: 0; }
/* A whole page in view: the book's percentage height does not resolve, so the viewport's own height bounds it. */
.reader-book .plate-frame .plate { margin: 0; cursor: pointer; max-height: var(--rd-page-h, 80vh); }
.plate-marks { position: absolute; inset: 0; pointer-events: none; }
/* Pinch and drag move the layer inside the frame, which clips it (P53). */
.plate-frame { overflow: hidden; }
.plate-layer { position: relative; will-change: transform; }
.plate-frame.zoomed .plate { cursor: grab; }
/* Two pages (PictureTurn.SPREAD): the earlier on the right, the pair meeting at the middle as a printed spread does. */
.reader-book .plate-spread { display: flex; flex-direction: row-reverse; justify-content: center; align-items: flex-start; break-inside: avoid; }
.reader-book .plate-spread > .plate-frame, .reader-book .plate-slot { max-width: 50%; margin: 0; }
.reader-book .plate-slot > .plate-frame { margin: 0; }
.plate-mark { position: absolute; border-radius: 3px; background: color-mix(in srgb, var(--red) 30%, transparent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--red) 30%, transparent); mix-blend-mode: multiply; }
.picture-note { margin: 8px 0 0; text-align: center; cursor: pointer; }
.reader-book > .notice, .reader-book > .muted { font-size: 17px; font-family: system-ui, sans-serif; }
.reader-book [class^="heat-"] { border-radius: 2px; }
.reader-stage[data-tone="night"] .heat-learning { background: #262A33; }
.reader-stage[data-tone="night"] .reader-book [class^="heat-"]:not(.heat-learning) { background: #1F3A28; }
/* A toned page is its own side whatever the app is (PageTone, ReaderTone.kt):
   sepia takes the light tokens, night the dark ones, so heat, the dye and the
   marker's strength are the ones measured for that ground. */
.reader-stage[data-tone="sepia"] { --card: #FFFFFF; --sunk: #EFE7D8; --good: #1D6B3C; --good-wash: #DCEFE1; color-scheme: light; }
.reader-stage[data-tone="night"] { --good: #8FD4A5; --good-wash: #1F3A28; color-scheme: dark; }
:root[data-accent="ai"] .reader-stage[data-tone="sepia"] { --red: #1E3566; --link: #1E3566; }
:root[data-accent="asagi"] .reader-stage[data-tone="sepia"] { --red: #1E4A52; --link: #1E4A52; }
:root[data-accent="murasaki"] .reader-stage[data-tone="sepia"] { --red: #4A2C54; --link: #4A2C54; }
:root[data-accent="suo"] .reader-stage[data-tone="sepia"] { --red: #5C2436; --link: #5C2436; }
:root[data-accent="matsuba"] .reader-stage[data-tone="sepia"] { --red: #2F4A38; --link: #2F4A38; }
:root[data-accent="uguisu"] .reader-stage[data-tone="sepia"] { --red: #4A5820; --link: #4A5820; }
:root[data-accent="sakura"] .reader-stage[data-tone="sepia"] { --red: #7E3642; --link: #7E3642; }
:root[data-accent="ai"] .reader-stage[data-tone="night"] { --red: #9EB0DC; --link: #9EB0DC; }
:root[data-accent="asagi"] .reader-stage[data-tone="night"] { --red: #6BB8B0; --link: #6BB8B0; }
:root[data-accent="murasaki"] .reader-stage[data-tone="night"] { --red: #C4A0D4; --link: #C4A0D4; }
:root[data-accent="suo"] .reader-stage[data-tone="night"] { --red: #E498A4; --link: #E498A4; }
:root[data-accent="matsuba"] .reader-stage[data-tone="night"] { --red: #8FBC8F; --link: #8FBC8F; }
:root[data-accent="uguisu"] .reader-stage[data-tone="night"] { --red: #B8C86A; --link: #B8C86A; }
:root[data-accent="sakura"] .reader-stage[data-tone="night"] { --red: #F0B8C0; --link: #F0B8C0; }
:root[data-marker]:not([data-marker="current"]) .reader-stage[data-tone="sepia"] { --mark-a: 40%; }
:root[data-marker]:not([data-marker="current"]) .reader-stage[data-tone="night"] { --mark-a: 28%; }
.reader-drawer {
  order: 2; flex: 0 0 340px; position: sticky; top: 16px;
  max-height: calc(100dvh - 32px); overflow-y: auto;
  display: flex; flex-direction: column; gap: 16px;
  padding: 16px 18px; background: var(--card); color: var(--ink);
  border: 1px solid color-mix(in srgb, var(--edge) 45%, transparent); border-radius: 12px; box-shadow: var(--lift);
}
.reader-drawer-head { display: flex; align-items: center; gap: 8px; }
.reader-drawer-head h2 { flex: 1 1 auto; margin: 0; font-size: 18px; }
.reader-drawer-head h2:focus { outline: none; }
.reader-drawer > p { margin: -8px 0 0; }
.reader-drawer .radio { min-height: 36px; padding: 4px 12px; }
.reader-drawer .specimen { font-size: 18px; min-width: 0; line-height: 1; }
.stepper { display: grid; grid-template-columns: minmax(0, 1fr) auto auto auto; align-items: center; gap: 8px; }
.stepper-label { font-weight: 500; }
.stepper-value { min-width: 2.2em; text-align: right; font-variant-numeric: tabular-nums; }
.stepper .btn { min-width: 40px; min-height: 36px; justify-content: center; }
.reader-keys dl { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 6px 14px; margin: 10px 0 4px; font-size: 14px; }
.reader-keys dt { white-space: nowrap; font-variant-numeric: tabular-nums; color: var(--muted); }
.reader-keys dd { margin: 0; }
.reader-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px 10px; flex-wrap: wrap; margin: 12px 0 0; }
.reader-foot[data-flow="down"] { flex-direction: row-reverse; }
.reader-position { flex: 1 1 auto; text-align: center; font-variant-numeric: tabular-nums; }
@media (max-width: 900px) {
  /* A strip at the foot, as the phone's: the page above stays lit and live.
     Sticky rather than fixed, because `main` is a size container and so the
     containing block a fixed strip would take. */
  .reader-shell { flex-direction: column; align-items: stretch; }
  .reader-drawer {
    position: sticky; top: auto; bottom: 0; z-index: 2;
    max-height: 46dvh; flex-basis: auto;
  }
}
@media (max-width: 800px) {
  .reader-drawer { bottom: calc(66px + env(safe-area-inset-bottom)); }
}
@media (max-width: 520px) {
  .reader-stage { border-radius: 12px; padding-top: 14px; padding-bottom: 14px; }
  .reader-viewport { --rd-page-h: clamp(240px, calc(100dvh - 280px), 900px); }
  .reader-bar .reader-open { margin-left: 0; }
}
.along-bar { padding: 8px 12px; margin: 0 0 12px; border-radius: 12px; background: var(--sunk); }
.along-bar .along-line { flex: 1 1 12em; }
.along-bar .aloud-rate { width: auto; min-width: 5.5em; }

/* The shop's preview (ADR-366): a modal dialog showing a cosmetic where it is worn. */
.page > dialog.preview, dialog.preview { margin: auto; width: min(30rem, calc(100vw - 32px)); max-height: calc(100vh - 32px); max-height: calc(100dvh - 32px); overflow: auto; padding: 20px; color: var(--ink); background: var(--card); border: 1px solid color-mix(in srgb, var(--edge) 45%, transparent); }
dialog.preview::backdrop { background: rgba(0, 0, 0, 0.45); }
dialog.preview h2 { margin: 0 0 4px; }
dialog.preview > .sub { display: flex; gap: 4px; align-items: center; color: var(--muted); font-size: 14px; }
dialog.preview .study.sample { margin: 12px 0; padding: 20px 16px; gap: 10px; box-shadow: none; pointer-events: none; }
dialog.preview .study.sample .prompt-glyph { font-size: 4rem; }
dialog.preview .bars.sample { margin: 12px 0; }
dialog.preview .bars.sample .bar-row { grid-template-columns: 36px minmax(0, 1fr); }
dialog.preview > .sample:not(.bars):not(.study) { margin: 16px 0; }
dialog.preview .row.end { margin-top: 12px; }

/* The lookup marker (WordMark.kt). Current leaves --mark-ink unset, so a mark
   stays the dye at its own strength; a named pen is its pigment at 0.40 on
   cream and 0.28 on the indigo ground, as Marker.wash measures it. */
:root[data-marker="lemon"] { --mark-ink: #F5E04A; --mark-a: 40%; }
:root[data-marker="sakura"] { --mark-ink: #F472B6; --mark-a: 40%; }
:root[data-marker="sprout"] { --mark-ink: #4ADE80; --mark-a: 40%; }
:root[data-marker="mizu"] { --mark-ink: #38BDF8; --mark-a: 40%; }
:root[data-marker="fuji"] { --mark-ink: #C084FC; --mark-a: 40%; }
:root[data-marker="mikan"] { --mark-ink: #FB923C; --mark-a: 40%; }
:root[data-theme="dark"][data-marker]:not([data-marker="current"]) { --mark-a: 28%; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"])[data-marker]:not([data-marker="current"]) { --mark-a: 28%; } }

/* Word colours (Accents.kt RUBY_PALETTES_LIGHT/_DARK): the word card's divided
   reading alternates two inks, the reading wearing its kanji's. As a chip the
   ink moves behind the kanji at 0.40 and the kanji stays body colour. None
   sets nothing, so the pieces keep the body colour and the muted reading. */
:root[data-ruby-tint="seiji"] { --tint-0: #0B6E68; --tint-1: #C0390C; }
:root[data-ruby-tint="murasaki"] { --tint-0: #7326A8; --tint-1: #B04900; }
:root[data-ruby-tint="kurenai"] { --tint-0: #C01A72; --tint-1: #0E7551; }
:root[data-ruby-tint="fuji"] { --tint-0: #6042C8; --tint-1: #4A7A0E; }
:root[data-ruby-tint="ai"] { --tint-0: #1E50A2; --tint-1: #C0390C; }
:root[data-theme="dark"][data-ruby-tint="seiji"] { --tint-0: #5AD1C6; --tint-1: #FF7A52; }
:root[data-theme="dark"][data-ruby-tint="murasaki"] { --tint-0: #C48BFF; --tint-1: #FF8A45; }
:root[data-theme="dark"][data-ruby-tint="kurenai"] { --tint-0: #FF77B4; --tint-1: #4FC79A; }
:root[data-theme="dark"][data-ruby-tint="fuji"] { --tint-0: #B0A0FF; --tint-1: #9CCB4A; }
:root[data-theme="dark"][data-ruby-tint="ai"] { --tint-0: #8CAAFE; --tint-1: #FF7A52; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"])[data-ruby-tint="seiji"] { --tint-0: #5AD1C6; --tint-1: #FF7A52; }
  :root:not([data-theme="light"])[data-ruby-tint="murasaki"] { --tint-0: #C48BFF; --tint-1: #FF8A45; }
  :root:not([data-theme="light"])[data-ruby-tint="kurenai"] { --tint-0: #FF77B4; --tint-1: #4FC79A; }
  :root:not([data-theme="light"])[data-ruby-tint="fuji"] { --tint-0: #B0A0FF; --tint-1: #9CCB4A; }
  :root:not([data-theme="light"])[data-ruby-tint="ai"] { --tint-0: #8CAAFE; --tint-1: #FF7A52; }
}
ruby.tint-0 { color: var(--tint-0, inherit); }
ruby.tint-1 { color: var(--tint-1, inherit); }
ruby.tint-0 rt { color: var(--tint-0, var(--muted)); }
ruby.tint-1 rt { color: var(--tint-1, var(--muted)); }
:root[data-ruby-chip] ruby.tint-0, :root[data-ruby-chip] ruby.tint-1 { color: inherit; }
/* The chip is the phone's (RubyText.kt chipBehind): the base text's own height (a
   little over its em, as Compose lays it out), not the line box, inset a fortieth of the glyph each side so 場 and 合 stay two
   chips, with a radius of 0.16 of the glyph. An inline background fills the
   whole line height, which drew a tall pill reaching past the kanji. */
:root[data-ruby-chip] ruby.tint-0 .base, :root[data-ruby-chip] ruby.tint-1 .base {
  display: inline-block;
  line-height: 1.2;
  border-radius: 0.16em;
  background: linear-gradient(var(--chip), var(--chip)) center / calc(100% - 0.05em) 100% no-repeat;
}
:root[data-ruby-chip] ruby.tint-0 .base { --chip: color-mix(in srgb, var(--tint-0) 40%, transparent); }
:root[data-ruby-chip] ruby.tint-1 .base { --chip: color-mix(in srgb, var(--tint-1) 40%, transparent); }

/* A finger has no keyboard: the key hints and the number on each choice
   come off when the primary pointer is coarse, as press() in Dom.kt says
   "tap" there (QA 2026-10-12, ADR-403). */
@media (pointer: coarse) {
  .keys, button kbd, .tiles button small { display: none; }
}

/* Settings' colour sample is a picture of a button, not one (ADR-403). */
.settings-preview .sample-button { pointer-events: none; cursor: default; }

/* A tap on a word the dictionary does not have says so for a moment. */
.tap-miss { margin: 6px 0 0; }

/* The learner's own note on an item (Notes.kt, ADR-255). */
.item-note { margin: 16px 0; }
.item-note-text { white-space: pre-wrap; margin: 0 0 8px; }
.item-note-field { display: block; width: 100%; min-height: 4.5em; resize: vertical; font: inherit; line-height: 1.5; }

/* The public dictionary at /dictionary (ADR-470): the site's header and
   footer (site/style.css .bar, .nav, .theme, .foot) around the app's
   dictionary, with no rail. */
.site-frame { width: min(1080px, calc(100% - 48px)); margin: 0 auto; padding: 22px 0 48px; min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; }
.site-frame main { padding: 28px 0 0; flex: 1; }
.site-bar { display: flex; align-items: center; gap: 28px; padding-bottom: 16px; border-bottom: 1px solid var(--rule); }
.site-bar .brand { display: flex; align-items: center; gap: 10px; flex: none; color: var(--ink); text-decoration: none; font-weight: 500; }
.site-bar .mark { display: block; width: 28px; height: 26px; flex: none; background: var(--ink); -webkit-mask: url("/mark.svg") center / contain no-repeat; mask: url("/mark.svg") center / contain no-repeat; }
.site-nav { margin-left: auto; display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: 8px 18px; font-size: 15px; }
.site-nav a { color: var(--muted); text-decoration: none; }
@media (hover: hover) and (pointer: fine) { .site-nav a:hover { color: var(--link); text-decoration: underline; } }
.site-nav a:active { color: var(--link); text-decoration: underline; }
.site-nav a[aria-current="page"] { color: var(--ink); font-weight: 500; text-decoration: underline; text-underline-offset: 4px; }
.site-nav .theme { font: inherit; font-size: 14px; color: var(--muted); background: transparent; border: 1px solid var(--edge); border-radius: 8px; padding: 6px 10px; cursor: pointer; }
.site-foot { display: flex; flex-wrap: wrap; gap: 8px 18px; margin-top: 36px; padding-top: 16px; border-top: 1px solid var(--rule); font-size: 14px; }
.site-foot a { color: var(--muted); }
.site-foot .mail { margin-left: auto; }
@media (max-width: 640px) { .site-frame { width: calc(100% - 32px); } .site-bar { flex-wrap: wrap; gap: 12px; } .site-nav { margin-left: 0; justify-content: flex-start; } }

/* A send to Anki after the first, said on the page (the phone's ExportNotice, ADR-470). */
.anki-notice { position: fixed; left: 50%; bottom: 16px; transform: translateX(-50%); z-index: 20; display: flex; align-items: center; gap: 12px; max-width: calc(100% - 32px); padding: 10px 16px; border-radius: 8px; background: var(--ink); color: var(--paper); }
.anki-notice .btn { color: var(--paper); border-color: var(--paper); }

/* A page drawn again in place (Shell.redraw) has not arrived: it does not rise and fade in a second time. */
main[data-redraw] > * { animation: none !important; }
