/*
 * Klassenblick - eine Stylesheet-Datei, kein Praeprozessor.
 *
 * Der Entwurf orientiert sich am Kursheft: papierne Kacheln auf dunklem Grund.
 * Keine Dashboard-Aesthetik, keine Schatten, keine Verlaeufe. Saettigung tritt
 * ausschliesslich in den Marker-Farben auf (SPEC.md 4).
 */

@import url('/css/fonts.css');

/* --- Tokens (SPEC.md 4.1) ----------------------------------------------- */

:root {
  --ground:        #1F2A33;  /* Hintergrund, tiefes Schiefergrau-Blau */
  --ground-raised: #2A3742;  /* Leisten, Kopfzeile */
  --paper:         #F7F5F0;  /* Sitzkacheln */
  --paper-edge:    #DDD8CE;  /* Kachelkante */
  --ink:           #1A222A;  /* Text auf Papier */
  --ink-muted:     #6B7681;

  --signal-plus:   #2F6F6B;  /* Meldung - gedecktes Petrol */
  --signal-strong: #7A5CA8;  /* Guter Beitrag - Violett */
  --signal-minus:  #A32E3C;  /* Störung - Weinrot */
  --signal-warn:   #B57A1F;  /* Material fehlt - Ocker */

  --focus:         #F0C24B;  /* Tastaturfokus, hoher Kontrast auf beiden Gründen */

  --font-display: 'Space Grotesk', system-ui, sans-serif;
  --font-text:    'Source Sans 3', system-ui, sans-serif;
  --font-digits:  'IBM Plex Mono', ui-monospace, monospace;

  --radius: 6px;
  --touch:  56px;   /* Untergrenze für Touch-Ziele (SPEC.md 6) */
}

/* --- Grundlagen --------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

/* Das Browser-Stylesheet setzt [hidden] { display: none }, aber JEDE eigene
   display-Regel schlaegt es - unabhaengig von der Spezifitaet. `.toolbar` ist
   `display: flex`, also blieb `#seating-tools.hidden = true` im
   Einrichtungsmodus wirkungslos und die Reiter standen weiter da. Seit
   `.button` ein eigenes display hat, traefe es dort genauso. */
[hidden] { display: none !important; }

body {
  margin: 0;
  min-height: 100dvh;
  background: var(--ground);
  color: var(--paper);
  font-family: var(--font-text);
  font-size: 1rem;
  line-height: 1.5;
  -webkit-text-size-adjust: 100%;
}

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: -0.01em;
  margin: 0 0 0.5rem;
}

/* Tabellenziffern: In Zahlenspalten müssen die Stellen untereinander stehen,
   sonst lassen sich Spalten nicht mit dem Auge vergleichen (SPEC.md 4.2). */
.digits, td.num, .count {
  font-family: var(--font-digits);
  font-variant-numeric: tabular-nums;
}

a { color: inherit; }

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

button, input, select, textarea {
  font: inherit;
  color: inherit;
}

/* --- Kopfzeile ---------------------------------------------------------- */

.topbar {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.75rem 1rem;
  background: var(--ground-raised);
  border-bottom: 1px solid rgb(0 0 0 / 0.25);
}

.topbar__title {
  font-family: var(--font-display);
  font-size: 1.125rem;
  margin: 0;
}

.topbar__spacer { flex: 1; }

/* --- Flächen und Formulare ---------------------------------------------- */

.page {
  max-width: 60rem;
  margin: 0 auto;
  padding: 1.5rem 1rem 4rem;
}

.card {
  background: var(--ground-raised);
  border: 1px solid rgb(0 0 0 / 0.25);
  border-radius: var(--radius);
  padding: 1.25rem;
  margin-bottom: 1.5rem;
}

.field {
  display: grid;
  gap: 0.25rem;
  margin-bottom: 0.75rem;
}

.field__label {
  font-size: 0.875rem;
  color: var(--ink-muted);
}

input[type='text'],
input[type='password'],
input[type='number'],
textarea,
select {
  min-height: var(--touch);
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--paper-edge);
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--ink);
  width: 100%;
}

textarea {
  min-height: 10rem;
  font-family: var(--font-text);
  resize: vertical;
}

.row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

.row > * { flex: 1 1 12rem; }

/* --- Knöpfe ------------------------------------------------------------- */

