/* ---------- Tafel: Zeilen beliebig lang, Kreise schrumpfen mit der längsten Zeile ---------- */
/* Unter etwa 46px pro Platz wird nicht weiter geschrumpft, dann lässt sich die Tafel seitlich wischen */
.grid {
  --g: 6px; /* Abstand zwischen zwei Plätzen */
  --nw: 1.5rem; --mw: 2.7rem; /* Spalte vor den Plätzen: Breite der Zeilennummer, dazu die der Taktart */
  flex: 1; min-height: 0;
  min-width: calc(var(--nw) + var(--cols, 1) * 46px);
  padding: 14px 12px;
  display: grid;
  gap: 6px;
  /* 12rem: Platz für einen großen Kreis plus Längenzeichen und r/l darunter */
  grid-template-rows: repeat(var(--rows, 3), minmax(0, 12rem));
  align-content: start;
  touch-action: none;
}
.grid.wide { touch-action: pan-x; }
.row {
  display: grid;
  grid-template-columns: var(--nw) repeat(var(--cols, 1), minmax(0, 7rem));
  justify-content: start;
  grid-template-rows: minmax(0, 1fr);
  gap: var(--g);
  min-height: 0;
}
/* Die Spalte der Zeilennummer bleibt frei; die Nummer selbst sitzt im ersten Platz und steht von dort aus links
   in dieser Spalte, auf Höhe der Kreismitte (wie die Taktart) */
.rnum {
  position: absolute; right: calc(100% + var(--g)); top: calc(var(--d) / 2);
  width: var(--nw); transform: translateY(-50%); text-align: center;
  font: 700 .85rem var(--font-ui); color: var(--muted);
}
.grid.meters .rnum { right: calc(100% + var(--g) + var(--mw)); }
/* Üben und Spielen: große Nummern, damit man sie von weitem sieht und gut antippen kann (Welcher war's?) */
.app.practice .grid { --nw: 3.2rem; }
.app.practice .rnum { font-size: 1.9rem; font-weight: 800; color: var(--fg); }
/* Ein Tipp auf die Nummer klappt die Zeile ein; der Tippbereich ist größer als die Ziffer */
.rnum { cursor: pointer; }
.rnum::after { content: ""; position: absolute; inset: -.9rem -.4rem; }
.cell {
  container-type: size;
  position: relative;
  display: grid; place-items: center;
  min-width: 0; min-height: 0;
  cursor: pointer; border-radius: 14px;
}
/* Unter dem Kreis: Längenzeichen (Höhe .5 × Kreis), darunter r/l.
   --f ist der Anteil des Platzes, den der Kreis vorn bekommt (normal 1, also der ganze Platz),
   --sw diese Breite; --dq ist der Kreis, --d der Kreis dieses Platzes. */
.stack {
  --sw: calc(100cqw * var(--f, 1));
  --dq: max(24px, min(calc(var(--sw) * .84), calc((100cqh - 2.8rem) / 1.5)));
  --d: var(--dq);
  position: relative; z-index: 0;
  width: var(--sw);
  display: flex; flex-direction: column; align-items: center; gap: .25rem;
}
/* Breite nach Notenlänge: Jede Spalte ist eine Sechzehntel. Ein Schlag ist einen Kreis breit (vier Spalten zu ½ --L);
   steht in der Zeile auf diesem Schlag eine Achtel, ist er zwei Kreise breit (vier Spalten zu 1 --L).
   Jede Zeile bekommt ihre Spalten als --tpl aus dem Skript; --fr ist die Breite der längsten Zeile in --L.
   --L ist für alle Zeilen gleich, damit alle Kreise gleich groß sind: höchstens 3.5rem + 3px (ein Kreis also so breit
   wie sonst ein Platz mit Abstand), weniger, wenn die längste Zeile sonst nicht passt. Das Zeichen steht vorn in seinem Platz. */
