/* Japanese Kanji - card styling.
 *
 * Two rules govern everything below.
 *
 * 1. Every colour is a token on .kanji-card, and the dark palette redefines the
 *    tokens rather than restyling components. Four things can ask for it, and they
 *    are written as one selector list per palette so the hexes are stated once:
 *
 *      the reader          .kanji-card[data-theme="dark"]
 *      the page around it  html[data-theme="dark"]
 *      Anki desktop        .night_mode  on an ancestor
 *      AnkiDroid/Mobile    .nightMode   on an ancestor
 *      everywhere else     @media (prefers-color-scheme: dark)
 *
 *    The second is for the lookup site, whose settings panel is itself a
 *    `.kanji-card` that no runtime ever stamps: the site writes the word on <html>
 *    once and every card on the page follows. In Anki nothing writes it there, so
 *    that selector simply never matches.
 *
 *    The `html:not(...)` on the media query is not decoration either. A bare
 *    `:not([data-theme="light"]) .kanji-card` would match through any ancestor that
 *    is not light - which is every div on the page - and exclude nothing.
 *
 *    The reader's choice outranks the other three, which is why each of them is
 *    written `:not([data-theme="light"])`. Anki does not always agree with the OS -
 *    a light Anki on a dark desktop used to render a dark card - and `light` is the
 *    answer to that, not a bug report.
 * 2. Nothing is sized in fixed pixels above 20px. The 2017 template asked for a
 *    180px glyph, which is more than half the height of a phone screen.
 */

.card {
  /* Anki's own wrapper: give it a ground so the page behind the card is not the
     app's default white in night mode. */
  background: transparent;
  padding: 0;
  margin: 0;
}

/* Blank until built - see the note at the head of each template. Visibility rather
   than display: the stroke animation measures path lengths on first build, and an
   element with no box has no lengths to measure. */
.k-hold .kanji-card { visibility: hidden; }

.kanji-card {
  --paper: #ffffff;
  --sunk: #f2f4f8;
  --ink: #14161d;
  --ink-2: #4c5366;
  --ink-3: #7a8298;
  --rule: #dfe3ec;
  --guide: #ccd3e2;
  --accent: #23407a;
  --accent-soft: #e6ecf8;
  --brush: #14161d;

  box-sizing: border-box;
  max-width: 44rem;
  margin: 0 auto;
  padding: clamp(0.75rem, 3vw, 1.5rem);
  background: var(--paper);
  color: var(--ink);
  font-family: -apple-system, "Segoe UI Variable Text", "Segoe UI", Roboto,
    system-ui, sans-serif;
  font-size: clamp(15px, 1.1vw + 13px, 18px);
  line-height: 1.6;
  text-align: left;
  display: flex;
  flex-direction: column;
  gap: clamp(0.9rem, 2.5vw, 1.35rem);
}

.kanji-card[data-theme="dark"],
html[data-theme="dark"] .kanji-card:not([data-theme="light"]),
.night_mode .kanji-card:not([data-theme="light"]),
.nightMode .kanji-card:not([data-theme="light"]) {
  --paper: #16181f;
  --sunk: #1d212a;
  --ink: #e8eaf1;
  --ink-2: #a3abbe;
  --ink-3: #7d8598;
  --rule: #2b3140;
  --guide: #363d4f;
  --accent: #8facee;
  --accent-soft: #1b2440;
  --brush: #e8eaf1;
}

@media (prefers-color-scheme: dark) {
  html:not([data-theme="light"]) .kanji-card:not([data-theme="light"]) {
    --paper: #16181f;
    --sunk: #1d212a;
    --ink: #e8eaf1;
    --ink-2: #a3abbe;
    --ink-3: #7d8598;
    --rule: #2b3140;
    --guide: #363d4f;
    --accent: #8facee;
    --accent-soft: #1b2440;
    --brush: #e8eaf1;
  }
}

/* ------------------------------------------------------------------- preferences
 *
 * Every setting that only changes how the card looks is an attribute on the card
 * element and a rule here, so the runtime writes one word and the cascade does the
 * rest. Nothing below is read by script.
 *
 * The accent tones are chosen for the two grounds separately rather than by
 * lightening one hex: a colour that carries on white at 4.5:1 goes muddy on #16181f,
 * and the label it tints has to stay readable on both.
 */
.kanji-card[data-size="s"] { font-size: clamp(13px, 0.9vw + 11px, 15.5px); }
.kanji-card[data-size="l"] { font-size: clamp(17px, 1.3vw + 15px, 21px); }