.button {
  /* Ein <button> bekommt seine zentrierte Beschriftung vom Browser geschenkt,
     ein <a> nicht: weder das text-align: center noch die senkrechte Mitte. Wer
     dieselbe Klasse auf beide legt, muss die Zentrierung deshalb hier
     hinschreiben. Ohne diese vier Zeilen sass der Text in jedem <a class=button>
     31 px zu hoch und in einer breiten Zeile ganz links. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  text-align: center;
  text-decoration: none;

  min-height: var(--touch);
  padding: 0 1.125rem;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: var(--signal-plus);
  color: var(--paper);
  font-weight: 600;
  cursor: pointer;
}

.button--quiet {
  background: transparent;
  border-color: var(--ink-muted);
  color: var(--paper);
  font-weight: 400;
}

.button--danger { background: var(--signal-minus); }

/* Ein Umschalter muss ansehen lassen, ob er an ist.
   Der Diskretionsschalter trug bisher nur `aria-pressed` - fuer eine
   Vorlesesoftware genug, fuer das Auge nichts. Man sah dem Knopf nicht an, ob
   die Zaehlungen gerade verdeckt sind, und die Wirkung selbst ist unsichtbar,
   solange niemand eine negative Zaehlung hat (SPEC.md 7.4).
   Nicht nur die Farbe: Der staerkere Schriftschnitt traegt den Zustand auch
   dorthin, wo Farbe nicht ankommt. */
.button[aria-pressed='true'] {
  background: var(--signal-plus);
  border-color: var(--signal-plus);
  color: var(--paper);
  font-weight: 600;
}

.button:disabled { opacity: 0.55; cursor: not-allowed; }

/* --- Listen und Tabellen ------------------------------------------------ */

.list { list-style: none; margin: 0; padding: 0; }

.list__item {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.75rem 0;
  border-bottom: 1px solid rgb(255 255 255 / 0.08);
}

.list__item:last-child { border-bottom: none; }

.list__title {
  font-family: var(--font-display);
  font-size: 1.0625rem;
}

.list__meta {
  color: var(--ink-muted);
  font-size: 0.875rem;
}

/* Die ganze Klassenzeile fuehrt auf ihre Seite - nicht nur der Name.
   Ein Ziel von der Groesse eines Wortes trifft man auf dem iPad nicht. */
.list__link {
  display: block;
  color: inherit;
  text-decoration: none;
  padding: 0.25rem 0;
  border-radius: var(--radius);
}

.list__link:hover .list__title { color: var(--signal-plus); }
.list__link:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

/* Abgegangene bleiben sichtbar, aber deutlich abgesetzt: Sie stehen noch in
   der Auswertung des Halbjahres, gehoeren aber nicht mehr in die Klasse. */
.list__item--gone { opacity: 0.55; }
.list__item--gone .list__rename { text-decoration: line-through; }

.list__rename {
  font-family: var(--font-display);
  font-size: 1.0625rem;
  width: 100%;
  background: transparent;
  border: 1px solid transparent;
  padding: 0.125rem 0.375rem;
  margin-left: -0.375rem;
}

.list__rename:hover { border-color: rgb(255 255 255 / 0.14); }
.list__rename:focus { border-color: var(--focus); background: var(--ground-raised); }

table { width: 100%; border-collapse: collapse; }

th, td {
  text-align: left;
  padding: 0.5rem 0.5rem 0.5rem 0;
  border-bottom: 1px solid rgb(255 255 255 / 0.08);
}

th { color: var(--ink-muted); font-weight: 600; font-size: 0.875rem; }

/* --- Meldungen ---------------------------------------------------------- */

.notice {
  padding: 0.625rem 0.875rem;
  border-radius: var(--radius);
  margin-bottom: 1rem;
  font-size: 0.9375rem;
}

.notice--error { background: var(--signal-minus); }
.notice--warn  { background: var(--signal-warn); color: var(--ink); }
.notice--ok    { background: var(--signal-plus); }

/* Leere Zustände zeigen genau einen nächsten Schritt - keine Illustrationen,
   keine aufmunternden Sätze (SPEC.md 5.6). */
.empty {
  text-align: center;
  padding: 2.5rem 1rem;
  color: var(--ink-muted);
}

.empty p { margin: 0 0 1rem; }

/* --- Anmeldung ---------------------------------------------------------- */

.login {
  width: min(22rem, calc(100vw - 2rem));
  margin: 0 auto;
  padding: 4rem 0;
}

.login h1 { text-align: center; margin-bottom: 1.5rem; font-size: 1.75rem; }
.login__form { display: grid; gap: 0.5rem; }
.login__label { font-size: 0.875rem; color: var(--ink-muted); }
.login__input { min-height: var(--touch); }
.login__button { margin-top: 0.5rem; }
.login__error {
  margin: 0.5rem 0 0;
  padding: 0.625rem 0.75rem;
  border-radius: var(--radius);
  background: var(--signal-minus);
  font-size: 0.9rem;
}

/* --- Bewegung ----------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* --- Sitzplan ----------------------------------------------------------- */

.page--wide { max-width: 78rem; }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Reiter und "Alle in die Ablage" gehoeren beide zur Sitzordnung, nicht zum
   Raum - deshalb stehen sie zusammen und verschwinden zusammen, sobald der
   Einrichtungsmodus laeuft. */
.toolbar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.75rem;
  flex-wrap: wrap;
}

