/* ===== S3 App-Bereich ===== */
#app{padding:52px 0 8px;scroll-margin-top:76px}
.apphead{display:flex;align-items:center;gap:22px;margin-bottom:18px;flex-wrap:wrap}
.apphead .head{flex:1;min-width:260px}
.apphead h2{font-size:clamp(1.7rem,2.4vw,2.1rem);color:var(--maroon)}
.apphead p{color:var(--ink-2);font-size:15px;max-width:560px}
.ring-wrap{display:flex;align-items:center;gap:14px;background:var(--card);
  border:1px solid var(--line);border-radius:var(--r);padding:14px 18px;box-shadow:var(--shadow);flex-wrap:wrap;min-width:340px}
.ring{position:relative;width:74px;height:74px;flex:none}
.ring svg{transform:rotate(-90deg)}
.ring .pct{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  font-weight:800;font-size:18px;color:var(--maroon)}
.ring-meta .rm1{font-weight:700;font-size:14px}
.ring-meta .rm2{font-size:12.5px;color:var(--ink-2)}
#rankRow{display:flex;gap:7px;flex-basis:100%;margin-top:6px}
.rankpill{flex:1;display:flex;align-items:center;gap:7px;background:var(--bg-2);border:1px solid var(--line);border-radius:9px;padding:6px 8px}
.rankpill.next{box-shadow:0 0 0 2px rgba(201,154,59,.4)}
.rankpill.done{background:var(--gold-bg);border-color:var(--gold-soft)}
.rankpill .rg{width:24px;height:24px;flex:none;position:relative;display:flex;align-items:center;justify-content:center}
.rankpill:not(.done) .rg{opacity:.78}
.rankpill .rg .rgem{font-size:15px}
.rankpill .rg img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain}
.rankpill .rb{flex:1;min-width:0}
.rankpill .rbt{display:flex;justify-content:space-between;font-size:10.5px;color:var(--ink-2);line-height:1.3}
.rankpill .rbt b{color:var(--ink);font-weight:700}
.rankpill .rbar{height:5px;border-radius:3px;background:rgba(0,0,0,.08);margin-top:3px;overflow:hidden}
.rankpill .rbar i{display:block;height:100%;border-radius:3px;transition:width .6s var(--ease)}
.rankpill.pop{animation:rankpop .55s ease}
@keyframes rankpop{0%{transform:scale(1)}40%{transform:scale(1.07)}100%{transform:scale(1)}}