/* The palette is ten named tones rather than ten pairs of hexes spread through the
   rules below: the swatch in the settings panel and the accent it sets have to be
   the same colour, and reading them from one token is how that stays true.

   Each tone is picked for its ground, not lightened from the other. A hue that
   carries on white at 4.5:1 goes muddy on #16181f, and these tint the labels and
   the stroke being taught, so both have to stay legible. */
.kanji-card {
  --tone-indigo:  #23407a;  --soft-indigo:  #e6ecf8;
  --tone-blue:    #10559a;  --soft-blue:    #e2eefb;
  --tone-teal:    #0f6a66;  --soft-teal:    #dcefed;
  --tone-green:   #2b6a34;  --soft-green:   #e2f0e3;
  --tone-olive:   #63611a;  --soft-olive:   #eeeeda;
  --tone-amber:   #8a5200;  --soft-amber:   #f8ecd8;
  --tone-rust:    #94421c;  --soft-rust:    #fae5da;
  --tone-crimson: #9a2540;  --soft-crimson: #fbe2e7;
  --tone-plum:    #7a2f63;  --soft-plum:    #f4e4ef;
  --tone-ink:     #2f3440;  --soft-ink:     #e9ebf0;
}

.kanji-card[data-theme="dark"],
html[data-theme="dark"] .kanji-card:not([data-theme="light"]),
.night_mode .kanji-card:not([data-theme="light"]),
.nightMode .kanji-card:not([data-theme="light"]) {
  --tone-indigo:  #8facee;  --soft-indigo:  #1b2440;
  --tone-blue:    #6bb2f0;  --soft-blue:    #12283d;
  --tone-teal:    #58c7bf;  --soft-teal:    #12312f;
  --tone-green:   #82c68a;  --soft-green:   #16301a;
  --tone-olive:   #c9c05a;  --soft-olive:   #2c2a10;
  --tone-amber:   #e0ac5a;  --soft-amber:   #33270f;
  --tone-rust:    #ef9a71;  --soft-rust:    #37200f;
  --tone-crimson: #f08fa4;  --soft-crimson: #3a1620;
  --tone-plum:    #dc9ac8;  --soft-plum:    #33203b;
  --tone-ink:     #b9c0d0;  --soft-ink:     #262b36;
}

@media (prefers-color-scheme: dark) {
  html:not([data-theme="light"]) .kanji-card:not([data-theme="light"]) {
    --tone-indigo:  #8facee;  --soft-indigo:  #1b2440;
    --tone-blue:    #6bb2f0;  --soft-blue:    #12283d;
    --tone-teal:    #58c7bf;  --soft-teal:    #12312f;
    --tone-green:   #82c68a;  --soft-green:   #16301a;
    --tone-olive:   #c9c05a;  --soft-olive:   #2c2a10;
    --tone-amber:   #e0ac5a;  --soft-amber:   #33270f;
    --tone-rust:    #ef9a71;  --soft-rust:    #37200f;
    --tone-crimson: #f08fa4;  --soft-crimson: #3a1620;
    --tone-plum:    #dc9ac8;  --soft-plum:    #33203b;
    --tone-ink:     #b9c0d0;  --soft-ink:     #262b36;
  }
}

.kanji-card[data-accent="indigo"]  { --accent: var(--tone-indigo);  --accent-soft: var(--soft-indigo); }
.kanji-card[data-accent="blue"]    { --accent: var(--tone-blue);    --accent-soft: var(--soft-blue); }
.kanji-card[data-accent="teal"]    { --accent: var(--tone-teal);    --accent-soft: var(--soft-teal); }
.kanji-card[data-accent="green"]   { --accent: var(--tone-green);   --accent-soft: var(--soft-green); }
.kanji-card[data-accent="olive"]   { --accent: var(--tone-olive);   --accent-soft: var(--soft-olive); }
.kanji-card[data-accent="amber"]   { --accent: var(--tone-amber);   --accent-soft: var(--soft-amber); }
.kanji-card[data-accent="rust"]    { --accent: var(--tone-rust);    --accent-soft: var(--soft-rust); }
.kanji-card[data-accent="crimson"] { --accent: var(--tone-crimson); --accent-soft: var(--soft-crimson); }
.kanji-card[data-accent="plum"]    { --accent: var(--tone-plum);    --accent-soft: var(--soft-plum); }
.kanji-card[data-accent="ink"]     { --accent: var(--tone-ink);     --accent-soft: var(--soft-ink); }

/* The character itself in the accent, for a reader who wants the ink to match the
   labels. Ink is the default because black on paper is what a character is. */
.kanji-card[data-brush="accent"] { --brush: var(--accent); }

.kanji-card * { box-sizing: border-box; }