.tabs {
  display: flex;
  gap: 0.25rem;
}

.tab {
  font: inherit;
  font-family: var(--font-display);
  min-height: var(--touch);
  padding: 0 1.25rem;
  border: 1px solid rgb(255 255 255 / 0.14);
  border-radius: var(--radius);
  background: transparent;
  color: var(--ink-muted);
  cursor: pointer;
}

.tab--on {
  background: var(--ground-raised);
  border-color: var(--signal-plus);
  color: var(--paper);
}

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

.seating {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 14rem;
  gap: 1.5rem;
  align-items: start;
}

@media (max-width: 52rem) {
  .seating { grid-template-columns: minmax(0, 1fr); }
}

.grid {
  /* Der Abstand ZWISCHEN Tischen. Er muss deutlich groesser sein als der
     (geschlossene) Abstand INNERHALB eines Tisches - sonst liest sich das
     Raster weiter als gleichmaessiges Gitter.

     Das Raster selbst laesst keinen Zwischenraum: Jede Kachel traegt die
     halbe Fuge als Innenabstand (siehe `.cell`). Nur so kann ein Tisch sie an
     der gemeinsamen Seite weglassen, ohne dass eine Haelfte groesser wird. */
  --grid-gap: 0.85rem;

  /* Der Abstand zwischen Tischplatte und Sitzkachel, und die Staerke der
     Plattenkante. Beides geht in die Mindesthoehe der Kachel ein - deshalb
     stehen die Werte hier und nicht verstreut in den Regeln. */
  --plate-pad: 3px;
  --plate-edge: 1px;

  display: grid;
  grid-template-columns: repeat(var(--cols, 10), minmax(0, 1fr));
  gap: 0;

  /* Ohne das scrollt die Seite beim Ziehen mit und der Plan lässt sich am
     iPad nicht bauen (SPEC.md 5.3). */
  touch-action: none;
}

/* Den Raum vom anderen Ende aus ansehen.
   Eine Drehung um 180 Grad, KEINE Spiegelung: Wer ans andere Ende geht und
   sich umdreht, sieht aus "vorne links" ein "hinten rechts". Eine Spiegelung
   an einer Achse vertauschte links und rechts, ohne vorn und hinten
   mitzunehmen - und zeigte damit einen Raum, den es nicht gibt.
   Die Kacheln werden gegengedreht, sonst stünden die Namen auf dem Kopf. */
.grid--flipped { transform: rotate(180deg); }
.grid--flipped .seat { transform: rotate(180deg); }

/* Der Tafelbalken muss die Seite wechseln, sonst drehen sich die Sitze um eine
   Tafel, die stehen bleibt - und der Plan behauptet, die Tafel sei weiterhin
   unten. Deshalb liegen Raster und Balken in einer Spalte, deren Richtung sich
   umkehren lässt. */
.seating__grid-wrap {
  display: flex;
  flex-direction: column;
}

.seating__grid-wrap--flipped { flex-direction: column-reverse; }

.seating__grid-wrap--flipped .blackboard {
  margin: 0 0 0.75rem;
  border-top: none;
  border-bottom: 2px solid var(--ink-muted);
}

/* Einrichtungsmodus: Der Raum wird umgebaut, nicht die Sitzordnung. Die
   Kacheln bleiben sichtbar - man muss sehen, was man umbaut - reagieren aber
   nicht mehr, damit ein Fingerstrich niemanden versetzt (SPEC.md 5.3). */
.grid--setup .seat {
  pointer-events: none;
  opacity: 0.4;
}

.grid--setup .cell { cursor: pointer; }