/* Import-Banner */
.import{display:flex;align-items:center;gap:12px;margin:0 0 22px;
  background:linear-gradient(100deg,#fbf2e0,#f8eef4);border:1px solid var(--gold-soft);
  border-radius:var(--r);padding:12px 16px;box-shadow:var(--shadow);animation:rise .5s ease both}
.import .sp{width:30px;height:30px;border-radius:9px;background:#fff;display:flex;align-items:center;justify-content:center;font-size:16px;flex:none;box-shadow:var(--shadow)}
.import .txt{flex:1;font-size:13.5px;color:var(--ink)}
.import .txt b{color:var(--maroon)}
.import .x{cursor:pointer;color:var(--ink-2);font-size:18px;line-height:1;padding:4px 8px;border-radius:8px;border:none;background:none;font-family:inherit}
.import .x:hover{background:rgba(0,0,0,.05);color:var(--ink)}

/* Layout */
/* minmax(0,…) auf BEIDEN Spalten (Dom 13.08.): ohne das darf keine der beiden unter ihren
   Inhalt schrumpfen — ein einziger überlanger Etappen-Titel im Plan zog die linke Spalte
   auf und quetschte das Chat-Fenster daneben zusammen. Mit minmax(0,…) bleibt das
   Verhältnis 1,62:1 stehen, egal wie lang ein Titel wird; gekürzt wird dann INNEN. */
.grid{display:grid;grid-template-columns:minmax(0,1.62fr) minmax(0,1fr);gap:22px;align-items:start}
body.view-plan #flokiCol{display:none}
body.view-floki #planCol{display:none}
body.view-plan .grid,body.view-floki .grid{grid-template-columns:minmax(0,1fr)}
body.view-floki .floki{position:static;max-width:680px;margin:0 auto;max-height:none;
  transition:max-width .18s}
/* Breite Fassung (Dom 03.09.2026): Graphen bekommen Platz zum Ziehen und Skalieren.
   96vw statt 100 %, damit an den Raendern Luft bleibt; 1180 px ist die Grenze, ab der
   Fliesstext unangenehm lang wird. */
body.view-floki.chat-breit .floki{max-width:min(1180px,96vw)}
body.view-floki.chat-breit .c4u-graph{max-width:100%}
/* Vergroessern-Knoepfe an den Panels (Dom 03.09.2026). Sie ersetzen die drei Reiter
   „Beides / Lernplan / Floki": die Entscheidung faellt dort, wo man sie trifft.
   Sichtbar in `both` (dann heissen sie „gross machen") und in der jeweils eigenen
   Einzelansicht (dann „wieder kleiner"). In der ANDEREN Einzelansicht ist das Panel
   ausgeblendet — dort gibt es auch keinen Knopf. */
.panel-gross{display:none;align-items:center;justify-content:center;
  min-width:34px;min-height:34px;border-radius:9px;cursor:pointer;
  border:1px solid rgba(255,255,255,.28);background:rgba(255,255,255,.10);color:#fff;
  font-size:15px;line-height:1;transition:background .15s,border-color .15s}
body.view-both #chatGross,body.view-floki #chatGross{display:inline-flex;margin-left:auto}
.panel-gross:hover{background:rgba(255,255,255,.20)}
.panel-gross:focus-visible{outline:3px solid #fff;outline-offset:2px}
/* Der Lernplan hat keine farbige Kopfzeile — sein Knopf schwebt in der Ecke und traegt
   deshalb die Papierfarben statt der weissen Kontur. */
/* Platz fuer den Knopf, der oben aus der Spalte herausragt. */
#planCol{position:relative;margin-top:13px}
/* Der Knopf sitzt AUF der Kante der ersten Karte, nicht in ihr: bei top:10px stand er
   ueber einer Tagesaufgabe (Dom-Fund 03.09.2026 „kollidiert fast mit einer tagesaufgabe").
   Jetzt liegt er in der Luecke darueber und laesst der Karte ihren Platz. */
body.view-both #planGross,body.view-plan #planGross{display:inline-flex;
  position:absolute;top:-13px;right:-4px;z-index:5;
  border-color:var(--line,#ecdfdb);background:var(--card,#fff);color:var(--maroon,#6b1a1a);
  box-shadow:0 3px 10px rgba(60,30,20,.14)}
#planGross:hover{background:var(--bg-2,#fbf3f1)}
#planGross:focus-visible{outline:3px solid var(--focus,#0b5fff);outline-offset:2px}
@media print{.panel-gross{display:none!important}}
body.view-floki .msgs{min-height:58vh}
@media(max-width:620px){.viewseg button .vl{display:none}}

/* Empty-State */
.empty{position:relative;border:2px dashed var(--line-2);border-radius:var(--r);background:rgba(255,255,255,.6);
  padding:34px 28px 38px;text-align:center;animation:rise .5s ease both} /* KEIN overflow:hidden (Review 06.09.2026): es schnitte den goldenen Wander-Rahmen (::after, inset:-2px) weg — die Pfoten-Spur hält das SVG selbst in der Box (preserveAspectRatio meet, innere SVGs clippen von sich aus) */
/* Wander-Glow auf den Strichen: goldenes Dash-Border deckungsgleich über dem grauen, per conic-Fenster nacheinander „gezündet" */
.empty::after{content:"";position:absolute;inset:-2px;border-radius:inherit;border:2px dashed #e8b81f;
  filter:drop-shadow(0 0 5px rgba(237,191,46,.75));
  -webkit-mask:conic-gradient(from var(--fga),transparent 0 8%,#fff 18% 26%,transparent 36% 100%);
  mask:conic-gradient(from var(--fga),transparent 0 8%,#fff 18% 26%,transparent 36% 100%);
  opacity:0;pointer-events:none;animation:esGlowDash 7s linear infinite}
@keyframes esGlowDash{from{--fga:315deg;opacity:1}to{--fga:-45deg;opacity:1}}
.empty-art{width:min(240px,64%);margin:0 auto 6px}
.empty-art .es-spark{transform-box:fill-box;transform-origin:center;opacity:0;will-change:opacity,transform;
  animation:esTwinkle 4.2s cubic-bezier(.45,0,.55,1) infinite}
.empty-art .es-spark.s2{animation-duration:5.2s;animation-delay:1.6s}
.empty-art .es-spark.s3{animation-duration:4.7s;animation-delay:3s}
.empty-art .es-ff{transform-box:fill-box;transform-origin:center;will-change:opacity,transform;
  animation:esFloat 4.8s ease-in-out infinite}
.empty-art .es-ff.f2{animation-duration:6s;animation-delay:1.1s}
.empty-art .es-ff.f3{animation-duration:5.4s;animation-delay:2.2s}
/* Pfoten-Spur über die ganze Box: Abdrücke wandern abwechselnd von rechts oben / links oben zur Karte;
   Fenster 1,4s bei Takt 0,42s => nie mehr als 4 gleichzeitig sichtbar; Phasenwechsel erst wenn alle weg sind */
.empty-paws{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}
.empty-paws .es-paw{opacity:0;will-change:opacity;animation:esTrail 10s linear infinite}
@keyframes esTrail{0%{opacity:0}1.5%{opacity:.95}9.5%{opacity:.85}14%{opacity:0}100%{opacity:0}}
@keyframes esTwinkle{0%,100%{opacity:0;transform:scale(.4) rotate(-12deg)}50%{opacity:1;transform:scale(1) rotate(8deg)}}
@keyframes esFloat{0%,100%{opacity:.3;transform:translateY(0)}50%{opacity:.9;transform:translateY(-4px)}}
.empty-t{font-weight:800;font-size:20px;color:var(--ink);margin-bottom:6px}
.empty-s{color:var(--ink-2);font-size:14.5px;max-width:440px;margin:0 auto 16px}
.empty-btn{display:inline-flex;align-items:center;gap:8px;margin:2px 0 14px;border:none;cursor:pointer;font-family:inherit;font-weight:800;font-size:15px;color:var(--cta-ink);background:var(--cta);padding:14px 26px;border-radius:var(--r-pill);box-shadow:0 3px 0 var(--cta-edge),var(--shadow);transition:transform var(--t-fast),background var(--t-fast)}
.empty-btn:hover{background:var(--cta-hover);transform:translateY(-1px)}
.empty-cta{font-size:13px;color:var(--maroon);background:var(--tint-rose);display:inline-flex;gap:9px;align-items:center;
  padding:10px 16px;border-radius:var(--r-pill)}
.empty-cta .arrow{font-weight:800;animation:nudge 1.4s ease-in-out infinite}
.empty-cta .mob{display:none}
@media(max-width:860px){.empty-cta .desk{display:none}.empty-cta .mob{display:inline}}

/* Tagesmission */
#missionBar{display:none;background:var(--card);border:1px solid var(--gold-soft);border-radius:var(--r);
  box-shadow:var(--shadow);padding:13px 16px;margin:0 0 14px}
body.hasplan #missionBar{display:block;animation:rise .5s ease both}
#missionBar .mh{display:flex;align-items:center;gap:9px;margin-bottom:9px}
#missionBar .mh .mt{font-weight:800;font-size:14px;color:var(--maroon)}
#missionBar .mh .ms{font-size:12px;color:var(--ink-2)}
#missionBar .mh .mc{margin-left:auto;font-size:12.5px;font-weight:700;color:var(--gold-ink)}
/* minmax(0,1fr) statt 1fr: eine 1fr-Spalte darf per Vorgabe nicht unter ihren Inhalt
   schrumpfen. Seit die Tagesmission nach Zeit gefüllt wird, stehen dort auch lange Titel
   („A_261 Fallschirmsprung c [Lineare Funktionen]") — die Kacheln forderten dadurch 686px
   Mindestbreite, drückten die linke Spalte auf und machten das Chat-Fenster schmal
   (Dom-Fund 13.08.). Mit minmax(0,…) greift endlich die Ellipse in .mslot .mtx. */
.mission-slots{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}
.mslot{display:flex;align-items:center;gap:8px;border:1px solid var(--line);border-radius:10px;background:var(--paper);min-width:0;
  padding:9px 11px;font-size:12.5px;cursor:pointer;font-family:inherit;text-align:left;transition:border-color var(--t-fast),background var(--t-fast)}
.mslot:hover{border-color:var(--gold);background:var(--gold-bg)}
.mslot .mi{width:22px;height:22px;border-radius:7px;background:var(--tint-rose);color:var(--maroon);display:flex;align-items:center;justify-content:center;font-size:11px;flex:none}
.mslot .mtx{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--ink)}
.mslot.done{background:var(--green-bg);border-color:#bfe3cc}
.mslot.done .mi{background:var(--green);color:#fff}
.mslot.done .mtx{color:var(--green-ink);text-decoration:none}
@media(max-width:640px){.mission-slots{grid-template-columns:minmax(0,1fr)}}

/* Wochen */
.week{background:var(--card);border:1px solid var(--line);border-radius:var(--r);
  margin-bottom:16px;box-shadow:var(--shadow);overflow:hidden}
.week.curweek{border-color:var(--gold);box-shadow:0 0 0 3px rgba(201,154,59,.14),var(--shadow)}
.week-head{display:flex;align-items:center;gap:13px;padding:15px 18px;cursor:pointer;user-select:none;width:100%;
  border:none;background:none;font-family:inherit;text-align:left;font-size:inherit}
.week-head:hover{background:var(--bg-2)}
.wnum{width:34px;height:34px;border-radius:10px;display:flex;align-items:center;justify-content:center;
  font-weight:800;font-size:14px;flex:none}
.wnum.done{background:var(--green);color:#fff}
.wnum.cur{background:var(--maroon);color:#fff;box-shadow:0 2px 8px rgba(104,24,38,.3)}
.wnum.soon{background:var(--tint-rose);color:var(--maroon)}
.week-head .wt{flex:1}
.week-head .wt .a{font-weight:700;font-size:15.5px;color:var(--ink)}
.week-head .wt .b{font-size:12.5px;color:var(--ink-2)}
.badge{font-size:11px;font-weight:700;padding:4px 10px;border-radius:var(--r-pill)}
.badge.cur{background:var(--gold-soft);color:var(--gold-ink-deep)}
.badge.done{background:var(--green-bg);color:var(--green-ink)}
.badge.soon{background:var(--bg-2);color:var(--ink-2)}
.chev{color:var(--ink-2);transition:transform var(--t-slow);font-size:13px;width:16px;text-align:center}
.week.open .chev{transform:rotate(180deg)}
.week-body{display:none;padding:4px 14px 14px}
.week.open .week-body{display:block;animation:fade .3s ease}
/* Der Wochenbalken endet auf DERSELBEN Kante wie die Themenbalken darunter, und seine
   Zahl steht in derselben Spalte (Dom 12.08.). Vorher war die Zeile ein flex mit 10px
   Abstand und einem 30px-Label — der Balken reichte dadurch ~35px weiter nach rechts als
   die Themenbalken. Jetzt dieselben Endspalten wie .thema-head: Zähler 52px, Chevron 12px
   (hier leer, nur als Platzhalter, damit die Kanten fluchten). */
.week-prog{display:grid;grid-template-columns:1fr 52px 12px;gap:8px;align-items:center;padding:0 18px 13px}
.week-prog .wp-track{flex:1;height:6px;border-radius:var(--r-pill);background:rgba(40,30,25,.10);overflow:hidden}
.week-prog .wp-fill{height:100%;width:0%;background:linear-gradient(90deg,#8a2336,#c99a3b);border-radius:var(--r-pill);transition:width .6s var(--ease)}
.week-prog .wp-lbl{font-size:11px;font-weight:700;color:var(--ink-2);text-align:center} /* mittig in der 52px-Spalte, damit „3/59" über „3/19" steht */
/* Themen-Blöcke: eine Woche mit mehreren Kapiteln */
/* .wthemes/.wth (Themen-Chips im Wochenkopf) sind am 12.08. entfernt worden — doppelt
   zur Wochenüberschrift, und seit die Themen aufklappbar sind ohnehin überflüssig. */
/* Außenabstand größtenteils in INNENabstand verwandelt (Dom 13.08.): der Abstand einer
   Zeile gehört nicht zu ihr und ist deshalb nicht klickbar — die Zeile ist nur 24px hoch,
   die sichtbare Bahn aber gut das Doppelte. Als Innenabstand zählt dieselbe Fläche zur
   Schaltfläche. Der Zeilenabstand insgesamt bleibt gleich (8+12+24+14 statt 14+12+24+8),
   die gestrichelte Trennlinie rutscht dabei 6px nach oben. */
.thema-head{display:flex;align-items:center;gap:8px;margin:8px 4px 0;padding:12px 0 14px;border-top:1px dashed var(--line)}
.week-body > .thema-head:first-child{margin-top:6px;padding-top:0;border-top:none}
.thema-head .th-ico{width:24px;height:24px;border-radius:8px;background:var(--tint-rose);color:var(--maroon);display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:800;flex:none}
.thema-head .th-name{font-weight:700;font-size:13px;color:var(--maroon)}
.thema-head .th-track{flex:1;height:4px;border-radius:var(--r-pill);background:rgba(40,30,25,.10);overflow:hidden;margin:0 4px}
.thema-head .th-fill{display:block;height:100%;width:0%;background:linear-gradient(90deg,#8a2336,#c99a3b);border-radius:var(--r-pill);transition:width .6s var(--ease)}
.thema-head .th-prog{font-size:11px;font-weight:700;color:var(--ink-2);background:var(--bg-2);padding:2px 8px;border-radius:var(--r-pill);flex:none;
  min-width:52px;text-align:center} /* feste Breite: sonst schiebt „3/19" vs „0/100" die Balken gegeneinander */
/* Gleich lange Fortschrittsbalken (Dom-Wunsch 12.08.): vorher war die Zeile ein flex und
   der Balken bekam den Rest — bei „Vektoren" war er dadurch deutlich länger als bei
   „Grundlagen Zentralmatura". Jetzt ein festes Spaltenraster, in dem NUR die Balkenspalte
   dehnbar ist: gleiche Namensspalte + gleiche Zählerbreite = überall gleich lange Balken.
   Lange Namen werden gekürzt statt die Spalte zu sprengen. */
/* Namensspalte in PIXELN, nicht in em: `em` rechnet im Raster gegen die Schriftgröße der
   ZEILE (16px) und nicht gegen die des Namens (13px) — 12em wären 192px statt der
   erwarteten 156. Gemessen ist der längste Themenname „Grundlagen Zentralmatura" 150px
   (über alle 13 Themen aller drei Kurse), 160px lässt also 10px Luft. Schmaler geht nicht,
   ohne ihn abzuschneiden; das war Doms „zu viel Abstand" vom 12.08. */
.thema-head{display:grid;grid-template-columns:24px minmax(0,160px) 1fr 52px 12px;gap:8px}
/* Name + Teil-Pille in EINER Rasterzelle (05.09.2026): der Text darf ellipsieren, die Pille
   nie — vorher hing „· Teil 1/2" am Ende des Namens und wurde als Erstes verschluckt. */
.thema-head .th-name{display:flex;align-items:center;gap:6px;min-width:0}
.thema-head .th-txt{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.thema-head .th-teil{flex:none;font-size:10.5px;font-weight:800;line-height:1;padding:3px 6px;border-radius:var(--r-pill);
  background:var(--tint-rose);color:var(--maroon);border:1px solid rgba(107,26,26,.18);letter-spacing:.02em}
.thema-head .th-track{margin:0}
/* Themenkopf MIT Lernzettel-Knopf (Dom-Fund 05.09.2026: „sieht broken aus"): der Kopf ist
   ein Raster mit fünf festen Spalten — ein sechstes Kind schob den Knopf in die 1fr-Spalte
   des Balkens (riesige Pille), den Balken in die 52-px-Spalte, den Zähler aus dem Bild und
   den Pfeil in eine zweite Zeile. Deshalb bekommt der Kopf mit Knopf eine eigene Spalte
   `auto` VOR dem Balken; der Balken bleibt das einzige flexible Stück und gibt den Platz. */
.thema-head.mit-zettel{grid-template-columns:24px minmax(0,160px) auto 1fr 52px 12px}
/* Handy: umgekehrte Verteilung. Ein 8em-Namensfeld hätte „Grundlagen Zentralmatura" und
   „Quadratische Funktionen" abgeschnitten — der Name ist die Information, der Balken nur
   Schmuck. Deshalb bekommt der Name den freien Platz und der Balken eine feste, schmale
   Breite; gleich lang bleiben die Balken dadurch erst recht. */
@media(max-width:640px){
  .thema-head{grid-template-columns:24px minmax(0,1fr) 56px 52px 12px;gap:6px}
  /* mit Knopf: eigene Spalte auch am Handy (dort nur das Zeichen, app-zettel.css) */
  .thema-head.mit-zettel{grid-template-columns:24px minmax(0,1fr) auto 56px 52px 12px}
  .week-prog{gap:6px} /* gleicher Abstand wie oben, sonst fluchten die Kanten am Handy nicht */
}
.thema-head .th-prog.full{background:var(--green-bg);color:var(--green-ink)}
/* Themen auf-/zuklappen (Dom 12.08.): bei 59 Etappen in Woche 1 war die Liste sonst
   eine endlose Rolle. Nur das erste Thema startet offen; die Etappen der anderen sind
   ausgeblendet, bleiben aber im DOM — die Fortschrittszähler laufen über Geschwister
   und dürfen sich beim Zuklappen nicht ändern. */
.thema-head{cursor:pointer;user-select:none}
.thema-head:focus-visible{outline:2px solid var(--gold);outline-offset:3px;border-radius:6px}
.thema-head .th-chev{margin-left:8px;font-size:10px;color:var(--ink-2);flex:none;transition:transform .18s}
.thema-head.zu .th-chev{transform:rotate(-90deg)}
.task.thm-zu{display:none}

/* „Noch eine Runde" — erscheint erst, wenn alle Etappen der Tagesmission grün sind.
   Bewusst zurückhaltend (kein Primär-Grün): das Angebot soll da sein, aber nicht drängen —
   der Plan verspricht eine Tagesportion, alles darüber ist freiwillig. */
.mission-mehr{display:block;margin:16px auto 2px;font-size:12px;font-weight:700;
  padding:8px 16px;border-radius:var(--r-pill);cursor:pointer;
  background:var(--paper);color:var(--maroon);border:1px solid var(--line-2)}
.mission-mehr:hover{background:var(--tint-rose)}
@media(max-width:640px){.mission-mehr{width:100%;margin:14px 0 2px}}

/* „Der Plan ist zu groß geworden" (13.08.). Ruhig, nicht alarmrot: es ist keine Panne,
   sondern eine Terminlage — und der Knopf daneben löst sie. */
.mission-zuviel{margin:14px 0 2px;padding:10px 12px;border-radius:10px;
  background:var(--gold-bg);border:1px solid var(--line-2);
  font-size:12.5px;line-height:1.5;color:var(--ink-2)}
.mission-zuviel .btn{display:inline-block;margin-top:8px;font-size:12px;font-weight:700;
  padding:7px 14px;border-radius:var(--r-pill);cursor:pointer;
  background:var(--paper);color:var(--maroon);border:1px solid var(--line-2)}
.mission-zuviel .btn:hover{background:var(--tint-rose)}

/* Task */
.task{border:1px solid var(--line);border-radius:var(--r-sm);margin-top:9px;
  background:var(--paper);transition:border-color var(--t),box-shadow var(--t)}
.task.cur{border-color:var(--gold);box-shadow:0 0 0 3px rgba(201,154,59,.12)}
.task.done{background:#f7f5f0}
.task-head{display:flex;align-items:center;gap:12px;padding:11px 13px}
/* Zeigt die Hand über der GANZEN Zeile, nicht nur über Titel und ▼ (Dom 13.08.).
   Die Klasse setzt app.js beim Verdrahten — nur Etappen mit Aufklapper bekommen sie. */
.task-head.head-klick{cursor:pointer}
.cbx{width:24px;height:24px;border-radius:7px;border:2px solid var(--line-2);flex:none;cursor:pointer;
  display:flex;align-items:center;justify-content:center;transition:all .18s;color:#fff;background:#fff;
  padding:0;font-family:inherit;position:relative}
.cbx::before{content:'';position:absolute;inset:-10px}
.cbx:hover{border-color:var(--maroon)}
.task.done .cbx{background:var(--green);border-color:var(--green)}
.cbx svg{opacity:0;transform:scale(.5);transition:all .18s}
.task.done .cbx svg{opacity:1;transform:scale(1)}
.ticon{width:30px;height:30px;border-radius:8px;display:flex;align-items:center;justify-content:center;
  font-size:15px;flex:none}
.ticon.vid{background:var(--tint-rose);color:var(--maroon)}
.ticon.quiz{background:var(--gold-bg);color:var(--gold-ink-deep)}
.ticon.read{background:#eef0f4;color:#5a6175}
.ticon.exam{background:var(--green-bg);color:var(--green-ink)}
.tmain{flex:1;cursor:pointer;min-width:0}
/* `.tt` ist seit 09.09.2026 ein <h4> (Screenreader-Sprungmarke, Philipp Huber) — die
   Browser-Voreinstellungen einer Überschrift müssen deshalb hier weg, sonst bekäme jede
   Etappenzeile Abstände und eine eigene Schriftgröße. Aussehen unverändert. */
.tmain .tt{margin:0;font-weight:600;font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--ink)}
.task.done .tmain .tt{color:var(--ink-2)}
.tmain .ts{font-size:12px;color:var(--ink-2);display:flex;align-items:center;gap:8px;margin-top:1px;flex-wrap:wrap}
.tmin{font-size:12px;color:var(--ink-2);flex:none}
.expander{color:var(--ink-2);font-size:12px;transition:transform var(--t-slow);width:18px;text-align:center;flex:none;cursor:pointer}
.task.exp .expander{transform:rotate(180deg)}
.task-body{display:none;padding:0 13px 14px 55px}
.task.exp .task-body{display:block;animation:fade .28s ease}
@media(max-width:640px){.task-body{padding-left:13px}}

/* Video */
/* Grundton = Grundfarbe der Thumbnails (#f6f2f3, an echten Poster-SVGs gemessen:
   deren .cls-1-Fläche). Vorher stand hier #1a0a0d — das war der „schwarze Moment"
   vor dem Poster: nicht das <video>, sondern der Wrapper DAHINTER. Unsere Videos sind
   16:9 im 16:9-Rahmen, es gibt also keine Letterbox-Balken, für die Dunkel nötig wäre. */
.player{border-radius:12px;overflow:hidden;border:1px solid var(--line);background:#f6f2f3;position:relative}
.player video{display:block;width:100%;aspect-ratio:16/9;background:#f6f2f3}
.player-meta{display:flex;align-items:center;gap:8px;margin-top:9px;font-size:12px;color:var(--ink-2);flex-wrap:wrap}
.player-meta .dot{width:4px;height:4px;border-radius:50%;background:var(--ink-3)}

/* Kontrollfrage am Player (Dom-Wunsch 14.08., gebaut 16.08.) — Geschwister NACH .player, nie darin: der Player
   hat eigenen Hintergrund und Radius, eine Karte darin sähe aus wie Teil des Videos. */
.vfr-block{margin-top:12px;display:flex;flex-direction:column;gap:10px}
.vfr-karte{border:1px solid var(--line);border-radius:var(--r-sm);background:var(--paper);padding:13px 14px}
.vfr-kopf{display:flex;align-items:center;gap:7px;margin-bottom:7px}
.vfr-ico{display:grid;place-items:center;width:19px;height:19px;border-radius:50%;background:var(--gold-soft);color:var(--gold-ink-deep);font-size:12px;font-weight:700}
.vfr-label{font-size:var(--fs-caption);letter-spacing:.02em;text-transform:uppercase;color:var(--ink-2);font-weight:600}
.vfr-frage{margin:0 0 10px;font-size:var(--fs-body);line-height:1.45;color:var(--ink)}
.vfr-opts{display:flex;flex-direction:column;gap:6px}
.vfr-opt{text-align:left;padding:9px 12px;border:1px solid var(--line-2);border-radius:var(--r-sm);background:var(--card);color:var(--ink);font:inherit;font-size:var(--fs-small);cursor:pointer;transition:background var(--t-fast),border-color var(--t-fast)}
.vfr-opt:hover:not(:disabled){background:var(--bg-2);border-color:var(--maroon-light)}
.vfr-opt:disabled{cursor:default}
/* Ergebnis-Zustand: Farbe UND Zeichen — Rot/Grün allein ist für Farbenblinde keine Aussage. */
.vfr-opt.richtig{border-color:var(--green);background:var(--green-bg);color:var(--green-ink);font-weight:600}
.vfr-opt.richtig::after{content:" ✓";font-weight:700}
.vfr-opt.falsch{border-color:var(--error);background:var(--error-bg);color:var(--error)}
.vfr-opt.falsch::after{content:" ✗";font-weight:700}
.vfr-erg{margin-top:10px;padding:10px 12px;border-radius:var(--r-sm);border-left:3px solid}
.vfr-erg.vfr-gut{background:var(--green-bg);border-left-color:var(--green)}
.vfr-erg.vfr-schlecht{background:var(--gold-bg);border-left-color:var(--gold)}
.vfr-verdict{margin:0;font-size:var(--fs-small);font-weight:600;color:var(--ink)}
.vfr-erkl{margin:5px 0 0;font-size:var(--fs-small);line-height:1.5;color:var(--ink-2)}
.inline-flag{display:inline-flex;align-items:center;gap:5px;color:var(--green-ink);font-weight:600}

/* Probe-Matura: die amtlichen Hefte (13.08.). Zwei Knöpfe, klar abgestuft — die Angabe
   ist der Weg, das Lösungsheft kommt erst NACH dem Rechnen. Mindesthöhe 44px, weil das
   am Handy mit dem Daumen getroffen werden muss. */
.hefte{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.heft{display:inline-flex;align-items:center;min-height:44px;padding:0 16px;border-radius:10px;
  background:var(--maroon);color:#fff;font-size:13.5px;font-weight:600;text-decoration:none}
.heft:hover{background:var(--maroon-light)}
/* Die Review-Etappe trägt einen KNOPF statt eines Links (er öffnet den Chat, kein PDF) —
   ohne Reset erbt er Systemrahmen und Systemschrift und sieht neben den Heften fremd aus. */
button.heft{border:0;font-family:inherit;cursor:pointer}
.heft.heft-zweit{background:transparent;color:var(--maroon);border:1px solid var(--line-2)}
.heft.heft-zweit:hover{background:var(--green-bg);border-color:var(--line-2)}
.heft-hinweis{flex-basis:100%;font-size:12px;color:var(--ink-2)}

/* Quiz */
.quiz .q{font-size:14.5px;font-weight:600;margin-bottom:4px;color:var(--ink)}
.quiz .src{display:inline-flex;align-items:center;gap:5px;font-size:11px;font-weight:700;color:var(--gold-ink-deep);
  background:var(--gold-bg);padding:4px 9px;border-radius:var(--r-pill);margin-bottom:11px}
.opt{display:flex;align-items:center;gap:11px;border:1.5px solid var(--line);border-radius:10px;
  padding:12px 13px;margin-top:8px;cursor:pointer;font-size:14px;transition:all var(--t-fast);background:#fff;min-height:48px}
.opt:hover{border-color:var(--maroon-light);background:#fdf9f9}
.opt .k{width:24px;height:24px;border-radius:50%;border:1.5px solid var(--line-2);flex:none;
  display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:700;color:var(--ink-2);transition:all var(--t-fast)}
.opt.correct{border-color:var(--green);background:var(--green-bg)}
.opt.correct .k{background:var(--green);border-color:var(--green);color:#fff}
.opt.wrong{border-color:var(--error);background:var(--error-bg);animation:shake .4s ease}
.opt.wrong .k{background:var(--error);border-color:var(--error);color:#fff}
.opt.lock{pointer-events:none;opacity:.55}
.opt.lock.correct,.opt.lock.wrong{opacity:1}
.feedback{display:none;margin-top:12px;border-radius:10px;padding:12px 14px;font-size:13.5px;line-height:1.6}
.feedback.show{display:block;animation:fade .3s ease}
.feedback.ok{background:var(--green-bg);border:1px solid #bfe3cc}
.feedback.ok b{color:var(--green-ink)}
.feedback.no{background:var(--error-bg);border:1px solid #eec7c4}
.feedback.no b{color:var(--error)}
.fb-retry{display:block;margin-top:10px;border:1.5px solid var(--error);background:#fff;color:var(--error);font-family:inherit;font-weight:700;font-size:13px;padding:9px 16px;border-radius:var(--r-pill);cursor:pointer;transition:all var(--t-fast);min-height:40px}
.fb-retry:hover{background:var(--error);color:#fff}

/* Fokus-Leiste (Pomodoro) */
#focusBar{display:flex;align-items:center;gap:11px;background:linear-gradient(100deg,#fbf2e0,#f8eef4);border:1px solid var(--gold-soft);border-radius:var(--r);padding:9px 14px;margin:0 0 14px;box-shadow:var(--shadow)}
#focusBar .fb-ic{font-size:16px}
#focusBar .fb-l{font-weight:700;font-size:13px;color:var(--maroon)}
#focusBar .fb-time{font-weight:800;font-size:19px;color:var(--ink);font-variant-numeric:tabular-nums;min-width:5ch}
#focusBar .fb-time.run{color:var(--gold-ink)}
#focusBar .fb-hint{font-size:11.5px;color:var(--ink-2)}
/* Fokus-Länge (02.09.2026): sieht aus wie der Hinweistext daneben, ist aber ein echtes
   <select> — deshalb nur entschärft, nicht neu erfunden. */
#focusBar .fb-sel{font-family:inherit;font-size:11.5px;color:var(--ink-2);background:transparent;
  border:1px solid var(--line-2);border-radius:var(--r-pill);padding:3px 6px;cursor:pointer}
#focusBar .fb-sel:hover{border-color:var(--maroon);color:var(--ink)}
#focusBar .fb-sel:disabled{opacity:.45;cursor:default}
/* Stift-Knopf statt zweiter Minutenanzeige (Dom 02.09.2026). Gleiche Optik wie das
   Auswahlfeld, damit die Leiste ruhig bleibt; 32 px Trefferflaeche fuers Handy. */
#focusBar .fb-edit{font-family:inherit;font-size:13px;line-height:1;color:var(--ink-2);
  background:transparent;border:1px solid var(--line-2);border-radius:8px;
  min-width:32px;min-height:28px;cursor:pointer;transition:border-color var(--t),color var(--t)}
#focusBar .fb-edit:hover{border-color:var(--maroon);color:var(--maroon)}
#focusBar .fb-edit:focus-visible{outline:3px solid var(--maroon);outline-offset:2px}
#focusBar .fb-btns{margin-left:auto;display:flex;gap:6px}
#focusBar .fb-btns button{width:36px;height:36px;border-radius:50%;border:1px solid var(--line-2);background:var(--card);font-size:14px;cursor:pointer;transition:all var(--t-fast);font-family:inherit}
#focusBar .fb-btns button:hover{background:var(--maroon);color:#fff;border-color:var(--maroon)}

/* Komet um die Fokus-Leiste — die Optik der Feature-Karten, das Tempo gleichmäßig
   (Dom 07.09.2026: erst „bau einfach den genau gleichen effekt ein wie bei den anderen
   kacheln … genau den", dann „der komet soll aber nicht so um die ecken flitzen das sieht
   stressig aus, lass den komet smooth und schön gleichmäßig entlang des randes gleiten").

   DAS AUSSEHEN steht hier und ist Zeichen für Zeichen die Regel aus `landing.css`
   (`:is(.feat,.testi,.news-card,.bridge-card)::before/::after`): derselbe
   `conic-gradient`, dieselbe Maske, dasselbe Padding, derselbe `blur(6px)` auf der
   zweiten Lage. `test/komet.test.ts` liest die Bausteine AUS landing.css und verlangt sie
   hier — wer sie dort ändert, bekommt einen roten Test statt stiller Drift.

   DAS TEMPO kommt aus `/app/komet.js`. Grund: ein konischer Verlauf dreht einen WINKEL,
   und auf dieser Leiste (am Schreibtisch rund 18:1) liegen 96 % des Winkels auf den zwei
   Langseiten — der Bogen kriecht in der Mitte und schnellt an den kurzen Enden durch.
   Gemessen und angesehen, es ist Doms „um die Ecken flitzen". Ein gleichmäßiges Gleiten
   braucht deshalb eine Zeitkurve, die vom Seitenverhältnis der Box abhängt, und das kann
   statisches CSS nicht wissen. Das Skript misst die Leiste und fährt `--fga` über die
   Web-Animations-API mit Stützstellen, die in gleichen Zeitschritten gleiche
   UMFANGS-Schritte ergeben.

   ZWEI WEGE, DIE NICHT GEHEN — beide gebaut, angesehen, verworfen (07.09.):
     * Ein Leuchtstreifen auf einer `offset-path`-Bahn hat zwar von Haus aus gleichmäßiges
       Tempo, ist aber GERADE: in der 14-px-Ecke verlässt er den 2,5-px-Rahmen, die Maske
       schneidet ihn weg und er verschwindet viermal je Runde kurz ganz.
     * Eine zusätzliche, UNGEMASKTE Verlaufs-Lage („mehr Glow") ist kein Bogen, sondern ein
       Keil über die ganze Fläche — beim Drehen ein heller Schwall, an den Enden ein Blitz.
       Genau das war Doms „flare effekt".

   DIE CSS-ANIMATION UNTEN IST DER RÜCKFALL: kann ein Browser keine Pseudo-Element-
   Animation über die Web-Animations-API, läuft die Runde eben gleichförmig im Winkel —
   dieselbe Optik, nur mit dem Tempo der Karte. Nie gar nichts.

   WARUM `@supports`: ohne `mask-composite` bliebe der Verlauf ungeschnitten, und dann
   stünde genau der Keil da. Deko darf nur ganz oder gar nicht. */
#focusBar{position:relative}
#focusBar .fb-komet{display:none}

@supports ((mask-composite: exclude) or (-webkit-mask-composite: xor)){
  #focusBar .fb-komet{
    display:block;position:absolute;inset:-1px;border-radius:inherit;pointer-events:none;
  }
  #focusBar .fb-komet::before,
  #focusBar .fb-komet::after{
    content:"";position:absolute;inset:0;border-radius:inherit;padding:2.5px;
    background:conic-gradient(from var(--fga),transparent 0 71%,#fff3c4 73.5%,#edbf2e 78%,rgba(201,154,59,.4) 88%,transparent 96%);
    -webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);
    -webkit-mask-composite:xor;
    mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);
    mask-composite:exclude;
    opacity:0;pointer-events:none;
    animation:fbKomet 8s linear 1 both;animation-name:none;
  }
  #focusBar .fb-komet::after{filter:blur(6px)}
  #focusBar .fb-komet.laeuft::before,
  #focusBar .fb-komet.laeuft::after{animation-name:fbKomet}
}
/* Eine volle Runde — derselbe Weg wie `featComet` in landing.css (315deg → -45deg, also
   gegen den Uhrzeigersinn, damit die helle Spitze vorne läuft). Das Ein- und Ausblenden
   liegt in denselben Keyframes, damit der Komet nicht mitten auf der Kante aufpoppt. */
@keyframes fbKomet{
  0%{--fga:315deg;opacity:0}
  8%{opacity:1}
  90%{opacity:1}
  100%{--fga:-45deg;opacity:0}
}

/* Erfolge / Notizen Views */
body.view-erfolge #planCol,body.view-erfolge #flokiCol{display:none}
body.view-erfolge .grid{grid-template-columns:minmax(0,1fr)}
#erfolgeView{display:none;scroll-margin-top:76px} /* Reiter-Sprung am Handy landet unter dem Kopf (06.09.2026) */
body.view-erfolge #erfolgeView{display:block}
.erf-h{margin-bottom:14px}
.erf-h h2{font-size:22px;font-weight:800;color:var(--maroon)}
.erf-h p{color:var(--ink-2);font-size:14px}
.erf-sec{background:var(--card);border:1px solid var(--line);border-radius:var(--r);padding:16px 18px;box-shadow:var(--shadow);margin-bottom:16px}
.erf-t{font-weight:700;font-size:12.5px;text-transform:uppercase;letter-spacing:.5px;color:var(--maroon);margin-bottom:12px}
.erf-t .erf-sub{text-transform:none;letter-spacing:0;color:var(--ink-2);font-weight:600}
.erf-ranks{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}
.rankcard{background:var(--bg-2);border:1px solid var(--line);border-radius:12px;padding:14px;text-align:center}
.rankcard.on{background:var(--gold-bg);border-color:var(--gold);box-shadow:0 0 0 2px rgba(201,154,59,.25)}
.rankcard .rcg{width:54px;height:54px;border-radius:50%;margin:0 auto;display:flex;align-items:center;justify-content:center;position:relative;overflow:hidden;background:var(--card)}
.rankcard .rcg.lk{background:rgba(0,0,0,.05)}
.rankcard .rcg .bemoji{font-size:27px}
.rankcard .rcg img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;padding:7px}
.rankcard .rcg .block{font-size:23px;opacity:.4}
.rankcard .rcn{font-weight:700;margin-top:4px;color:var(--ink)}
.rankcard .rcbar{height:6px;border-radius:3px;background:rgba(0,0,0,.08);margin:8px 0 6px;overflow:hidden}
.rankcard .rcbar i{display:block;height:100%;transition:width .7s var(--ease)}
.rankcard .rcsub{font-size:12px;color:var(--ink-2)}
.erf-stats{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
.erf-stat{background:var(--bg-2);border-radius:10px;padding:12px;text-align:center}
.erf-stat b{display:block;font-size:22px;font-weight:800;color:var(--maroon)}
.erf-stat span{font-size:12px;color:var(--ink-2)}
.erf-mile{margin-top:14px}
.erf-mt{font-size:13px;color:var(--ink-2)}.erf-mt b{color:var(--ink)}
.mbar{height:8px;border-radius:4px;background:rgba(0,0,0,.08);margin:6px 0 4px;overflow:hidden}
.mbar i{display:block;height:100%;background:linear-gradient(90deg,#8a2336,#c99a3b);transition:width .7s}
.erf-msub{font-size:12px;color:var(--ink-2)}
.erf-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:10px}
.bt{background:var(--bg-2);border:1px solid var(--line);border-radius:12px;padding:12px 8px;text-align:center}
.bt .bcircle{width:52px;height:52px;border-radius:50%;margin:0 auto 2px;display:flex;align-items:center;justify-content:center;position:relative;overflow:hidden;background:var(--card)}
.bt .bcircle.lk{background:rgba(0,0,0,.05)}
.bt .bcircle .bemoji{font-size:25px}
.bt .bcircle img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;padding:6px}
.bt .bcircle .block{font-size:21px;opacity:.4}
.bt.on{background:#fff;border-color:var(--gold-soft);box-shadow:var(--shadow)}
.bt.locked{opacity:.96}
.bt.fresh{box-shadow:0 0 0 2px var(--gold)}
.bt .btn2{font-weight:600;font-size:12px;margin-top:5px;color:var(--ink)}
.bt:not(.on) .btn2{color:var(--ink-2)}
.bt .bts{font-size:10.5px;color:var(--ink-2);margin-top:2px}
#erfReset{margin-top:4px;border:1px solid var(--line-2);background:var(--card);color:var(--ink-2);font-family:inherit;font-weight:600;font-size:13px;padding:10px 18px;border-radius:var(--r-pill);cursor:pointer;min-height:44px}
#erfReset:hover{background:var(--maroon);border-color:var(--maroon);color:#fff}
@media(max-width:760px){.erf-grid{grid-template-columns:repeat(3,1fr)}}
body.view-meintag #planCol,body.view-meintag #flokiCol{display:none}
body.view-meintag .grid{grid-template-columns:minmax(0,1fr)}
#meintagView{display:none;scroll-margin-top:76px}
body.view-meintag #meintagView{display:block}
.myadd{display:flex;gap:8px;margin-bottom:14px}
.myadd input{flex:1;border:1px solid var(--line-2);border-radius:10px;padding:11px 14px;font-size:14px;font-family:inherit;outline:none;background:var(--bg);color:var(--ink)}
.myadd input:focus{border-color:var(--maroon);background:#fff}
.myadd input:focus-visible{outline:3px solid var(--focus);outline-offset:2px} /* outline:none oben schlägt base.css:20 — Tastaturfokus braucht die Outline zurück */
/* flex:none + nowrap (Dom 06.09.2026, Handy: „hinzufügen button ist noch bugged und zu groß"):
   in der schmalen Spalte brach „+ Hinzufügen" auf zwei Zeilen um und der Knopf wuchs in die Höhe. */
.myadd button{flex:none;white-space:nowrap;border:none;background:var(--maroon);color:#fff;font-weight:600;font-size:13.5px;padding:0 16px;border-radius:10px;cursor:pointer;font-family:inherit;min-height:44px}
@media(max-width:640px){.myadd button{padding:0 12px;font-size:13px}.myadd input{min-width:0;padding:11px 12px}}
.myadd button:hover{background:var(--maroon-dark)}
.mylist{display:flex;flex-direction:column;gap:8px}
.myitem{display:flex;align-items:center;gap:12px;border:1px solid var(--line);border-radius:10px;padding:11px 13px;background:var(--card)}
.myitem.done{background:#f7f5f0}
.mycbx{width:24px;height:24px;border-radius:7px;border:2px solid var(--line-2);flex:none;cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:13px;color:#fff;font-weight:800;background:#fff;font-family:inherit;padding:0}
.myitem.done .mycbx{background:var(--green);border-color:var(--green)}
.myt{flex:1;font-size:14px;color:var(--ink)}
.myitem.done .myt{color:var(--ink-2)}
.mydel{margin-left:auto;border:none;background:transparent;color:var(--ink-2);font-size:18px;cursor:pointer;line-height:1;padding:6px 10px;border-radius:6px;font-family:inherit}
.mydel:hover{background:rgba(0,0,0,.05);color:var(--ink)}
.myempty{text-align:center;color:var(--ink-2);font-size:13.5px;padding:20px}
@media(max-width:640px){
  .apphead{flex-direction:column;align-items:flex-start}
  .ring-wrap{min-width:0;width:100%}
}
/* W2-Portierung: aus header.css hierher — Override muss NACH der #app-Basisregel (Z.2) laden */
@media(max-width:860px){
  #app{padding-top:36px}
}

/* ===== W3-A: In-App-Quiz (additiv — keine neue Farbe, kein neuer Radius, keine neue Schrift) ===== */
.quiz math{font-size:1.06em;vertical-align:baseline;line-height:normal} /* Grundlinie, wie Chat + Lernzettel (06.09.2026) */
.opt .lbl{flex:1;min-width:0;overflow-wrap:anywhere}
.qact{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-top:12px}
.qact .btn{font-size:14px}
.qbonus{font-size:11.5px;color:var(--ink-2);margin-top:6px}
.qhint{margin-top:10px;background:var(--gold-bg);border:1px solid var(--gold-soft);
  border-radius:10px;padding:11px 13px;font-size:13px;line-height:2.4}
.qval{margin-top:11px}
.qval-lab{display:block;font-size:12.5px;font-weight:700;color:var(--ink-2);margin-bottom:5px}
.qval-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.qval-in{width:10ch;min-height:48px;border:1.5px solid var(--line-2);border-radius:10px;
  padding:11px 13px;font-size:15px;font-family:inherit;font-variant-numeric:tabular-nums;
  outline:none;background:var(--bg);color:var(--ink)}
.qval-in:focus{border-color:var(--maroon);background:#fff}
.qval-in:focus-visible{outline:3px solid var(--focus);outline-offset:2px} /* outline:none oben schlägt base.css:20 — Tastaturfokus braucht die Outline zurück */
.qval-unit{font-size:13px;font-weight:700;color:var(--gold-ink-deep);background:var(--gold-bg);
  border-radius:var(--r-pill);padding:5px 11px}
.qval-neg{width:40px;min-height:40px;border:1.5px solid var(--line-2);border-radius:10px;
  background:var(--card);color:var(--ink);font-family:inherit;font-size:16px;cursor:pointer}
.qval-fmt{font-size:12px;color:var(--ink-2);margin-top:6px}
/* Bruchstriche brauchen Luft (CLAUDE.md-Lesson): \dfrac steht in Prompt, Tipp und Rechenweg */
.fb-sol{margin-top:9px;padding-top:9px;border-top:1px dashed var(--line);line-height:2.4}
.quiz .q-next{margin-top:12px}

/* ===== M9-B: Paywall-Modal (Gratis-Kontingent erschöpft) — additiv, keine neue Farbe,
   kein neuer Radius, keine neue Schrift. Gold nur als Mini-Akzent-Box wie .qhint. ===== */
.pw-ovl{position:fixed;inset:0;z-index:var(--z-overlay);display:flex;align-items:center;justify-content:center;
  padding:20px;background:rgba(40,30,25,.55);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}
.pw-ovl[hidden]{display:none} /* die Klassenregel oben würde die UA-Regel [hidden] sonst schlagen */
.pw{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--shadow-float);
  width:100%;max-width:430px;padding:22px;animation:rise .3s var(--ease) both;
  max-height:calc(100vh - 40px);overflow-y:auto}
/* Doms Grafik als Kopf (03.09.2026). Sie sitzt buendig in der oberen Rundung, deshalb
   negative Raender in Hoehe der Polsterung — der Rest des Fensters bleibt unberuehrt. */
.pw-bild{margin:-22px -22px 14px;border-radius:var(--r-lg) var(--r-lg) 0 0;overflow:hidden;
  background:#fff;display:flex;justify-content:center}
/* Das Bild ist quadratisch und wuerde auf einem flachen Bildschirm das halbe Fenster
   fressen. `contain` statt `cover`, weil die Bildaussage UNTEN steht (das Spruchband) —
   ein Zuschnitt haette genau die Pointe abgeschnitten. Der Hintergrund ist am Bild
   gemessen (#ffffff an drei Ecken), die Letterbox faellt deshalb nicht auf. */
.pw-bild img{display:block;width:100%;height:auto;max-height:min(300px,38vh);object-fit:contain}

/* QUERFORMAT ab 700 px (Dom 03.09.2026: „text links und die grafik rechts davon, dadurch
   kann die grafik groesser werden"). Umgesetzt als Raster auf dem vorhandenen Fenster —
   kein zweites Markup, keine zweite Wahrheit: dieselben Kinder, nur anders verteilt.
   Die Grafik haengt in Spalte 2 ueber ALLE Zeilen und stoesst rechts, oben und unten
   buendig an den Rand; die negativen Raender entsprechen genau der Polsterung. */
@media (min-width:700px){
  /* Genau ZWEI Rasterzellen: Text und Grafik. Als lose Geschwister bekam jedes Stueck
     Text eine eigene Zeile, und die ueber alles gespannte Grafik zog sie auf gleiche
     Hoehe — zwischen Ueberschrift und Absatz klaffte eine Handbreit Luft. */
  .pw-quer{max-width:820px;display:grid;grid-template-columns:minmax(0,1fr) 340px;
    column-gap:26px;align-items:stretch}
  .pw-quer .pw-inhalt{grid-column:1;display:flex;flex-direction:column;
    /* Platz fuer den Boden: die Knoepfe stehen UEBER Huegel und Band, nicht darauf —
       ein weisser Geisterknopf auf dunkelrotem Band waere unlesbar. */
    position:relative;z-index:0;padding-bottom:64px}
  /* Die Grafik ist QUADRATISCH und sitzt unten rechts, buendig mit dem Fensterrand.
     Nur so liegen Huegel, Band und Boden an einer BERECHENBAREN Hoehe — und nur dann
     kann der Boden links im selben Mass weiterlaufen. (Vorher war sie mittig
     eingepasst; dann haette die Naht bei jeder Textlaenge woanders gelegen.) */
  .pw-quer .pw-bild{grid-column:2;grid-row:1;align-self:end;
    margin:0 -22px -22px 0;border-radius:0 0 var(--r-lg) 0;align-items:flex-end;
    width:362px;height:362px}
  .pw-quer .pw-bild img{width:362px;height:362px;max-height:none;object-fit:contain}
  /* GRAFIK UND BODEN SIND EIN BILD (Dom 03.09.2026: „stell sicher dass der uebergang
     fluessig ist. wichtig."). Vorher lagen Grafik (<img>) und Bodenstreifen (Hintergrund)
     als ZWEI Dateien nebeneinander und mussten per CSS aufeinander ausgerichtet werden —
     jede Rundung war eine sichtbare Naht, und der gleichnamige Streifen blieb obendrein im
     Browser-Cache haengen (Dom sah die alte gerade Fassung). `paywall-quer.jpg` ist 1640×724
     (2x fuer scharfe Bildschirme): rechts die Grafik, links die Verlaengerung aus ihrer
     EXAKTEN Randspalte (groesste Farbabweichung an der Naht: 9/255), mit der Welle nach
     unten. Verankert rechts unten, 362 CSS-px hoch — genau die Grafikkante. Das <img>
     bleibt fuer die gestapelte Handy-Ansicht und ist hier nur unsichtbar (behaelt seinen
     Platz, damit das Raster gleich bleibt). Weiss im Bild = --card (#ffffff, tokens.css). */
  .pw-quer{background:var(--card) url(/app/img/paywall-quer.jpg) no-repeat right bottom / auto 362px}
  .pw-quer .pw-bild img{opacity:0}
  /* Die Bildbox malt sonst ihr Weiss UEBER das Komposit — dann fehlt genau die Grafik. */
  .pw-quer .pw-bild{background:transparent}
  /* Jetzt darf sie gross werden: keine Hoehendeckelung mehr, sie fuellt die Spalte. */
  .pw-quer .pw-bild img{max-height:none}
  /* Im Querformat passt alles ohne Scrollen — der klebende Fuss waere nur eine Kante. */
  /* Die Knoepfe sitzen unten in der Textspalte — sie sind der Abschluss, nicht ein Absatz. */
  .pw-quer .pw-act{position:static;margin:auto 0 0;padding:6px 0 0}
  .pw-quer .pw-coupon{margin-bottom:16px}
}
.pw:focus-visible{outline:3px solid var(--focus);outline-offset:2px}
.pw-top{display:flex;align-items:center;gap:13px;margin-bottom:12px}
.pw-face{width:52px;height:52px;flex:none}
.pw-top h3{font-size:var(--fs-h3);margin-top:2px}
.pw-txt{font-size:14.5px;margin-bottom:10px}
.pw-keep{font-size:13.5px;color:var(--green-ink);background:var(--green-bg);border:1px solid var(--line);
  border-radius:10px;padding:10px 12px;margin-bottom:8px}
.pw-coupon{font-size:13px;color:var(--gold-ink-deep);background:var(--gold-bg);border:1px solid var(--gold-soft);
  border-radius:10px;padding:10px 12px;margin-bottom:15px}
/* Verdient: derselbe Kasten, nur kraeftiger — der Code ist jetzt eine Belohnung und
   darf das auch aussehen. Kein neuer Farbton, nur mehr davon. */
.pw-coupon-auf{font-weight:700;border-width:2px;box-shadow:0 2px 10px rgba(212,175,55,.22)}
/* Warnbox der Lösch-Rückfrage (02.09.2026) — gebaut wie .pw-keep/.pw-coupon, nur in
   Maroon statt Grün/Gold. Keine neue Farbe, kein neuer Radius: dieselbe Bühne. */
.pw-warn{font-size:13.5px;color:var(--maroon);background:var(--tint-rose);
  border:1px solid rgba(104,24,38,.28);border-radius:10px;padding:10px 12px;margin-bottom:15px}
/* Die Knoepfe bleiben stehen, auch wenn das Fenster scrollt: mit der Grafik im Kopf
   passt der Inhalt auf einem flachen Bildschirm nicht mehr ganz hinein, und ein
   Bezahl-Fenster, dessen Knopf man erst suchen muss, ist eine Sackgasse. */
.pw-act{display:flex;flex-wrap:wrap;gap:9px;position:sticky;bottom:-22px;
  background:var(--card);padding:10px 0 0;margin-bottom:-22px;padding-bottom:22px}
.pw-act .btn{font-size:14px}
@media(max-width:480px){.pw-act .btn{width:100%}}
.pw-act .pw-login[hidden]{display:none} /* „Anmelden“ nur im Zettel-Fenster eines Gasts (17.09.2026) — sonst schlägt .btn das hidden */
@media (prefers-reduced-motion: reduce){.pw{animation:none}}
html.noanim .pw{animation:none}

/* Intro-Trailer (Dom 09.09.2026). ZWEI Zutaten, beide additiv — keine neue Farbe, kein
   neuer Radius, keine neue Schrift.
   (a) .pw-breit: die Karte ist auf 430px gebaut, ein 16:9-Video darin waere briefmarkengross.
       720px ist die Breite, ab der ein Video auf einem Laptop wirklich anschaubar ist; die
       Karte bleibt darunter genau wie bisher, weil width:100% aus .pw weitergilt.
   (b) .tr-eintrag: der angeheftete Zugang ueber der ersten Wochenkarte. Sieht aus wie eine
       Etappe (.task), ist aber KEINE — er traegt kein data-task und zaehlt nirgends mit. */
.pw-breit{max-width:720px}
.tr-player{margin:0 0 15px}
.tr-player video{width:100%;display:block;border-radius:12px;background:var(--tint-rose)}

.tr-eintrag{display:flex;align-items:center;gap:12px;width:100%;text-align:left;
  border:1px solid var(--line);border-radius:var(--r-sm);background:var(--paper);
  padding:11px 13px;margin-top:9px;cursor:pointer;font-family:inherit;
  transition:border-color var(--t),box-shadow var(--t)}
.tr-eintrag:hover{border-color:var(--maroon)}
/* Dom-Fund 11.09.2026: „das sollen die leute noch nicht sehen". Die Kachel stand SICHTBAR in
   jeder Lernreise, obwohl der Server ohne Manifest-Eintrag `da:false` meldet und trailer.js
   `hidden` deshalb nie entfernt — `display:flex` oben schlaegt die UA-Regel fuer [hidden]
   (gleiche Spezifitaet, spaetere Regel gewinnt). Fuenfter Fall dieser Klasse im Haus
   (.pw-ovl, .composer button, .bild-leiste, .zettel-leiste, .sp-login haben die Zeile alle):
   WER display SETZT, MUSS [hidden] SELBST WIEDER BEDIENEN. */
.tr-eintrag[hidden]{display:none}
.tr-ic{width:30px;height:30px;border-radius:8px;display:flex;align-items:center;
  justify-content:center;font-size:13px;flex:none;background:var(--tint-rose);color:var(--maroon)}
.tr-tx{flex:1;min-width:0}
.tr-tt{display:block;font-weight:600;font-size:14px;color:var(--ink)}
.tr-sub{display:block;font-size:12px;color:var(--ink-2);margin-top:1px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
@media(max-width:560px){.tr-sub{white-space:normal}}

/* Hinweiszeile am Player (video.js: Sperr-/Fehlerfall statt stummem Schwarz) — additiv,
   Optik wie .qbonus/.qval-fmt: keine neue Farbe, keine neue Schrift. */
.player-hint{font-size:13px;line-height:1.5;color:var(--ink-2);margin-top:8px;
  background:var(--bg-2);border:1px solid var(--line);border-radius:10px;padding:10px 12px}
/* Der Weg zum Hinweis (26.08.2026): steht direkt unter „Bitte melde dich an" — ein
   Hinweis ohne Weg ist nur eine schlechte Nachricht. Bewusst zurueckhaltend als Link
   und nicht als zweiter grosser Knopf: der Player bleibt die Hauptsache. */
.hint-login{display:inline-block;margin-top:4px;font-size:13px;font-weight:600;
  color:var(--cta);text-decoration:underline;text-underline-offset:3px}
.hint-login:hover{color:var(--cta-hover)}
/* Gesperrtes Video (14.09.2026, video.js sperreZeigen): „Kurs freischalten“ bzw. „Anmelden“
   MITTIG auf dem Bild, im Kartenton statt Schwarz — der Poster bleibt dahinter erkennbar.
   Nur ueber dem 16:9-Bild (top + aspect-ratio statt inset:0): die Hinweiszeile darunter liegt
   im selben .player und bleibt lesbar. z-index, weil das <video> beim Einblenden (opacity)
   einen eigenen Stapel bildet und sonst ueber dem Knopf laege. */
.vsperre{position:absolute;left:0;right:0;top:0;aspect-ratio:16/9;z-index:1;display:flex;
  flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:12px;
  background:rgba(246,242,243,.82);cursor:pointer;text-align:center}
.vsperre[hidden]{display:none}
.vsperre-schloss{font-size:22px;line-height:1}
.vsperre-knopf{max-width:100%}

/* Sanftes Einblenden der fertigen Kachel (video.js posterLaden setzt .vposter-da).
   Den Grundton liefert .player oben — dadurch ist auch der Zustand VOR dem Fade
   korrekt hell, und ein hängendes Poster kann nie Dunkles zeigen. */
video[data-video]{opacity:0;transition:opacity .25s ease}
video[data-video].vposter-da{opacity:1}
@media (prefers-reduced-motion: reduce){video[data-video]{transition:none}}
html.noanim video[data-video]{transition:none}

/* Vorlese-Knopf (02.09.2026): sitzt unauffällig an der fertigen Antwort. Bewusst KEIN
   Blickfang — wer ihn sucht, findet ihn; wer liest, wird nicht abgelenkt. */
.msg.bot{position:relative}
.vl-btn{position:absolute;top:6px;right:6px;width:28px;height:28px;border-radius:50%;
  border:1px solid var(--line);background:var(--card);font-size:13px;line-height:1;
  cursor:pointer;opacity:.45;transition:opacity var(--t-fast),background var(--t-fast)}
.msg.bot:hover .vl-btn,.vl-btn:focus-visible{opacity:1}
.vl-btn:hover{background:var(--maroon);color:#fff;border-color:var(--maroon)}
/* Waehrend die Serverstimme geholt wird (07.09.2026): der Knopf ist voll sichtbar,
   auch ohne Mauszeiger darauf. Ein Sanduhr-Symbol bei 45 % Deckkraft sieht aus wie
   ein toter Knopf — und genau in dieser einen Sekunde schaut der Lernende hin. */
.vl-btn[aria-busy="true"]{opacity:1;cursor:progress}

/* ===== Handy-Feinschliff (Dom 03.09.2026, alles bei 375 px nachgemessen) ============
   Drei Stellen hatten zu wenig Platz. Gemessen statt geschaetzt:
     Rang-Pillen  3 x 97 px + 14 px Abstand = 305 px in einer 300-px-Zeile,
                  fuer den Text blieben ~50 px -> „Bronze0/5" klebte zusammen.
     Fokus-Leiste 333 px Inhalt in 329 px Kasten (+4), mit offenem Auswahlfeld mehr.
     Wochen-Kopf  der Titel bekam nur 112 px, weil das Abzeichen 92 px nahm — daher
                  die zerrissenen Zeilen („Woche 1 · Grundlagen / Zentralmatura, …"). */
@media(max-width:560px){
  /* Raenge: kleineres Zeichen, engere Polsterung, Name darf kuerzen statt kollidieren. */
  #rankRow{gap:6px}
  .rankpill{padding:6px;gap:5px}
  .rankpill .rg{width:20px;height:20px}
  .rankpill .rg .rgem{font-size:13px}
  .rankpill .rbt{font-size:10px;gap:4px}
  .rankpill .rbt span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .rankpill .rbt b{flex:none}

  /* Fokus-Leiste: das Wort „Fokus-Timer" traegt schon die Flamme daneben; die Leiste
     darf umbrechen, damit das Auswahlfeld nicht die Knoepfe hinausdraengt. */
  #focusBar{flex-wrap:wrap;gap:8px;padding:9px 11px}
  #focusBar .fb-l{display:none}
  #focusBar .fb-btns{gap:5px}
  #focusBar .fb-btns button{width:32px;height:32px;font-size:13px}
  #focusBar .fb-sel{max-width:100%}

  /* Wochen-Kopf: das Abzeichen rutscht in die naechste Zeile, statt den Titel zu
     zerquetschen. Der Titel behaelt so seine ganze Breite. */
  .week-head{flex-wrap:wrap;gap:9px 11px}
  .week-head .wt{flex:1 1 60%;min-width:0}
  .week-head .badge{order:3;margin-left:44px}
  .week-head .chev{order:2;margin-left:auto}

  /* Vergroessern-Knopf: am Handy gibt es keine zwei Spalten, also nichts zu vergroessern
     (Dom: „bringt ja nichts auf nem handy"). */
  #planGross,#chatGross{display:none!important}

  /* Tagesmission: Titel, Zeitangabe und Zaehler standen in EINER Zeile — bei 375 px
     brach „13 Etappen · ≈ 153 min" mitten im Wort um. Jetzt Titel oben, darunter die
     Zeitangabe; der Zaehler bleibt rechts oben auf Titelhoehe (Dom 03.09.2026). */
  #missionBar .mh{flex-wrap:wrap;column-gap:9px;row-gap:2px}
  #missionBar .mh .mt{flex:1 1 auto}
  #missionBar .mh .mc{margin-left:auto;order:2}
  #missionBar .mh .ms{flex:1 1 100%;order:3}

  /* Etappen-Titel duerfen am Handy ZWEI Zeilen haben statt abzubrechen. „Testfrage:
     Grundlagen …" und „Aufgabenpool Teil A: G…" sahen abgeschnitten nach Platzhalter aus
     (Dom 03.09.2026: „sieht nach mockup artefakten aus") — es sind echte Etappen, ihnen
     fehlte nur die Zeile. */
  .tmain .tt{white-space:normal;overflow:visible;display:-webkit-box;-webkit-line-clamp:2;
    -webkit-box-orient:vertical;overflow:hidden;line-height:1.3}
}

/* Die feste Leiste unten „driftet" beim Scrollen (Dom-Fund 03.09.2026). Ursache ist die
   Milchglas-Flaeche: `backdrop-filter` zwingt den Browser, bei JEDER Scroll-Bewegung den
   Bereich dahinter neu zu filtern — auf einem Handy hinkt das dem Scrollen hinterher, die
   Leiste scheint zu wandern. Eine eigene Kompositor-Ebene (`translateZ(0)` + `will-change`)
   nimmt sie aus diesem Takt heraus. Was davon bleibt: das Ein- und Ausblenden der
   Adressleiste verschiebt JEDES `position:fixed`-Element — das kann keine App abfangen. */
#tabbar,#ctaBar{transform:translateZ(0);will-change:transform;backface-visibility:hidden}
/* Und der Riegel gegen das seitliche Verrutschen: die Ursache (Raster) ist behoben, aber
   ein einzelnes zu breites Kind wuerde die ganze Seite wieder seitlich scrollbar machen —
   `clip` verhindert das, ohne `position:sticky` zu brechen (anders als `hidden`). */
html{overflow-x:clip}

/* Beschreibung unter dem Video (09.09.2026, Philipp Huber): zugeklappt eine Zeile, offen
   der Text von der Website. <details> bringt Tastatur und Ansage mit — deshalb bleibt es
   ein <details> und wird nicht nachgebaut. */
.vbeschreibung{margin:8px 0 0;border:1px solid var(--line);border-radius:var(--r-sm);background:var(--bg-2)}
.vbeschreibung-titel{cursor:pointer;padding:8px 12px;font-size:13px;font-weight:600;color:var(--ink-2);list-style:none}
.vbeschreibung-titel::-webkit-details-marker{display:none}
.vbeschreibung-titel::before{content:"▸ ";color:var(--maroon-light)}
.vbeschreibung[open] .vbeschreibung-titel::before{content:"▾ "}
.vbeschreibung-titel:hover{color:var(--ink)}
.vbeschreibung-titel:focus-visible{outline:3px solid var(--focus);outline-offset:2px}
.vbeschreibung-text{padding:0 12px 11px;font-size:13.5px;line-height:1.55;color:var(--ink);white-space:pre-line}