.grid.prop { --g: 0px; min-width: calc(var(--nw) + var(--fr, 2) * 15px); }
.grid.prop .row { --L: min(3.5rem + 3px, (100% - var(--nw)) / var(--fr, 2)); grid-template-columns: var(--nw) var(--tpl); }
.grid.prop.meters { min-width: calc(var(--nw) + var(--mw) + var(--fr, 2) * 15px); }
.grid.prop.meters .row { --L: min(3.5rem + 3px, (100% - var(--nw) - var(--mw)) / var(--fr, 2)); grid-template-columns: calc(var(--nw) + var(--mw)) var(--tpl); }
.grid.prop .cell { justify-items: start; }
/* Achtel im geteilten Feld (Rhythmus): das Zeichen ist so groß wie sonst und steht mittig über seiner halben Spalte;
   der Balken reicht nur bis zur nächsten Achtel (eine halbe Stapelbreite) */
/* Das Zeichen ist doppelt so breit wie der halbe Platz und ragt auf beiden Seiten gleich weit hinaus. Mit justify-items:
   center ginge das nicht: Die Spalte im Platz wächst mit dem Zeichen, und es stünde eine halbe Spalte zu weit rechts
   (das zweite Achtel eines Paars dann genau auf dem Taktstrich danach). */
.grid.prop .cell.half .stack { --bx: calc((var(--sw) - 100cqw) / 2); margin-left: calc(0px - var(--bx)); }
/* ein leerer halber Platz (nach einer einzelnen Achtel) bekommt einen kleineren Kreis, damit er den nächsten nicht überdeckt */
.grid.prop .cell.half .dot.ghost { transform: scale(.5); }
/* Rhythmus: Notenzeichen größer (Rahmen 1,2 × Kreis statt .8; der Kopf bei 24.6/30 bleibt auf der Linie), Pausen
   ebenso; die Balken entsprechend: Halsmitte .12 rechts, Hals .03 breit, Halsende .382 über dem Kreis, Balken .126 dick */
.grid.rhy .dot.beat .sym { height: calc(var(--d) * 1.2); top: calc(var(--d) * -.484); }
/* Die Hälse ragen bis .48 Kreise über den Kreis hinaus: so viel Platz bekommt jedes Zeichen oben dazu (und der Kreis
   wird so viel kleiner, dass es trotzdem in die Zeile passt). Sonst stießen sie in der ersten Zeile an den Rand der Tafel. */
.grid.rhy .stack { --dq: max(24px, min(calc(var(--sw) * .84), calc((100cqh - 2.8rem) / 2))); margin-top: calc(var(--d) * .5); }
.grid.rhy .dot.rest { --rh: calc(var(--d) * 1.05); }
.grid.rhy .stack.bbeam::after { left: calc(50% + var(--d) * .105); top: calc(var(--d) * -.382); width: calc(100% * var(--bw, 1) + var(--g) + var(--d) * .03); height: calc(var(--d) * .126); }
/* Zweiter Balken der Sechzehntel, parallel zum ersten (ein dreiviertel Linienabstand des Lieds zum Kopf hin versetzt):
   s1 bis zur nächsten Sechzehntel, s3 kurzer Ansatz nach rechts, s4 nach links (einzelne Sechzehntel neben Achteln) */
.grid.rhy .bm2 {
  position: absolute; left: calc(50% + var(--d) * .105); top: calc(var(--d) * -.193);
  width: calc(100% * var(--bw, 1) + var(--d) * .03); height: calc(var(--d) * .126); background: var(--fg);
}
.grid.rhy .bm2.s3 { width: calc(var(--d) * .3); }
.grid.rhy .bm2.s4 { left: calc(50% + var(--d) * -.165); width: calc(var(--d) * .3); }
.cell.quiz .bm2, .cell.ahead .bm2 { visibility: hidden; }
.len {
  position: relative; width: 100%; height: calc(var(--d) * .5);
  display: flex; justify-content: center; color: var(--fg);
}
/* Rhythmussprache unter eigenständigen Notenzeichen (ta, ti-ti, taja …) */
.len .syl { align-self: center; white-space: nowrap; font: 700 calc(var(--d) * .3)/1 var(--font-display); color: var(--fg); }
/* Farbfeld hinter einer Silbengruppe: von der Mitte des Zeichens bis --w Platzbreiten weiter. Die Farbe zeigt den
   Notenwert (durchscheinend, damit es auf heller und dunkler Tafel passt). */