/* Die Fuge gehoert IN die Kachel, nicht zwischen die Kacheln.
   Vorher trennte `gap` die Kacheln, und ein Tisch zog die Fuge mit einem
   negativen Aussenrand zu. Das machte die linke Tischhaelfte um eine ganze
   Fuge breiter als die rechte, verschob die Naht aus der Tischmitte und liess
   senkrechte Tische ganz offen - Hoehe folgt hier dem Seitenverhaeltnis, und
   ein negativer Rand aendert sie nicht. Jetzt traegt jede Kachel ihre halbe
   Fuge selbst und laesst sie dort weg, wo der Tisch weitergeht: Beide Haelften
   wachsen um denselben Betrag, alle Kacheln bleiben gleich gross. */
.cell {
  aspect-ratio: 4 / 3;

  /* Hoch genug, dass die Sitzkachel mit ihrem Mindestmass (SPEC.md 6) samt
     Tischplatte und Fuge hineinpasst. Ist sie es nicht, waechst die Platte
     ueber ihre Kachel hinaus und die Tische schieben sich uebereinander. */
  min-height: calc(var(--touch) + var(--grid-gap) + 2 * (var(--plate-pad) + var(--plate-edge)));

  /* Pflicht neben `aspect-ratio`: Greift die Mindesthoehe - viele Spalten auf
     einem schmalen Schirm -, leitet das Seitenverhaeltnis die Breite aus der
     Hoehe ab, und die Kachel wird breiter als ihre Rasterspalte. Die Kacheln
     schoeben sich dann uebereinander, statt einfach flacher zu werden. */
  max-width: 100%;

  padding: calc(var(--grid-gap) / 2);
  display: grid;
  position: relative;
}

/* Die sichtbare Tischplatte. Die Kachel selbst zeichnet nichts mehr - sie
   haelt nur den Platz im Raster und die Fuge. */
.cell__plate {
  display: grid;
  position: relative;
  border: var(--plate-edge) dashed rgb(255 255 255 / 0.12);
  border-radius: var(--radius);
}

/* --- Tische ------------------------------------------------------------- */

/* Ein Tisch muss eine FLAECHE sein, kein Rahmen.
   Der erste Versuch zeichnete ihn als 1-px-Linie um die Zelle - unsichtbar,
   sobald eine Sitzkachel darauf liegt, denn die fuellt die Zelle randlos aus
   und verdeckt genau diese Linie. Jetzt traegt die Zelle eine hellere
   Tischplatte, und die Kachel liegt mit etwas Abstand darauf. */
.cell--table > .cell__plate {
  background: rgb(255 255 255 / 0.09);
  border: var(--plate-edge) solid rgb(255 255 255 / 0.34);
  padding: var(--plate-pad);
}

.cell--table .seat { border-radius: 3px; }

/* Die Auswahl steht VOR den Fugenregeln: Sonst zoege ihr Rahmen an der
   gemeinsamen Seite wieder eine Linie, und der ausgewaehlte Tisch fiele
   optisch in zwei Haelften auseinander. */
.cell--chosen > .cell__plate {
  border: 2px solid var(--focus);
  background: rgb(240 194 75 / 0.14);
  box-shadow: 0 0 0 3px rgb(240 194 75 / 0.30);
  z-index: 2;
}

.cell--chosen .seat { opacity: 0.75; }

/* Wo der Tisch weitergeht, faellt die halbe Fuge weg. Die beiden Platten
   stossen damit genau auf der Rasterlinie zusammen - also in der Tischmitte. */
.cell--join-right { padding-right: 0; }
.cell--join-left { padding-left: 0; }
.cell--join-down { padding-bottom: 0; }
.cell--join-up { padding-top: 0; }

.cell--join-right > .cell__plate {
  border-right: none;
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
}

.cell--join-left > .cell__plate {
  border-left: var(--plate-edge) solid rgb(255 255 255 / 0.16);   /* die Naht in der Tischmitte */
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
}

.cell--join-down > .cell__plate {
  border-bottom: none;
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}

.cell--join-up > .cell__plate {
  border-top: var(--plate-edge) solid rgb(255 255 255 / 0.16);
  border-top-left-radius: 0;
  border-top-right-radius: 0;
}

/* Rueckmeldung waehrend eines langen Tipps. Ohne sie merkt man erst, dass man
   zu lange gedrueckt hat, wenn die Zelle ploetzlich gesperrt ist - und weiss
   nicht, wodurch. Die Flaeche laeuft ueber die Druckdauer voll. */