/* Anki desktop is not a bare browser: it puts `fancy` on the reviewer's body and
   ships, in its own `webview.css`,
       .isWin button { font-size: 12px }
       .fancy button { border-radius: var(--border-radius-large);   // 15px
                       box-shadow: 0 2px 1px -1px ... }
   plus a plain `button { padding: 8px 10px; margin: 0 4px; font-weight: 500 }`.
   The first two are one class and one element - (0,1,1) - so a single-class rule
   of ours such as `.k-step` loses to them on SPECIFICITY, not on order, and no
   amount of moving our stylesheet fixes it. A 1.9rem button with a 15px radius is
   a circle, which is exactly what the three stroke controls became on the desktop.

   So every rule below whose subject is a <button> is written `.kanji-card .k-*`
   rather than `.k-*`. Two classes outrank one class and an element, the relative
   order among our own rules is unchanged because all of them were raised by the
   same amount, and nothing needs `!important`. The properties Anki sets that we
   did not previously declare - margin, box-shadow - are stated in each button's
   base rule for the same reason, and `margin` is written as the FULL shorthand
   even where only the top matters: a longhand `margin-top` leaves the left and
   right to Anki's `margin: 0 4px`, which is what pushed "Glyph Origin" and
   "Show 3 more" four pixels right of the text they sit under.

   Keep it that way: a new `<button>` styled from a bare `.k-thing` selector will
   look right in the repository preview and wrong in Anki. */
.json-src { display: none; }
.k-hidden { display: none !important; }

/* And the attribute, for the same reason and with the same weight.
 *
 * A user-agent `display: none` - which is all `hidden` is - loses to ANY author
 * declaration, whatever the specificity suggests. `.k-stroke-bar { display: flex }`
 * was therefore stronger than the `hidden` the template ships that element with,
 * and the stroke controls sat under the character before the runtime had decided
 * whether this card has strokes to show. `.k-pills`, `.k-vocab`, `.k-links` and
 * `.k-chips` were one `hidden` away from the same thing.
 *
 * `!important` is what it takes: the rules it has to beat are ordinary class rules
 * in this very file, and hiding is the one thing a `hidden` element must always
 * manage. */
[hidden] { display: none !important; }
.k-quiet { color: var(--ink-3); }

/* ---------------------------------------------------------------- front sides */

/* Both question cards centre themselves in the viewport: a keyword, or a character
   with a hint button under it, left at the top of a tall card reads as a page that
   failed to load. At phone widths the recognition card gives that up - see the
   note in the media query at the foot of this file. */
.kanji-front {
  min-height: 60vh;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 0.5rem;
}

.k-ask {
  font-family: "Yu Mincho", "YuMincho", "Hiragino Mincho ProN", "MS Mincho",
    "Noto Serif JP", serif;
  font-size: clamp(5rem, 34vw, 13rem);
  line-height: 1.05;
}

.k-ask-keyword {
  font-size: clamp(1.6rem, 7vw, 2.6rem);
  line-height: 1.2;
  font-weight: 600;
  text-wrap: balance;
}

/* Vietnamese edition only: the Sino-Vietnamese reading leads, and the gloss under
   it drops to a supporting size. Absent from the English build entirely. */
.k-ask-hanviet {
  font-size: clamp(2rem, 9vw, 3.2rem);
  line-height: 1.1;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--accent);
}
.k-ask-hanviet + .k-ask-keyword {
  font-size: clamp(1.05rem, 4.5vw, 1.4rem);
  font-weight: 400;
  color: var(--ink-2);
  margin-top: 0.15rem;
}


/* A hint is offered, never shown. The button is the whole of it until pressed, and
   each press appends one more row - so what has been revealed stays revealed and
   the reviewer can stop wherever they got there. */
.kanji-card .k-hint-btn {
  /* Anki's own button reset, undone - see the note above `.kanji-card *`. */
  box-shadow: none;
  align-self: center;
  margin: 0.6rem 0 0;
  padding: 0.25rem 0.8rem;
  font: inherit;
  font-size: 0.78em;
  color: var(--ink-3);
  background: none;
  border: 1px solid var(--rule);
  border-radius: 0.4rem;
  cursor: pointer;
}
.kanji-card .k-hint-btn:hover { color: var(--accent); border-color: var(--accent); }

/* Every rung is shaped the same - label above, body under it, both centred on the
   card's own axis - so pressing the button adds a rung and moves nothing that is
   already on screen.
   Two earlier layouts each moved something. Laying the label beside the body left
   the wrap point up to how long that particular gloss ran, so one rung sat on a
   line and the next stood in two, and the wrapped half - being full width - was
   centred by nothing and fell flush left under a label that stayed centred. Laying
   the rungs out as a shrink-to-fit two-column grid lined them up with each other
   but sized the whole block to its widest rung, so revealing a word slid the two
   rungs above it sideways. */