.len .sgrp {
  position: absolute; z-index: -1; top: calc(50% - var(--d) * .21); left: calc(50% - var(--d) * .3);
  width: calc(100cqw * var(--w) + var(--d) * .6); height: calc(var(--d) * .42);
  border-radius: calc(var(--d) * .21); background: rgba(247, 209, 30, .4);
}
.len .sgrp.d025 { background: rgba(236, 72, 153, .26); } /* Sechzehntel: pink */
.len .sgrp.d05 { background: rgba(90, 160, 240, .32); } /* Achtel: blau */
.len .sgrp.d15 { background: rgba(40, 180, 170, .3); } /* punktierte Viertel: türkis */
.len .sgrp.d2 { background: rgba(120, 200, 80, .36); }  /* Halbe: grün */
.len .sgrp.d3 { background: rgba(160, 110, 220, .3); }  /* punktierte Halbe: lila */
.len .sgrp.d4 { background: rgba(245, 138, 31, .34); }  /* Ganze: orange */
/* auf die Schläge verteilt: --t ist der Abstand als Anteil des Platzes (wie bei den gehaltenen Zählzeiten) */
.len .syl.at { position: absolute; top: 50%; left: calc(50% + 100cqw * var(--t)); transform: translate(-50%, -50%); }
/* Notenzeichen im Menü ausgeschaltet: Zeile ausblenden, Kreise und Zeilen wieder wie ohne Zeichen */
.grid.nolen { grid-template-rows: repeat(var(--rows, 3), minmax(0, 8.75rem)); }
.grid.nolen .stack { --dq: max(24px, min(calc(var(--sw) * .84), calc(100cqh - 2.6rem))); }
.grid.nolen .len { display: none; }
/* Zählzeiten unter dem Notenzeichen; gehaltene Zählzeiten blasser. Nur wenn es welche gibt, bekommt die Zeile Platz dafür. */
.zz {
  position: relative; width: 100%;
  display: none; justify-content: center; align-items: center; gap: .45em;
  height: calc(var(--d) * .36); white-space: nowrap;
  font: 700 calc(var(--d) * .3)/1 var(--font-display); color: var(--fg);
}
.zz.many { font-size: calc(var(--d) * .22); }
.zz .held { color: var(--muted); }
/* Breite nach Notenlänge: gehaltene Zählzeiten stehen an ihrer Stelle, --t ist der Abstand als Anteil des Platzes */
.zz .at { position: absolute; left: calc(50% + 100cqw * var(--t)); transform: translateX(-50%); }
.grid.counts .zz { display: flex; }
.grid.counts { grid-template-rows: repeat(var(--rows, 3), minmax(0, 13.5rem)); }
.grid.counts .stack { --dq: max(24px, min(calc(var(--sw) * .84), calc((100cqh - 3.05rem) / 1.86))); }
.grid.counts.nolen { grid-template-rows: repeat(var(--rows, 3), minmax(0, 10rem)); }
.grid.counts.nolen .stack { --dq: max(24px, min(calc(var(--sw) * .84), calc((100cqh - 2.8rem) / 1.36))); }
/* Notenlinie: läuft auf Höhe der Kreismitte vom ersten bis zum letzten Zeichen, hinter den Kreisen */
.cell[class*="line-"] .stack::before {
  content: ""; position: absolute; z-index: -1;
  /* je 1px mehr als die halbe Lücke, damit sich die Stücke überlappen und beim Runden keine Haarlinie bleibt */
  /* dünn, damit das Loch halber und ganzer Noten frei bleibt */
  /* --bx: so weit ragt das Zeichen einer Achtel links über ihren Platz hinaus, um so viel rückt die Linie zurück */
  top: calc(var(--d) / 2 - .75px); height: 1.5px; left: calc(var(--bx, 0px) + var(--g) / -2 - 1px);
  right: calc(var(--g) / -2 - 1px - (100cqw - var(--sw)) - var(--bx, 0px)); /* bis zum Ende des Platzes, auch hinter dem Kreis */
  background: var(--fg);
}
.cell.line-first .stack::before { left: 50%; }
.cell.line-last .stack::before { right: 50%; }
.cell.line-one .stack::before { left: 10%; right: 10%; }
/* Taktart: zwei Zahlen übereinander vor dem ersten Platz, die Notenlinie läuft zwischen ihnen hindurch.
   Steht irgendwo eine Taktart, wird die Spalte vor den Plätzen in allen Zeilen breiter, damit sie untereinander bleiben. */