.cell__plate::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--focus);
  opacity: 0;
  pointer-events: none;
}

.cell--pressing > .cell__plate::after {
  opacity: 0.3;
  transition: opacity 650ms linear;
}

/* Rechnerplatz: ein kleines Zeichen in der Ecke, mehr nicht. Die Kachel
   gehoert der Person, die dort sitzt, nicht dem Geraet. */
.cell--pc > .cell__plate::before {
  content: "";
  position: absolute;
  top: 0.25rem;
  right: 0.3rem;
  width: 0.6rem;
  height: 0.45rem;
  border: 1px solid rgb(255 255 255 / 0.35);
  border-bottom-width: 2px;
  border-radius: 1px;
  pointer-events: none;
  /* Ueber der Kachel: In der Variante "Aussen" ist jeder Platz belegt, und
     die Kachel verdeckte das Zeichen sonst vollstaendig. */
  z-index: 1;
}

.cell--blocked > .cell__plate {
  border-style: solid;
  border-color: transparent;
  background: rgb(0 0 0 / 0.22);
}

.cell--target > .cell__plate {
  border-color: var(--focus);
  border-style: solid;
  background: rgb(240 194 75 / 0.12);
}

.seat {
  display: grid;
  grid-template-rows: 1fr auto;
  gap: 0;
  width: 100%;
  min-height: var(--touch);
  padding: 0.375rem 0.5rem 0;
  border: 1px solid var(--paper-edge);
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-text);
  font-size: 0.9375rem;
  text-align: left;
  cursor: grab;
  overflow: hidden;
}

.seat__name {
  align-self: start;
  line-height: 1.2;
  overflow-wrap: anywhere;
}

/* Die Strichlisten-Kante. Gefüllt wird sie im Unterrichtsmodus (Phase 7). */
.seat__tally {
  height: 14px;
  margin: 0 -0.5rem;
  border-top: 1px solid var(--paper-edge);
}

.seat--held {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}

.seat--source { opacity: 0.35; }

/* Festgesetzt: sitzt in beiden Varianten gleich. Ein Schloss oben links -
   klein genug, um den Namen nicht zu stoeren (SPEC.md 5.3). */
.seat--pinned::before {
  content: "";
  position: absolute;
  top: 0.25rem;
  left: 0.3rem;
  width: 0.45rem;
  height: 0.35rem;
  border: 1px solid var(--ink-muted);
  border-top: none;
  border-radius: 0 0 1px 1px;
  box-shadow: 0 -0.22rem 0 -0.14rem var(--ink-muted);
  pointer-events: none;
}

/* Das Geisterbild folgt dem Zeiger. `pointer-events: none` ist Pflicht -
   sonst findet elementFromPoint immer nur das Geisterbild selbst. */
.seat--ghost {
  position: fixed;
  z-index: 20;
  transform: translate(-50%, -50%) rotate(2deg);
  pointer-events: none;
  box-shadow: 0 6px 18px rgb(0 0 0 / 0.45);
  opacity: 0.95;
}

.blackboard {
  margin: 0.75rem 0 0;
  padding: 0.375rem;
  text-align: center;
  font-family: var(--font-display);
  font-size: 0.8125rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
  border-top: 2px solid var(--ink-muted);
}

.tray {
  display: grid;

  /* Zwei Spalten in der Seitenleiste, im gestapelten Hochformat so viele wie
     hineinpassen. 32 Namen untereinander sind eine Liste, die man abliest -
     nebeneinander sind sie ein Vorrat, den man ueberblickt.
     6rem ist mit Bedacht gewaehlt: Die Seitenleiste ist 14rem breit, ab 7rem
     faellt die Ablage wieder auf eine einzige Spalte zurueck. */
  grid-template-columns: repeat(auto-fill, minmax(6rem, 1fr));
  gap: 0.5rem;
  min-height: 6rem;
  padding: 0.5rem;
  border: 1px dashed rgb(255 255 255 / 0.15);
  border-radius: var(--radius);
  touch-action: none;
}

/* Die Strichlisten-Kante bleibt im Sitzplan leer - gefuellt wird sie nur im
   Unterricht, und der baut seine Kacheln selbst. In der Ablage kostet sie
   15 px je Kachel und haelt die Kachel bei zwei Spalten unnoetig hoch. */
.tray .seat__tally { display: none; }

/* --- Unterrichtsmodus --------------------------------------------------- */

.lesson-page { padding-bottom: 6.5rem; }