.k-hints {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.7rem;
  max-width: min(26rem, 100%);
  margin: 0.6rem auto 0;
  font-size: 0.9em;
}
.k-hints:empty { display: none; }
.k-hint-row {
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Tight against its own body and loose against the next rung, so the label reads
     as belonging to what is under it rather than floating between two rungs. */
  gap: 0.15rem;
  max-width: 100%;
}
.k-hint-label {
  font-size: 0.72em;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.k-hint-body {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: baseline;
  gap: 0.3rem;
}
.k-hint-reading {
  font-family: "Yu Gothic", "Hiragino Kaku Gothic ProN", "Noto Sans JP", sans-serif;
  font-size: 1.15em;
  letter-spacing: 0.06em;
  color: var(--accent);
}
/* Its own line always, rather than beside the word when it happens to be short
   enough: a gloss that sometimes sits right and sometimes below reads as a mistake. */
.k-hint-gloss { flex-basis: 100%; color: var(--ink-2); font-size: 0.85em; }
.k-hint-story {
  margin: 0;
  font-size: 0.85em;
  line-height: 1.5;
  color: var(--ink-2);
}

/* ----------------------------------------------------------------------- hero */

.k-hero {
  display: flex;
  gap: clamp(0.85rem, 3vw, 1.4rem);
  align-items: flex-start;
}

.k-stage-wrap { flex: 0 0 auto; }

.k-stage {
  position: relative;
  width: clamp(7.5rem, 38vw, 9.5rem);
  aspect-ratio: 1;
  border: 1px solid var(--rule);
  border-radius: 0.6rem;
  background: var(--sunk);
  display: grid;
  place-items: center;
  overflow: hidden;
}
/* The guide lines a practice sheet has. An empty box says how big to write; it is
   the cross that says where each stroke starts and how far it reaches - 中 is the
   vertical, 十 is both, and without it the box teaches size and nothing else.
   Dashed and faint on purpose: a guide the eye can ignore while reading the
   character and find again while copying it.

   Drawn as an SVG the runtime builds rather than as two pseudo-elements, for two
   reasons. A positioned pseudo-element paints over the character - the guide ended
   up laid across the ink instead of ruled under it - and two of them can only ever
   make one cross, where a sheet ruled into sixteen wants six lines. */
.k-grid {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}
.k-grid line {
  stroke: var(--guide);
  stroke-width: 1;
  stroke-dasharray: 3 3;
  /* The box scales with the card; the ruling should not get thicker with it. */
  vector-effect: non-scaling-stroke;
}
/* Everything else in the square sits on top of the ruling, which is the whole
   point of ruling: paper first, ink second. */
.k-stage > :not(.k-grid) { position: relative; z-index: 1; }

/* Panel off: the character sits directly on the card, with nothing around it. */
.k-stage.k-bare { background: transparent; border-color: transparent; }

.k-glyph {
  position: relative;
  font-family: "Yu Mincho", "YuMincho", "Hiragino Mincho ProN", "MS Mincho",
    "Noto Serif JP", serif;
  font-size: clamp(3.6rem, 16vw, 5.4rem);
  line-height: 1;
}
.k-stage.k-has-svg .k-glyph { display: none; }

.k-svg {
  position: relative;
  width: 100%;
  height: 100%;
  display: block;
}

.k-stroke {
  fill: none;
  stroke: var(--brush);
  stroke-width: 4.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: opacity 0.12s linear;
}
/* Play writes each stroke along its own path, so the dash properties are set per
   stroke by the runtime, which is the only place the path's length is known. */
@media (prefers-reduced-motion: reduce) {
  .k-stroke { transition: none; }
}
/* Stepping hides the strokes not written yet; it does not redraw the ones that are,
   so going back and forward is instant rather than animated each way. */
.k-stroke.k-off { opacity: 0; }
/* The stroke just added is the one being taught. */
.k-stroke.k-newest { stroke: var(--accent); }

/* Numbers placed where each stroke begins, from the path data itself. */
.k-stroke-no {
  font-family: -apple-system, "Segoe UI", system-ui, sans-serif;
  font-size: 7px;
  font-weight: 600;
  fill: var(--accent);
  paint-order: stroke;
  stroke: var(--sunk);   /* a halo, so a number over ink stays readable */
  stroke-width: 2.4;
  stroke-linejoin: round;
  dominant-baseline: middle;
  text-anchor: middle;
  transition: opacity 0.12s linear;
}
.k-stage.k-bare .k-stroke-no { stroke: var(--paper); }
.k-stroke-no.k-off { opacity: 0; }
/* Numbers follow the strokes, including while they are being written: `paint()`
   turns each one on with the stroke it labels, so the count builds as the hand
   moves. They used to be hidden during play on the grounds that they crowd the
   character, which is what the setting itself is now for. */
.k-svg.k-no-numbers .k-stroke-no { opacity: 0; }

/* Centred under the stage on every width. It used to sit left because a stroke
   counter held the right end with `margin-left: auto`; with the counter gone there
   was nothing balancing the three buttons against the character above them. */
.k-stroke-bar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
  margin-top: 0.5rem;
}
/* A square box that centres its glyph both ways, rather than a padded line of
   text. `A` and `B6` and `½9½9` have different vertical metrics and
   different widths, so padding and a line-height put each of the three in a
   slightly different place inside its own border. */