.grid.meters { min-width: calc(var(--nw) + var(--mw) + var(--cols, 1) * 46px); }
.grid.meters .row { grid-template-columns: calc(var(--nw) + var(--mw)) repeat(var(--cols, 1), minmax(0, 7rem)); }
.grid.meters .rownum { justify-self: start; width: var(--nw); }
.meter {
  position: absolute; right: calc(100% + var(--g) + .35rem); top: calc(var(--d) / 2);
  transform: translateY(-50%); color: var(--fg);
}
.meter .mtr { font-size: calc(var(--d) * .42); gap: calc(var(--d) * .08); }
.cell.has-meter.line-first .stack::before,
.cell.has-meter.line-one .stack::before { left: calc(0px - var(--g) - 2.6rem); }
/* Taktstrich in der Lücke vor dem Platz, so hoch wie Kreis und Notenzeichen. --bx: wie weit das Zeichen links über
   seinen Platz hinausragt (Achtel im geteilten Feld, siehe .half); um so viel rückt der Strich zurück an den Platz */
.barline {
  position: absolute; left: calc(var(--bx, 0px) + var(--g) / -2 - 1.5px); top: calc(var(--d) * -.2);
  height: calc(var(--d) * 1.6); width: 3px; border-radius: 2px; background: var(--fg);
}
.grid.nolen .barline { height: calc(var(--d) * 1.4); }
/* hinter dem Platz (Ende einer vollen Zeile) */
.barline.after { left: auto; right: calc(var(--sw) - var(--bx, 0px) - 100cqw - var(--g) / 2 - 1.5px); }
/* Schlussstrich: dünner und dicker Strich, der dicke direkt vor dem Platz */
.barline.final {
  left: calc(var(--bx, 0px) + var(--g) / -2 - 6px); width: 9px; border-radius: 0; background: none;
  border-left: 2px solid var(--fg); border-right: 5px solid var(--fg);
}
/* Wiederholung: Anfang ‖: (dicker Strich zuerst, Punkte rechts), Ende :‖ (wie der Schlussstrich, Punkte links),
   beides :‖: (dicker Strich in der Mitte, Punkte auf beiden Seiten). Die Punkte sitzen über und unter der Notenlinie. */
.barline.rep-start { border-left-width: 5px; border-right-width: 2px; }
.barline.rep-end.rep-start { left: calc(var(--bx, 0px) + var(--g) / -2 - 7px); width: 14px; border-left-width: 2px; border-right-width: 2px;
  background: linear-gradient(90deg, transparent 3px, var(--fg) 3px, var(--fg) 8px, transparent 8px); }
.barline.rep-end::before, .barline.rep-start::after {
  content: ""; position: absolute; top: calc(var(--d) * .48); width: 6px; height: 6px; border-radius: 50%;
  background: var(--fg); z-index: 1;
  /* zweiter Punkt darunter; beide mit schmalem Rand in Tafelfarbe, damit sie sich von bunten Kreisen abheben */
  box-shadow: 0 0 0 2px var(--board), 0 calc(var(--d) * .28) 0 0 var(--fg), 0 calc(var(--d) * .28) 0 2px var(--board);
}
.barline.rep-end::before { right: calc(100% + 3px); }
.barline.rep-start::after { left: calc(100% + 3px); }
/* Eigenständiges Notenzeichen statt Punkt: Notenkopf sitzt auf der Kreismitte (also auf der Notenlinie) */
.dot.beat { position: relative; background: none; box-shadow: none; color: var(--fg); }
.dot.beat .sym {
  position: absolute; left: 50%; top: calc(var(--d) * -.156);
  height: calc(var(--d) * .8); transform: translateX(-50%);
}
.cell.sel .dot.beat { box-shadow: 0 0 0 3px var(--board), 0 0 0 6px var(--ring); }
.grid.clean .cell.sel .dot.beat { box-shadow: none; }
/* Balken zweier eigenständiger Achtel (Zeichen wie im Lied): Halsmitte .08 × Kreis rechts der Mitte, Hals .02 breit,
   Halsende .088 über dem Kreis; der Balken ist .084 dick (ein halber Linienabstand des Lieds) */