.lesson {
  max-width: 78rem;
  margin: 0 auto;
  padding: 1rem;
}

.lesson-head { display: grid; }

.lesson-head__topic {
  border: none;
  background: none;
  padding: 0;
  color: var(--ink-muted);
  font-size: 0.8125rem;
  text-align: left;
  cursor: text;
}

.lesson-head__date { color: var(--ink-muted); font-size: 0.875rem; }

/* Im Unterricht verschwinden die leeren Zellen - aber NICHT die Tische. Die
   erste Fassung setzte `border-color: transparent` auf alle .cell und loeschte
   damit auch jede Tischkante; im Unterricht war von der Raumform nichts mehr
   zu sehen. */
.grid--lesson .cell:not(.cell--table) > .cell__plate { border-color: transparent; }
.grid--lesson .seat { cursor: pointer; }

/* Die Marker-Leiste sitzt am unteren Rand - auf Daumenhöhe, wenn das iPad
   im Stehen mit einer Hand gehalten wird (SPEC.md 5.4). */
.markerbar {
  position: fixed;
  inset: auto 0 0 0;
  display: flex;
  gap: 0.5rem;
  padding: 0.5rem 0.75rem calc(0.5rem + env(safe-area-inset-bottom));
  background: var(--ground-raised);
  border-top: 1px solid rgb(0 0 0 / 0.3);
}

.marker {
  flex: 1;
  min-height: var(--touch);
  display: grid;
  place-items: center;
  gap: 0.125rem;
  border: 2px solid transparent;
  border-radius: var(--radius);
  background: rgb(255 255 255 / 0.06);
  color: var(--paper);
  cursor: pointer;
}

.marker[aria-pressed='true'] {
  border-color: currentColor;
  background: color-mix(in srgb, currentColor 22%, transparent);
}

.marker__short {
  font-family: var(--font-display);
  font-size: 1.125rem;
  line-height: 1;
}

.marker__label { font-size: 0.6875rem; opacity: 0.8; }

/* --- Strichlisten-Kante ------------------------------------------------- */

.seat__tally {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  height: 14px;
  margin: 0 -0.5rem;
  padding: 0 0.375rem;
  border-top: 1px solid var(--paper-edge);
  overflow: hidden;
}

.tally { display: inline-flex; align-items: center; line-height: 1; }
.tally svg { display: block; }

.tally--discreet { color: var(--ink-muted); font-size: 0.75rem; letter-spacing: 0.15em; }

.tally__compact { display: inline-flex; align-items: center; gap: 0.125rem; }
.tally__factor { font-size: 0.625rem; }

/* --- Die drei Animationen (SPEC.md 4.4) --------------------------------- */

@keyframes seat-tap {
  50% { transform: scale(1.04); }
}

.seat--tapped { animation: seat-tap 120ms ease-out; }

@keyframes tally-in {
  from { transform: translateY(100%); opacity: 0; }
}

.tally--new { animation: tally-in 180ms ease-out; }

.seat--swiping { transform: translateX(-14px); transition: transform 120ms ease-out; }

/* --- Notiz-Ecke und Anwesenheit auf der Kachel -------------------------- */

/* Eine Ecke, kein Text: Im Diskretionsmodus soll erkennbar sein, DASS eine
   Notiz existiert, nicht was darin steht (SPEC.md 7.4). */
.seat--noted::after {
  content: '';
  position: absolute;
  top: 0; right: 0;
  border-width: 0 9px 9px 0;
  border-style: solid;
  border-color: transparent var(--ink-muted) transparent transparent;
}

.seat { position: relative; }

.seat--absent   { border-left: 4px solid var(--signal-minus); }
.seat--late     { border-left: 4px solid var(--signal-warn); }
.seat--excused  { border-left: 4px solid var(--ink-muted); }

/* --- Schülerblatt ------------------------------------------------------- */

/* Derselbe Kasten fuer jeden Dialog: Schuelerblatt, Startdialog, Rueckfrage.
   Geteilt statt kopiert - ein zweiter Kasten mit eigenen Werten waere nach der
   ersten Aenderung ein anderer Kasten. */
.sheet,
.dialog {
  width: min(30rem, calc(100vw - 2rem));
  max-height: 85dvh;
  padding: 1.25rem;
  border: 1px solid rgb(255 255 255 / 0.15);
  border-radius: 10px;
  background: var(--ground-raised);
  color: var(--paper);
  overflow-y: auto;
}