.kanji-card .k-step {
  /* Anki's own button reset, undone - see the note above `.kanji-card *`. */
  margin: 0;
  box-shadow: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 1.9rem;
  height: 1.9rem;
  padding: 0;
  font: inherit;
  font-size: 0.85em;
  line-height: 1;
  color: var(--ink-3);
  background: none;
  border: 1px solid var(--rule);
  border-radius: 0.35rem;
  cursor: pointer;
}
.kanji-card .k-step svg { width: 1.15em; height: 1.15em; display: block; }
/* Both icons ship in the play button and CSS picks one, so the swap costs no
   layout and the button never briefly has no icon at all. */
.kanji-card .k-step .k-ico-pause { display: none; }
.kanji-card .k-step.k-step-playing .k-ico-play { display: none; }
.kanji-card .k-step.k-step-playing .k-ico-pause { display: block; }
.kanji-card .k-step:hover { color: var(--accent); border-color: var(--accent); }
.kanji-card .k-step-on { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }

.k-identity { flex: 1 1 auto; min-width: 0; }

/* Vietnamese edition only. Set at a supporting size it read as a label above the
   meaning; it is not a label, it is half of what the card is teaching - the reading
   a Vietnamese reader already half knows and is here to attach to a shape. Sized
   just under the meaning, which keeps the meaning the heading of the block. */
.k-hanviet {
  font-size: clamp(1.2rem, 4.4vw, 1.55rem);
  font-weight: 600;
  letter-spacing: 0.03em;
  line-height: 1.2;
  color: var(--accent);
  margin-bottom: 0.15rem;
}

.k-meaning {
  font-size: clamp(1.25rem, 4.5vw, 1.6rem);
  line-height: 1.25;
  font-weight: 600;
  text-wrap: balance;
}

.k-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin-top: 0.6rem;
}

.k-pill {
  font-size: 0.7em;
  letter-spacing: 0.05em;
  padding: 0.15rem 0.5rem;
  border: 1px solid var(--rule);
  border-radius: 999px;
  color: var(--ink-2);
  white-space: nowrap;
}
.k-pill-muted { color: var(--ink-3); }


/* --------------------------------------------------------------------- blocks */

/* One rule per section, and it is the one attached to the label. The block used to
   carry a border of its own as well, so every heading arrived under two lines. */
.k-block { padding-top: clamp(0.5rem, 1.6vw, 0.8rem); }

.k-label {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 0 0 0.55rem;
  font-size: 0.68em;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.k-label::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--rule);
}