.stack.bbeam::after {
  content: ""; position: absolute;
  left: calc(50% + var(--d) * .07); top: calc(var(--d) * -.088);
  width: calc(100% * var(--bw, 1) + var(--g) + var(--d) * .02); height: calc(var(--d) * .084);
  background: var(--fg);
}
/* Balken von Hals zu Hals zweier Achtel unter bunten Punkten (Zeichen .5 × Kreis hoch): Halsmitte .05 × Kreis rechts der
   Mitte, Hals .0126 breit, Halsende .0425 unter der Oberkante; Balken .0525 dick */
.len.beam::after {
  content: ""; position: absolute;
  left: calc(50% + var(--d) * .0437); top: calc(var(--d) * .0425);
  width: calc(100% * var(--bw, 1) + var(--g) + var(--d) * .0126); height: calc(var(--d) * .0525);
  background: currentColor;
}
.dot {
  width: var(--d); aspect-ratio: 1; border-radius: 50%;
  background: var(--c); color: #000;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  font-family: var(--font-display); font-weight: 700;
  font-size: calc(var(--d) * .5); line-height: 1;
  box-shadow: inset 0 calc(var(--d) * -.05) 0 rgba(0, 0, 0, .16);
  transition: transform .12s ease;
}
.dot.ghost {
  background: transparent; border: 3px dashed var(--line); box-shadow: none;
}
/* Pausen ohne Kreis direkt auf der Notenlinie (Höhe der Kreismitte). Das Zeichen ist --rh hoch, sein Rahmen
   30 Einheiten; die Linie, an der die Pause steht, liegt im Rahmen bei 15 (siehe symbols.js). */
.dot.rest { --rh: calc(var(--d) * .8); position: relative; background: none; box-shadow: none; color: var(--fg); }
.dot.rest .sym {
  position: absolute; left: 50%; transform: translateX(-50%);
  height: var(--rh); top: calc(50% - var(--rh) * 15 / 30);
}
.cell.sel .dot.rest { box-shadow: 0 0 0 3px var(--board), 0 0 0 6px var(--ring); }
.grid.clean .cell.sel .dot.rest { box-shadow: none; }
/* Plätze hinter dem Zeilenende nur blass, damit man sieht, wo die Zeile aufhört */
.cell.beyond:not(.sel) .dot.ghost { opacity: .4; }
/* Buchstabe des Tons (auf der Tafel und in der Leiste) */
.sharp { font-size: .6em; vertical-align: .55em; margin-left: .03em; }
.up .ltr { font-size: .9em; }
.arr { width: .46em; height: .46em; margin-bottom: -.02em; }
.hand {
  height: 2.3rem; min-width: 3rem; padding-inline: .6rem;
  font: 700 1.7rem/1.8rem var(--font-display);
  text-align: center; border-radius: 999px; border: 3px solid transparent;
}
/* r gefüllt, l nur umrandet – so lassen sich beide auch von weitem unterscheiden */
.hand.r { background: var(--fg); border-color: var(--fg); color: var(--board); }
.hand.l { background: var(--board); border-color: var(--fg); color: var(--fg); }
.cell.sel .dot {
  box-shadow: inset 0 calc(var(--d) * -.05) 0 rgba(0, 0, 0, .16), 0 0 0 3px var(--board), 0 0 0 6px var(--ring);
}
.cell.sel .dot.ghost { border-color: var(--ring); border-style: solid; box-shadow: 0 0 0 3px var(--board), 0 0 0 6px var(--ring); }
/* Im Einfügen-Modus zeigt ein Balken links an, dass der Ton vor diesem Platz landet */
.grid.inserting:not(.clean) .cell.sel::before {
  content: ""; position: absolute; left: -5px; top: 10%; bottom: 10%;
  width: 4px; border-radius: 2px; background: var(--ring);
}
/* „Fertig“: Markierung und leere Plätze ausblenden, nur die Töne bleiben */
.grid.clean .dot.ghost { visibility: hidden; }
.grid.clean .cell.sel .dot { box-shadow: inset 0 calc(var(--d) * -.05) 0 rgba(0, 0, 0, .16); }
/* Beim Abspielen: der klingende Platz leuchtet als farbiger Balken über die ganze Zeilenhöhe, das Zeichen wird größer */
.cell.playing { background: var(--play-bg); box-shadow: 0 0 0 4px var(--play-bg); }
.cell.playing .dot:not(.ghost) { transform: scale(1.22); }
/* Noten mit Hals wachsen vom Halsende aus (am Balken bleibt er so dran), nur der Kopf wird größer; die Ganze von der Mitte */
.cell.playing .dot.beat.stem { transform-origin: calc(50% + var(--d) * .08) calc(var(--d) * -.088); }
.grid.rhy .cell.playing .dot.beat.stem { transform-origin: calc(50% + var(--d) * .12) calc(var(--d) * -.382); }
.cell.lifting { opacity: .3; }
.cell.drop .dot { transform: scale(1.08); }
.dot.dragging {
  position: fixed; left: 0; top: 0; z-index: 60; pointer-events: none;
  box-shadow: 0 14px 28px rgba(0, 0, 0, .35); transition: none;
}