.sheet::backdrop,
.dialog::backdrop { background: rgb(0 0 0 / 0.6); }

.sheet__head {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1rem;
}

.sheet__head h2 { margin: 0; flex: 1; }

.sheet__markers { display: grid; gap: 0.375rem; margin-bottom: 1rem; }

.sheet__marker {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.25rem 0;
}

.sheet__marker-label { flex: 1; font-size: 0.9375rem; }
.sheet__marker-count { min-width: 1.5rem; text-align: right; }

.sheet__step {
  min-width: var(--touch);
  min-height: var(--touch);
  border: 1px solid var(--ink-muted);
  border-radius: var(--radius);
  background: transparent;
  color: var(--paper);
  font-size: 1.25rem;
  cursor: pointer;
}

.sheet__attendance {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  margin-bottom: 1rem;
}

.sheet__attendance-option {
  flex: 1 1 6rem;
  min-height: var(--touch);
  border: 1px solid var(--ink-muted);
  border-radius: var(--radius);
  background: transparent;
  color: var(--paper);
  cursor: pointer;
}

.sheet__attendance-option[aria-pressed='true'] {
  background: var(--signal-plus);
  border-color: var(--signal-plus);
}

.sheet__note { min-height: 6rem; margin-bottom: 1rem; }
.sheet__history-title { font-size: 1rem; margin: 1rem 0 0.25rem; }

/* --- Auswertung --------------------------------------------------------- */

.th-sort {
  border: none;
  background: none;
  padding: 0;
  color: inherit;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

td.num, th.num { text-align: right; }

/* Der Druckkopf gehoert aufs Papier, nicht auf den Schirm: Dort steht die
   Klasse schon in der Kopfzeile, und beim Schuelerblatt stuende der Name sonst
   zweimal untereinander. */
.print-head { display: none; margin-bottom: 1rem; }
.print-head h2 { margin: 0; }

/* Ein Knopf, der wie Text liest - der Name in der Tabelle fuehrt zum Blatt.
   Kein Symbol daneben: In einer Tabelle mit dreissig Zeilen waere es dreissig
   Mal dasselbe Zeichen. Die Unterstreichung traegt den Hinweis, dass hier etwas
   passiert, und ueberlebt auch die Umstellung auf Schwarzweiss beim Drucken. */
.cell-button {
  display: block;
  width: 100%;
  padding: 0.25rem 0;
  border: none;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

/* --- Schuelerblatt (SPEC.md 5.5, zweite Ebene) --------------------------- */

.report-sheet__name {
  font-size: 1.375rem;
  margin: 0 0 0.25rem;
}

.report-sheet__heading {
  font-size: 1rem;
  margin: 1.5rem 0 0.5rem;
}

/* Die Summen des Zeitraums. Auto-fill statt fester Spaltenzahl: Es sind so
   viele Marker, wie die Klasse hat, plus drei feste Posten. */
.report-sheet__figures {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(10.5rem, 1fr));
  gap: 0.5rem;
}

/* Umbrechend: "Anwesend 12 von 12" ist laenger als "Meldung 25" und drueckt
   sonst aus dem Kasten heraus in den naechsten hinein. */
.report-sheet__figure {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0 0.5rem;
  padding: 0.5rem 0.625rem;
  border: 1px solid rgb(255 255 255 / 0.1);
  border-radius: var(--radius);
}

.report-sheet__figure-label { color: var(--ink-muted); font-size: 0.9375rem; min-width: 0; }
.report-sheet__figure-value { font-size: 1.125rem; font-weight: 600; white-space: nowrap; }

.report-sheet__table { width: 100%; border-collapse: collapse; }

.report-sheet__day { white-space: nowrap; vertical-align: top; }
.report-sheet__topic { vertical-align: top; }
.report-sheet__marks { text-align: right; white-space: nowrap; vertical-align: top; }
.report-sheet__note { vertical-align: top; overflow-wrap: anywhere; }

.report-sheet__absence {
  display: block;
  color: var(--signal-warn);
  font-size: 0.8125rem;
}

/* Eine Stunde, in der zu dieser Person nichts vorgefallen ist. Sie bleibt
   stehen - eine Chronologie mit Luecken liesse offen, ob nichts war oder nichts
   erfasst wurde -, tritt aber zurueck. */
.report-sheet__row--empty { color: var(--ink-muted); }

/* Nur auf Papier: die mitlaufende Kopfzeile im <thead>. Ueber eine Klasse,
   nicht ueber das hidden-Attribut - `[hidden] { display: none !important }`
   liesse sich im Druck nicht mehr aufheben. */
.print-only { display: none; }

/* --- Dialoge: Unterricht starten, Stunde loeschen ------------------------ */

.dialog__title { margin: 0 0 0.25rem; font-size: 1.25rem; }
.dialog__meta { color: var(--ink-muted); font-size: 0.9375rem; margin: 0 0 1rem; }
.dialog__warning { margin: 0 0 0.5rem; }
.dialog__facts { margin: 0 0 1rem; padding-left: 1.25rem; }

.dialog__actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
  margin-top: 1.25rem;
  flex-wrap: wrap;
}