.k-readings {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.3rem 0.9rem;
  margin: 0;
  align-items: baseline;
}
.k-readings dt {
  font-size: 0.68em;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.k-readings dd {
  margin: 0;
  font-family: "Yu Gothic UI", "Yu Gothic", "Hiragino Kaku Gothic ProN", Meiryo,
    "Noto Sans JP", sans-serif;
  font-size: 1.05em;
  overflow-wrap: anywhere;
}

/* The pre-1946 shape of the same character, set in the serif the character itself
   uses: it is a glyph being shown, not a word being read. */
.k-old-form {
  font-family: "Yu Mincho", "Hiragino Mincho ProN", "MS Mincho", serif;
  font-size: 1.35em;
  line-height: 1.2;
}

.k-chips { display: flex; flex-wrap: wrap; gap: 0.45rem; }
.k-chip {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.25rem 0.6rem 0.25rem 0.45rem;
  border: 1px solid var(--rule);
  border-radius: 0.45rem;
  background: var(--sunk);
  max-width: 100%;
}
.k-chip b {
  font-family: "Yu Mincho", "Hiragino Mincho ProN", "MS Mincho", serif;
  font-size: 1.35em;
  font-weight: 400;
  line-height: 1;
}
.k-chip span {
  font-size: 0.78em;
  color: var(--ink-2);
  line-height: 1.35;
  overflow-wrap: anywhere;
}
/* The component that is also the radical: marked, not captioned. */
.k-chip-radical { border-color: var(--accent); background: var(--accent-soft); }
.k-chip-radical b { color: var(--accent); }

/* The component the reading comes from. Underlined rather than filled: a chip can
   be both this and the radical - 田 in 界 is neither, 半 in 伴 is only this, 言 in
   語 is both - and two backgrounds cannot occupy the same chip. An underline sits
   on top of whatever the radical did to it. */
.k-chip-phon b { text-decoration: underline; text-decoration-style: dotted;
                 text-underline-offset: 0.22em; text-decoration-thickness: 1px; }

/* Shown only when _kanji.js did not run: the raw field, unstyled but readable. */
.k-fallback { font-size: 0.9em; color: var(--ink-2); }

.k-story {
  margin: 0 0 0.5rem;
  padding: 0.55rem 0.75rem;
  background: var(--accent-soft);
  border-radius: 0.45rem;
  font-size: 0.92em;
}
.k-story-alt { background: var(--sunk); color: var(--ink-2); }
/* The attribution Koohii's licence requires, reading as part of the sentence it
   belongs to rather than as a line under it. Quiet, but never absent. */
.k-story-by { color: var(--ink-3); }
.k-story-by a { color: var(--ink-3); text-decoration: none; border-bottom: 1px solid var(--rule); }
.k-story-by a:hover { color: var(--accent); border-color: var(--accent); }

/* Koohii's own emphasis, kept the way its readers already know it: the keyword in
   bold, each primitive that builds the character in italics, and a link to another
   character it points at. Restyling either would make the same mnemonic read
   differently here than on the site it came from. */
.k-story strong { font-weight: 600; }
.k-story em { font-style: italic; }
.k-story a { color: inherit; border-bottom: 1px solid var(--rule); text-decoration: none; }
.k-story a:hover { color: var(--accent); border-color: var(--accent); }

.k-vocab { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.5rem; }
.k-vocab-row {
  display: grid;
  grid-template-columns: minmax(0, auto) minmax(0, 1fr);
  gap: 0.3rem 0.85rem;
  align-items: baseline;
}
.k-vocab-word {
  font-family: "Yu Mincho", "Hiragino Mincho ProN", "MS Mincho", serif;
  font-size: 1.15em;
  white-space: nowrap;
}
.k-vocab-word rt {
  font-family: "Yu Gothic UI", "Yu Gothic", "Hiragino Kaku Gothic ProN", Meiryo,
    sans-serif;
  font-size: 0.48em;
  color: var(--ink-3);
}
.k-vocab-flag {
  /* The word beside it is set in a Japanese serif; without this the label would be
     too, and a Latin label in a Mincho face reads as part of the word. */
  font-family: -apple-system, "Segoe UI", system-ui, sans-serif;
  margin-left: 0.35rem;
  padding: 0 0.25rem;
  font-size: 0.62em;
  letter-spacing: 0.03em;
  line-height: 1.5;
  white-space: nowrap;
  color: var(--ink-3);
  border: 1px solid var(--rule);
  border-radius: 0.25rem;
  vertical-align: middle;
}

/* Beside the word, inside the first column, so the meanings still line up in the
   second - and so it stays beside the word on a phone too, where the row collapses
   to one column and anything of its own would land under it again. Under the word
   is where a meaning goes, and a reader coming down the list read it as one.
   Smaller and in the accent, set like the furigana above the word rather than like
   the meaning beside it, because that is what it is. */
.k-vocab-hv {
  font-family: -apple-system, "Segoe UI", system-ui, sans-serif;
  /* The same gap the grid puts between the word and the meaning. Tighter than this
     and the reading crowds the word it belongs to rather than standing beside it. */
  margin-left: 0.85rem;
  font-size: 0.62em;
  letter-spacing: 0.04em;
  line-height: 1.2;
  white-space: nowrap;
  color: var(--accent);
}

.k-vocab-meaning { font-size: 0.85em; color: var(--ink-2); line-height: 1.4; }

/* The one width breakpoint in this file: below it the card is a phone, above it the
   character sits beside its reading.
 *
 * It was 26rem = 416px, which is under several phones in portrait and left them on
 * the side-by-side layout:
 *
 *     360  Galaxy S23            390  iPhone 14/15
 *     402  iPhone 16 Pro         411  the phone this deck is tested on
 *     412  Pixel 7/8             430  iPhone Pro Max and Plus
 *     448  Pixel 8 Pro           480  Galaxy S24 Ultra
 *
 * 544px clears all of them with room to spare and is still well under a tablet in
 * portrait (768), so nothing that has space for two columns loses them. A desktop
 * window dragged narrower than 544px gets the phone layout, which is the right
 * answer rather than a side effect.
 *
 * Written in px on purpose. `rem` in a media query resolves against the initial
 * 16px and ignores the page's own root size - measured, with html{font-size:15px}
 * set, `(max-width: 26rem)` still matched at 410px - so rem here says nothing extra
 * and hides the number that matters. */
@media (max-width: 544px) {
  .k-vocab-row { grid-template-columns: 1fr; }

  /* On a phone the character is the card. Side by side it was capped at about a
     quarter of the width by the meaning next to it; stacked, it gets the room the
     thing being learned deserves. */
  .k-hero { flex-direction: column; align-items: center; text-align: center; }
  .k-stage { width: min(62vw, 15rem); }
  .k-identity { width: 100%; }
  .k-pills { justify-content: center; }
  .k-stroke-bar { justify-content: center; }

  /* On a phone the question and the answer show the same writing square, and the
     reader turns the card expecting the character to stay where it is. Centring the
     question in 60vh put it 176px lower than the answer's - measured at 390px wide:
     hero top 188px on the question, 12px on the answer - so turning the card jumped
     the character up by more than its own height.

     Only the recognition card. The recall card asks with a keyword and has no
     square to line up with, so it keeps the centring on every width. And only at
     this width: side by side on a desktop the answer's square sits in the top left
     with the reading beside it, there is nothing for the question to jump against,
     and a lone character centred in the card is the better page. */
  .kanji-front:not(.kanji-front-recall) {
    min-height: 0;
    justify-content: flex-start;
  }
  }

.kanji-card .k-more {
  /* Anki's own button reset, undone - see the note above `.kanji-card *`. */
  box-shadow: none;
  margin: 0.7rem 0 0;
  padding: 0.35rem 0.75rem;
  font: inherit;
  font-size: 0.75em;
  letter-spacing: 0.04em;
  color: var(--ink-2);
  background: none;
  border: 1px solid var(--rule);
  border-radius: 0.4rem;
  cursor: pointer;
}
.kanji-card .k-more:hover { color: var(--accent); border-color: var(--accent); }

.k-links { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.k-links a {
  font-size: 0.78em;
  letter-spacing: 0.04em;
  text-decoration: none;
  padding: 0.28rem 0.65rem;
  border: 1px solid var(--rule);
  border-radius: 0.4rem;
  color: var(--ink-2);
}
.k-links a:hover { color: var(--accent); border-color: var(--accent); }

/* ------------------------------------------------------------------ settings panel
 *
 * Quiet by design. It sits at the foot of the card and must not compete with the
 * character above it, so the button is the same weight as the credit line below and
 * only the chosen chip carries colour.
 */
.k-settings-slot { margin-top: 0.2rem; }

.kanji-card .k-set-btn {
  /* Anki's own button reset, undone - see the note above `.kanji-card *`. */
  margin: 0;
  box-shadow: none;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.25rem 0.6rem;
  font: inherit;
  font-size: 0.72em;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
  background: none;
  border: 1px solid var(--rule);
  border-radius: 0.4rem;
  cursor: pointer;
}
.kanji-card .k-set-btn::before { content: "\2699"; font-size: 1.15em; letter-spacing: 0; }
.kanji-card .k-set-btn:hover { color: var(--accent); border-color: var(--accent); }
.kanji-card .k-set-btn-on { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }

.k-set-panel {
  margin-top: 0.5rem;
  border: 1px solid var(--rule);
  border-radius: 0.5rem;
  background: var(--sunk);
  overflow: hidden;
}

.k-set-sec + .k-set-sec { border-top: 1px solid var(--rule); }

/* Grid, not wrapped flex. The item list spans the full width, and as a flex item
   at `flex: 1 1 100%` it pushed the chevron - the last item - onto a third line of
   its own, which was a whole empty row per section. Placed explicitly, the chevron
   sits on the label's row where it belongs. */
.kanji-card .k-set-head {
  /* Anki's own button reset, undone - see the note above `.kanji-card *`. */
  margin: 0;
  box-shadow: none;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 0.1rem 0.5rem;
  width: 100%;
  padding: 0.5rem 0.7rem;
  font: inherit;
  text-align: left;
  color: var(--ink);
  background: none;
  border: 0;
  cursor: pointer;
}
.kanji-card .k-set-head::after {
  content: "\203A";
  grid-column: 2;
  grid-row: 1;
  justify-self: end;
  color: var(--ink-3);
  transition: transform 0.15s ease;
}
.kanji-card .k-set-head[aria-expanded="true"]::after { transform: rotate(90deg); }
.kanji-card .k-set-head-name { grid-column: 1; grid-row: 1; font-size: 0.9em; font-weight: 600; }
/* Closed, a section says what is inside it - not what each one is set to, which
   would be a row of words with nothing to attach them to. */
.kanji-card .k-set-head-what {
  grid-column: 1 / -1;
  grid-row: 2;
  font-size: 0.72em;
  line-height: 1.4;
  color: var(--ink-3);
}
.kanji-card .k-set-head[aria-expanded="true"] .k-set-head-what { display: none; }

.k-set-body { padding: 0 0.7rem 0.6rem; }

.k-set-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.3rem 0.6rem;
  padding: 0.3rem 0;
}
.k-set-row + .k-set-row { border-top: 1px dashed var(--rule); }
.k-set-name { font-size: 0.82em; color: var(--ink-2); }

.k-set-opts { display: flex; flex-wrap: wrap; gap: 0.25rem; }
.k-set-opts-wide { flex: 1 1 100%; }

/* A colour is its own label. The name is still on the button for a screen reader
   and on hover, but a row of ten words says far less than a row of ten dots. */
.kanji-card .k-set-swatch {
  /* Anki's own button reset, undone - see the note above `.kanji-card *`. */
  font: inherit;
  margin: 0;
  box-shadow: none;
  /* 1.75rem with a 0.5rem gap: at 1.35rem and 0.25rem the ten of them were a strip
     of touching circles, and on a phone the wrong one got hit. */
  width: 1.75rem;
  height: 1.75rem;
  flex: 0 0 auto;
  padding: 0;
  border: 1px solid var(--rule);
  border-radius: 50%;
  background: var(--dot);
  cursor: pointer;
  position: relative;
}
.k-set-opts-swatch { gap: 0.5rem; }
.kanji-card .k-set-swatch:hover { transform: scale(1.12); }
.kanji-card .k-set-swatch:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
/* The chosen one is ringed, not filled. Filling its centre with the card's paper
   marked it clearly and hid the one thing the control is for: on a light ground the
   selected swatch was a white circle, whatever colour it stood for. A gap of paper
   and then a ring of ink reads on both grounds and leaves the colour alone. */
.kanji-card .k-set-swatch.k-set-on {
  box-shadow: 0 0 0 2px var(--paper), 0 0 0 3.5px var(--ink);
}

.kanji-card .k-set-opt {
  /* Anki's own button reset, undone - see the note above `.kanji-card *`. */
  margin: 0;
  box-shadow: none;
  padding: 0.15rem 0.5rem;
  font: inherit;
  font-size: 0.75em;
  line-height: 1.5;
  color: var(--ink-3);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 0.35rem;
  cursor: pointer;
}
.kanji-card .k-set-opt:hover { color: var(--accent); border-color: var(--accent); }
/* Scoped to the word chips. Unscoped, this rule sat after `.k-set-swatch` at the
   same specificity and repainted the selected colour swatch in `--accent-soft` -
   which is why the chosen accent showed as a near-white circle whatever it was. */
.kanji-card .k-set-opt.k-set-on {
  color: var(--accent);
  border-color: var(--accent);
  background: var(--accent-soft);
  font-weight: 600;
}

/* The version on the left, the way out on the right. `space-between` rather than a
   margin on the button, so the row still reads as one line when there is no version
   to show - an older build, or a card someone pasted the runtime into by hand. */
.k-set-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin: 0.1rem 0.7rem 0.6rem;
}