@media (max-width: 600px) { /* nur Handys; ein iPad (ab 768 px) behält die Leiste an der Seite */
  .boardwrap { height: min(62vh, 520px); min-height: 340px; }
}
@media (prefers-reduced-motion: reduce) {
  .dot { transition: none; }
}

/* ---------- Verdecken ---------- */
/* Eingeklappte Zeile: behält ihre Höhe, damit nichts verrutscht. Zu sehen ist nur ihre Nummer als kleiner Knopf mit
   Pfeil und eine feine Linie auf Höhe der Kreise; ein Tipp irgendwo darauf klappt sie wieder auf */
.row.folded { cursor: pointer; touch-action: manipulation; }
.row.folded .stack, .row.folded .cell .qcard { visibility: hidden; }
.row.folded .stack > .rnum { visibility: visible; }
.row.folded .rnum {
  display: inline-flex; align-items: center; gap: 2px;
  width: auto; min-width: 1.5rem; padding: 2px 6px 2px 8px; border-radius: 999px;
  background: var(--btn); border: 2px solid var(--btn-line); white-space: nowrap;
}
.row.folded .rnum::before { content: "▸"; order: 1; }
/* Der Knopf beginnt, wo sonst die Nummer steht, und wächst nach rechts über den (leeren) ersten Platz */
.row.folded .rnum { right: auto; left: calc(var(--bx, 0px) - var(--nw) - var(--g)); }
.grid.meters .row.folded .rnum { left: calc(var(--bx, 0px) - var(--nw) - var(--mw) - var(--g)); }
.row.folded .cell .stack::before {
  content: ""; visibility: visible; position: absolute; z-index: -1;
  top: calc(var(--d) / 2 - 1px); height: 2px; background: var(--btn-line);
  /* je 1px über die halbe Lücke hinaus, damit die Stücke ohne Spalt aneinanderstoßen (wie bei der Notenlinie);
     --bx: so weit ragt das Zeichen einer Achtel links über ihren Platz hinaus, um so viel rückt die Linie zurück */
  left: calc(var(--bx, 0px) + var(--g) / -2 - 1px); right: calc(var(--g) / -2 - 1px - (100cqw - var(--sw)) - var(--bx, 0px));
}
/* Mit Taktart beginnt die Linie gleich hinter dem Knopf */
.row.folded .cell.has-meter .stack::before { left: calc(var(--bx, 0px) - var(--g) - 2.6rem); }
/* Rhythmus-Echo, noch nicht aufgelöst: nur Notenlinie, Taktart, Takt- und Schlussstriche; bei jedem Schlag, der
   erklingt, blinkt die Zeile kurz */