/* Der zweite Schritt der Rueckfrage tauscht die Seiten. Stuende der
   bestaetigende Knopf beide Male rechts, traefe ein Doppeltipp beide - und die
   doppelte Rueckfrage haette nur die Tippgeschwindigkeit geprueft. */
.dialog__actions--swapped { justify-content: flex-start; }

/* --- Stundenliste (SPEC.md 5.5) ----------------------------------------- */

.card > .tabs { margin-bottom: 1rem; }

.lesson-row__body { flex: 1; min-width: 0; }

.lesson-row__note {
  margin: 0.25rem 0 0;
  color: var(--ink-muted);
  font-size: 0.875rem;
  overflow-wrap: anywhere;
}

/* Eine Stunde ohne jeden Eintrag ist meistens die versehentlich gestartete.
   Sie tritt zurueck, verschwindet aber nicht - geloescht wird von Hand. */
.lesson-row--empty .list__title { color: var(--ink-muted); }

/* --- Druck (SPEC.md 5.5) ------------------------------------------------ */

@media print {
  /* Navigation und Bedienelemente verschwinden - auf Papier gehört nur der
     Inhalt, und ein Ausdruck fürs Elterngespräch ist kein Screenshot. */
  .topbar, .no-print, .markerbar { display: none !important; }

  body {
    background: #fff;
    color: #000;
    font-size: 11pt;
  }

  .page { max-width: none; padding: 0; }

  .card {
    background: none;
    border: none;
    padding: 0;
    margin: 0;
  }

  th, td {
    border-bottom: 1px solid #ccc;
    color: #000 !important;
  }

  a[href]::after { content: none; }

  /* Ohne Angabe druckt der Browser sein Vorgabeformat - in der Messung Letter
     statt A4, mit abgeschnittener rechter Spalte. */
  @page { size: A4 portrait; margin: 16mm 14mm; }

  tr { break-inside: avoid; }

  /* Die Kopfzeile im <thead> wiederholt der Browser auf jeder Seite, den
     Druckkopf darueber nicht. Ein Blatt, das ueber den Tisch geschoben wird,
     traegt den Namen sonst ab Seite 2 nicht mehr. */
  .print-head { display: block; }

  .print-only { display: table-row; }

  /* Die mitlaufende Kopfzeile ist eine Kopfzeile, keine zweite Ueberschrift. */
  .print-only th {
    font-weight: 400;
    font-size: 9pt;
    text-align: left;
    border-bottom: none;
  }

  .report-sheet__figures { grid-template-columns: repeat(4, 1fr); }
  .report-sheet__figure { border-color: #999; }
  .report-sheet__figure-label { color: #000; }

  /* Die Farbe der Marker traegt die Zuordnung im Ausdruck NICHT: `th, td`
     setzt oben `color: #000 !important`, und das bleibt so. Zwei der vier
     Standardmarker verfehlen auf Weiss die 4,5:1 aus SPEC.md 6. Statt der
     Farbe traegt die Legende unter der Tabelle die Zuordnung. */
  .report-sheet__row--empty { color: #555 !important; }

  /* Der gedaempfte Grauton der Oberflaeche traegt auf Papier nicht mehr:
     Er erreicht auf Weiss knapp 4,6:1 und faellt im Kopierer weiter ab. */
  .list__meta, .lesson-row--empty .list__title { color: #555 !important; }
  .list__item { border-bottom: 1px solid #bbb; }
  .report-sheet__absence { color: #000 !important; }
}

/* --- Anzeige „n nicht gesendet" ---------------------------------------- */

.pending {
  min-height: 40px;
  padding: 0 0.75rem;
  border: 1px solid var(--signal-warn);
  border-radius: var(--radius);
  background: transparent;
  color: var(--signal-warn);
  font-size: 0.8125rem;
  cursor: pointer;
}