.k-set-ver {
  display: inline-flex;
  align-items: baseline;
  gap: 0.35rem;
  min-width: 0;
  font-size: 0.72em;
  color: var(--ink-3);
}

.k-set-ver-k { text-transform: uppercase; letter-spacing: 0.05em; }
.k-set-ver-v { font-family: inherit; color: var(--ink-2); }

.kanji-card .k-set-reset {
  /* Anki's own button reset, undone - see the note above `.kanji-card *`. */
  box-shadow: none;
  display: block;
  margin: 0;
  padding: 0.15rem 0.5rem;
  font: inherit;
  font-size: 0.72em;
  color: var(--ink-3);
  background: none;
  border: 1px solid var(--rule);
  border-radius: 0.35rem;
  cursor: pointer;
}
.kanji-card .k-set-reset:hover { color: var(--accent); border-color: var(--accent); }

/* The machine-written story is set like the others - it is a mnemonic, not a
   disclaimer - but its byline is the one that has no name in it, so it carries the
   quiet colour rather than the accent a link would take. */
.k-story-ai .k-story-by { color: var(--ink-3); }

.k-credit {
  margin: 0;
  padding-top: 0.6rem;
  border-top: 1px solid var(--rule);
  font-size: 0.68em;
  line-height: 1.5;
  color: var(--ink-3);
}

.k-error {
  margin-top: 0.75rem;
  padding: 0.5rem 0.7rem;
  border: 1px solid #b3382a;
  border-radius: 0.4rem;
  color: #b3382a;
  font-size: 0.8em;
}

.kanji-card :focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