.row.blank .dot, .row.blank .len, .row.blank .zz, .row.blank .hand { visibility: hidden; }
.row.blank .cell { pointer-events: none; }
.row.blank.beat { animation: blankbeat .18s ease-out; }
@keyframes blankbeat { 0% { background-color: var(--play-bg); } }
@media (prefers-reduced-motion: reduce) { .row.blank.beat { animation: none; } }
/* Das Tuch liegt in den Rasterzeilen ab seiner Zeile über allem */
.grid > .cloth { grid-column: 1; }
/* ?-Karte: verdeckt liegt sie über dem Kreis (Zeichen, Notenwert und Hand sind ausgeblendet) */
.cell.quiz .stack, .cell.ahead .stack { visibility: hidden; }
.cell.quiz .stack > .rnum, .cell.quiz .stack > .meter, .cell.quiz .stack > .barline,
.cell.ahead .stack > .rnum, .cell.ahead .stack > .meter { visibility: visible; }
.cell .qcard { position: absolute; left: 50%; top: 0; z-index: 2; width: calc(var(--d) * 1.05); height: calc(var(--d) * 1.2); transform: translate(-50%, calc(var(--d) * -.1)); font-size: calc(var(--d) * .7); visibility: visible; }
.cell.ahead .qcard { visibility: hidden; }
/* Die Notenlinie läuft unter Karten und ausgeblendeten Zeichen weiter */
.cell.quiz .stack::before, .cell.ahead .stack::before { visibility: visible; }
/* Rhythmus: die Karte liegt genau über dem Notenzeichen, vom Ende des Halses (dort auch der Balken) bis unter den
   Notenkopf; das Zeichen reicht von der Mitte aus gemessen von −.19 bis +.13 und von −.38 bis +.63 Kreisgrößen.
   Pausen stehen mittig auf der Linie und sind breiter. */
.grid.rhy .cell .qcard { left: calc(50% - var(--d) * .24); top: calc(var(--d) * -.43); width: calc(var(--d) * .42); height: calc(var(--d) * 1.11);
  transform: none; border-radius: calc(var(--d) * .1); font-size: calc(var(--d) * .34); }
.grid.rhy .cell .dot.rest ~ .qcard { left: calc(50% - var(--d) * .18); top: calc(var(--d) * .12); width: calc(var(--d) * .36); height: calc(var(--d) * .75); }
/* Balken an einem verdeckten Achtel: nur die Hälfte bis zur Grenze der beiden halben Plätze (75 % bzw. 25 % des Zeichens,
   das doppelt so breit ist wie sein Platz) bleibt; die andere liegt unter der Karte bzw. fehlt mit dem verdeckten Achtel */
.grid.rhy.prop .cell.half .stack.bbeam.bhalf::after { width: calc(50% * var(--bw, 1) - var(--d) * .105); }
.grid.rhy .hbeam { position: absolute; left: 25%; top: calc(var(--d) * -.382); width: calc(25% + var(--d) * .135); height: calc(var(--d) * .126); background: var(--fg); }

/* ---------- Tonnamen-Quiz: großer Farbpunkt über der Tafel ---------- */
.qfarb { display: flex; flex-direction: column; align-items: center; gap: 14px; }
.qdot { --d: min(38vh, 240px); }
/* Andersherum gefragt: der Buchstabe auf einem Punkt ohne Farbe */
.dot.plain { background: var(--board); color: var(--fg); box-shadow: inset 0 0 0 calc(var(--d) * .05) var(--btn-line); }
.qname { margin: 0; font: 700 2.4rem/1 var(--font-display); color: var(--fg); }
/* Höher oder tiefer?: die Frage, darunter zwei Punkte nebeneinander; der klingende leuchtet */
.qask { margin: 0; font: 800 1.5rem/1.2 var(--font-ui); color: var(--fg); text-align: center; }
.qpair { display: flex; gap: min(8vw, 80px); }
.qpair .qdot { --d: min(30vh, 190px); transition: transform .15s ease; }
.qpair .qdot.on { transform: scale(1.12); box-shadow: inset 0 0 0 calc(var(--d) * .05) var(--btn-line), 0 0 0 12px var(--play-bg); }
/* Spiele: Ist die Frage gelöst, spielen die Zeilennummern ihre Zeile ab (umrandet wie ein Knopf). Welcher war's?: die
   richtige Nummer grün, falsch getippte rot */
.boardwrap.rowplay .rnum, .rnum.ok, .rnum.bad { width: var(--nw); height: var(--nw); line-height: var(--nw); border-radius: 50%; }
.boardwrap.rowplay .rnum { line-height: calc(var(--nw) - 6px); border: 3px solid currentColor; color: var(--fg); }
.boardwrap .rnum.ok { background: var(--ok); border-color: var(--ok); color: #fff; }
.boardwrap .rnum.bad { background: var(--bad); border-color: var(--bad); color: #fff; }
