/* ============================================================
   MinuteStudio — the whole visible surface.

   The design has a name so that decisions can be argued against it:
   **Plakat**. A shelf of posters, not a sheet of paper. Flat grounds in
   four tints, shapes on them, one heavy condensed voice that shouts
   and one light voice beside it, ink on tint, and a card that turns
   over in your hand. It grew out of the catalogue: the course card was
   designed first, it was better than the pages around it, and the
   pages followed the card.

   Six rules hold it together:

   1. Ink borders, never shadows. A raised surface is drawn, not lit.
      `--strich` (2px) marks anything you touch, a hairline anything you
      only read.
   2. One accent, four grounds. `--roetel` is the only colour that *acts*:
      it means "now" — today, the beat, the milestone, an error. The four
      tints never act and never carry text; they are grounds, and since
      the posters they are shapes too. Anything you press is still ink.
   3. Grotesk shouts, sans reads, mono counts. Three voices. Every title
      is set in two of them at once — the first word in the poster cut,
      the rest in the sans at its lightest, or the other way round for a
      course, which decides that from its id. Prose is the sans.
   4. Radius says what a thing is: pills are pressed, cards are held,
      rules are neither.
   5. The window says how much room there is, the content says how much of
      it to take. A course text keeps the measure however wide the screen
      gets; a catalogue takes the width. See "Width and room" below.
   6. A course is a poster, and it is the same poster everywhere: its
      tint, its cover printed across it or its composition, its name in
      two voices, its theme in the corner. In the catalogue and the
      planner it turns over; at the head of its page it is grown to the
      width of the page.

   Tokens come in one set with two fillings. The scheme hangs off
   data-theme on <html>; without it the operating system decides. */

/* ---------------------------------------------------------- Typefaces
   Self-hosted, because the content policy in src/core/schutz.js says
   font-src 'self' and a webfont from a CDN would have to loosen it.
   The subsets are gated by unicode-range: a German or English page
   fetches latin only and never sees the latin-ext files.

   Three faces. Figtree is the variable weight build and does most of the
   work: prose at 400, the quiet half of a title at 300, labels at 600.
   Bricolage Grotesque is one static cut, condensed and heavy, for the
   loud half of a title and for section headings. Plex Mono at 400 for
   anything that is counted. No italic anywhere: emphasis is weight. */
@font-face{font-family:Figtree;font-style:normal;font-weight:300 900;font-display:swap;
  src:url(/marke/schrift/figtree-latin-wght-normal.woff2) format('woff2-variations');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:Figtree;font-style:normal;font-weight:300 900;font-display:swap;
  src:url(/marke/schrift/figtree-latin-ext-wght-normal.woff2) format('woff2-variations');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
/* The poster cut, for the loud half of every title. One static instance —
   weight 800, width 75 % — rather than the three-axis variable file, which
   is six times the size for axes a title never moves. Preloaded, since the
   first word of the first heading is set in it. */
@font-face{font-family:'Bricolage Grotesque';font-style:normal;font-weight:800;font-stretch:75%;font-display:swap;
  src:url(/marke/schrift/bricolage-grotesque-latin-800-condensed.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'Bricolage Grotesque';font-style:normal;font-weight:800;font-stretch:75%;font-display:swap;
  src:url(/marke/schrift/bricolage-grotesque-latin-ext-800-condensed.woff2) format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:'Plex Mono';font-style:normal;font-weight:400;font-display:swap;
  src:url(/marke/schrift/ibm-plex-mono-latin-400-normal.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'Plex Mono';font-style:normal;font-weight:400;font-display:swap;
  src:url(/marke/schrift/ibm-plex-mono-latin-ext-400-normal.woff2) format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}

/* ------------------------------------------------------------ Tokens
   The text colours are measured against their ground, not guessed.
   --grau carries .hinweis (12px) and .marke (10px) and therefore stands
   at body-text size: it needs 4.5:1 under WCAG AA, and so do --graphit,
   --payne, --roetel and --gold, on all three paper tones. The check is
   in tests/oberflaeche.test.mjs and it reads the values out of this
   file. Whoever changes them measures again.

   --nacht is the one colour that does not flip with the scheme. The
   landing page alternates cream and ink bands, and an ink band that
   turns cream in dark mode is not a band any more. */
:root{
  --papier:#FAFAF8; --papier-hell:#FFFFFF; --papier-tief:#F0EFEB;
  --tinte:#161616; --graphit:#454440; --grau:#4C4A46;
  --linie:rgba(22,22,22,.16); --linie-zart:rgba(22,22,22,.08);
  --payne:#1746A2; --roetel:#C7200F; --gold:#806012;
  /* The metal has two values, the way the tints do: --gold is brass as ink,
     dark enough to carry 4.5:1 as text on paper, and --gold-hell is brass as
     a *surface* — the face of a struck medal, with the figure knocked out of
     it in --nacht. The ink value cannot be a surface (white on it fails) and
     the surface value cannot be ink (1.86:1 on paper, 1.03 on a washed
     amethyst), so neither is a brightened or darkened version of the other to
     be folded back in. It is declared **once**, here, and deliberately not
     overridden below: paper and ink swap with the scheme because the page
     turns over, and brass does not — a medal is the same metal under a lamp
     as in daylight. tests/oberflaeche.test.mjs fails if a second declaration
     of it ever appears. */
  --gold-hell:#E0B44A;
  --salbei:#00916A; --lavendel:#8B4FD8; --apricot:#F5A300; --himmel:#0E8FB8;
  --wasch:44%; --wasch-stark:64%; --druck:44%; --geometrie:100%; --schleier:56%;
  --nacht:#161616; --nacht-text:#FAFAF8; --nacht-grau:#A9A69F; --nacht-linie:rgba(250,250,248,.20);

  --sans:Figtree,ui-sans-serif,-apple-system,'Helvetica Neue',Helvetica,Arial,sans-serif;
  --mono:'Plex Mono',ui-monospace,'SF Mono',SFMono-Regular,Menlo,Consolas,monospace;
  --plakat:'Bricolage Grotesque','Arial Narrow','Helvetica Neue',Helvetica,Arial,sans-serif;

  /* One drawn line for everything you can touch, a hairline for
     everything you only read. */
  --strich:2px;
  /* And a third thing, which is not a line at all: the mat a finished course's
     card is mounted in. A border this wide has stopped being a stroke and
     become a surface, so it is named rather than left as a --strich somebody
     kept increasing — the two weights above are about what you may *do* with a
     thing, and this one is about what a thing *is*. It is the only one. */
  --passepartout:7px;
  --rund:5px; --rund-gross:18px; --rund-voll:999px;
  --sp:1.5rem;

  /* --------------------------------------------------- Width and room
     One column was never a design decision, it was the phone showing
     through. A reading measure is right for prose and wrong for a
     catalogue, and the page has to be able to say which it is.

     Four widths, and each of them means something:

       --spalte  35rem  the measure. Prose, forms, a course text. About
                        70 characters, which is where a line stops being
                        comfortable to come back from.
       --mittel  58rem  a measure with a companion beside it — a column
                        of text at 35rem and a rail of 20rem. A course
                        page: the text is the point, and the rail only
                        carries what belongs next to it.
       --weit    76rem  something you scan rather than read: the
                        catalogue's cards, the notebook, the account's
                        three subscriptions beside each other, the
                        editor, a table in the administration.
       --schiene        how much room the navigation takes at the left.
                        Zero on a phone, where it is a bar at the bottom.

     The steps are named after what fits, not after a device, and they
     are in rem so that someone who enlarges their text gets the narrow
     layout rather than a squeezed wide one:

       under 48rem   compact   one column, tabs at the bottom
       from  48rem   medium    a rail of icons at the left
       from  64rem   weit      side columns appear inside the views
       from  72rem   gross     the rail writes its labels out
       from  90rem   sehr      nothing grows any further; the page
                               stops and the paper widens around it

     The rail widens *after* the side columns appear, and deliberately:
     the other way round the room left for the content would shrink at
     72rem and a two-column view would fall back to one just as the
     window got bigger.

     --rand is the gutter, and it grows with the window: 1.35rem against
     the edge of a phone, 2.6rem on a desk, so a wide page does not look
     as though it were bleeding off the screen. */
  --spalte:35rem; --mittel:58rem; --weit:76rem;
  --rand:clamp(1.35rem,.7rem + 1.8vw,2.6rem);
  --schiene:0px;
  --schwung:cubic-bezier(.22,.9,.28,1);
  color-scheme:light;
}
:root[data-theme="dark"]{
  --papier:#111111; --papier-hell:#1B1B1B; --papier-tief:#0A0A0A;
  --tinte:#F3F2EE; --graphit:#B9B6AF; --grau:#A8A59E;
  --linie:rgba(243,242,238,.20); --linie-zart:rgba(243,242,238,.10);
  --payne:#6FA8FF; --roetel:#FF5A45; --gold:#E0B44A;
  --salbei:#006A4E; --lavendel:#5A2E96; --apricot:#A87000; --himmel:#0A6A88;
  --wasch:26%; --wasch-stark:38%; --druck:24%; --geometrie:90%; --schleier:70%;
  --nacht:#0A0A0A; --nacht-text:#F3F2EE; --nacht-grau:#9A978F; --nacht-linie:rgba(243,242,238,.18);
  color-scheme:dark;
}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){
    --papier:#111111; --papier-hell:#1B1B1B; --papier-tief:#0A0A0A;
    --tinte:#F3F2EE; --graphit:#B9B6AF; --grau:#A8A59E;
    --linie:rgba(243,242,238,.20); --linie-zart:rgba(243,242,238,.10);
    --payne:#6FA8FF; --roetel:#FF5A45; --gold:#E0B44A;
    --salbei:#006A4E; --lavendel:#5A2E96; --apricot:#A87000; --himmel:#0A6A88;
    --wasch:26%; --wasch-stark:38%; --druck:24%; --geometrie:90%; --schleier:70%;
    --nacht:#0A0A0A; --nacht-text:#F3F2EE; --nacht-grau:#9A978F; --nacht-linie:rgba(243,242,238,.18);
    color-scheme:dark;
  }
}

/* -------------------------------------------------------------- Base */
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
[hidden]{display:none!important}
html,body{margin:0;padding:0}
html{scroll-behavior:smooth}
body{background:var(--papier);color:var(--tinte);font-family:var(--sans);font-size:16.5px;line-height:1.6;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;overscroll-behavior-y:none;
  /* The bands on the launch page reach past the reading column with a
     negative margin. Without this a phone can scroll sideways by the
     width of a scrollbar. */
  overflow-x:clip}
button{font:inherit;color:inherit;background:none;border:none;padding:0;cursor:pointer}
button:disabled{cursor:default}
input,textarea,select{font:inherit;color:inherit}
a{color:inherit}
::selection{background:var(--salbei);color:var(--tinte)}
:focus-visible{outline:2px solid var(--payne);outline-offset:3px;border-radius:2px}

/* ------------------------------------------------------------ The sheet
   The page is a padded field with one column standing in the middle of
   it, and the column's width is the view's decision. The width is
   published on <body> rather than kept here, because the header and the
   signpost have to line up with it and they are not inside the sheet.

   The grid is what does the centring: one track, as wide as --breite
   allows, placed in the middle of whatever room is left once the rail
   at the left and the gutters have taken theirs. A view puts exactly
   one node in here, so one track is all that is ever needed. */
body{--breite:var(--spalte)}
body:has(.blatt.weit){--breite:var(--weit)}
body:has(.blatt.mittel){--breite:var(--mittel)}
/* The launch page lays out its own bands at 72rem; the header follows them. */
body:has(.blatt.voll){--breite:72rem}

.blatt{display:grid;grid-template-columns:minmax(0,var(--breite));justify-content:center;
  padding:calc(env(safe-area-inset-top) + 1.8rem) var(--rand) 7.5rem;
  padding-left:calc(var(--schiene) + var(--rand))}
/* The launch page runs edge to edge and lays out its own bands. It also has
   no tab bar under it — nobody is signed in — so the column's landing strip
   at the bottom would only be a cream stripe under the last dark band. */
.blatt.voll{display:block;padding:0}
/* Prose inside a wide view keeps the measure: a catalogue may be 76rem, the
   sentence that introduces it may not. */
.mass{max-width:var(--spalte)}
/* `backwards` rather than `both`: after the run no transform declaration
   is left standing. One — even the identity matrix — makes every
   descendant `position:sticky` do nothing. */
.ansicht{animation:auf .45s var(--schwung) backwards}
@keyframes auf{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}

/* ------------------------------------------------------- Typography
   Grotesk shouts, sans reads, mono counts. The poster cut: the loud half
   of every title, and section headings on their own. The sans: prose,
   the quiet half of a title, anything in small caps, every button, every
   hint. The mono: clocks, day numbers, durations, prices — the things
   you compare down a column, which is why they are tabular. */
.marke{font-family:var(--sans);font-size:10.5px;font-weight:600;letter-spacing:.2em;text-transform:uppercase;
  color:var(--grau);display:block;margin-bottom:.6rem}
.titel{font-family:var(--plakat);font-weight:800;font-stretch:75%;font-size:1.7rem;line-height:1;
  letter-spacing:-.01em;margin:0 0 .7rem;text-wrap:balance}
.titel.gross{font-size:clamp(2.5rem,7vw,3.7rem)}
/* Two voices, stacked: the first word on its own line, the rest below it —
   stimmen() in ui.js writes them. Loud is the poster cut, quiet the label
   face at its lightest, the same size, so the contrast is weight and width
   rather than size and one measurement fits both on a card. Every title in
   the application has this shape; it is what makes a card in the catalogue
   and the head of a page the same design. */
.laut{display:block;font-family:var(--plakat);font-weight:800;font-stretch:75%;letter-spacing:-.01em;line-height:.9}
.leise{display:block;font-family:var(--sans);font-weight:300;letter-spacing:-.015em;line-height:1}
.laut+.leise{margin-top:.08em}
.leise+.laut{margin-top:.04em}
.unter{font-weight:300;font-size:1.18rem;color:var(--graphit);margin:0 0 1.7rem;line-height:1.45;text-wrap:pretty}
p{margin:0 0 1rem;text-wrap:pretty}
.zart{color:var(--graphit)}
.regel{height:1px;background:var(--linie);border:0;margin:2.4rem 0}
.hinweis{font-family:var(--sans);font-size:12px;font-weight:400;letter-spacing:.01em;color:var(--grau);line-height:1.6}
/* A hint that is a button gets a surface to hit — 12 pixels of text
   with no padding cannot be caught on a phone. */
button.hinweis{padding:.5rem .4rem;margin:-.5rem -.4rem;min-height:2.2rem;border-radius:var(--rund)}
button.hinweis:hover{color:var(--tinte)}
.formblock-knoepfe button.hinweis{min-width:2.2rem}
.mini{font-family:var(--sans);font-size:10.5px;font-weight:600;letter-spacing:.16em;text-transform:uppercase;color:var(--grau)}
.fehler{border-left:var(--strich) solid var(--roetel);padding:.6rem .9rem;margin:1rem 0;color:var(--roetel);
  font-family:var(--sans);font-size:.9rem;line-height:1.5}

/* ----------------------------------------------------------- Surfaces
   A card is drawn, not lit. The old rule was a shadow; a shadow needs a
   light source, and paper on a table has none that the screen agrees
   with. The border does the same work and survives the dark scheme
   without a second set of values. */
.karte{background:var(--papier-hell);border:1px solid var(--linie);border-radius:var(--rund-gross);
  padding:1.5rem 1.4rem}
.karte.stark{border-width:var(--strich);border-color:var(--tinte)}

/* --------------------------------------------------------- Buttons
   Pressed, not drawn on: a filled pill for the one thing to do next,
   an outlined pill for everything beside it. The 2px border is the
   signature — it is what makes an outlined button read as a button and
   not as a box of text. */
.knopf{display:block;width:100%;text-align:center;background:var(--tinte);color:var(--papier);
  border:var(--strich) solid var(--tinte);padding:.85rem 1.4rem;border-radius:var(--rund-voll);
  font-family:var(--sans);font-size:12.5px;font-weight:600;letter-spacing:.12em;text-transform:uppercase;
  transition:transform .18s var(--schwung),background .2s,color .2s,border-color .2s}
@media (hover:hover){
  .knopf:hover{transform:translateY(-1px)}
  .knopf.leise:hover{border-color:var(--tinte);color:var(--tinte);background:var(--papier-hell)}
}
.knopf:active{transform:translateY(0) scale(.985)}
a.knopf{text-decoration:none}
.knopf.leise{background:none;color:var(--graphit);border-color:var(--linie)}
.knopf.roetel{background:var(--roetel);border-color:var(--roetel);color:#FFFFFF}
.knopf[disabled]{opacity:.4;transform:none}
.knopf.schmal{display:inline-block;width:auto;padding:.5rem 1rem;font-size:11px;letter-spacing:.1em}
.werkzeug{display:flex;gap:.7rem;margin-top:1.2rem;flex-wrap:wrap}
.werkzeug .knopf{flex:1;min-width:10rem}
.werkzeug.senkrecht{flex-direction:column;gap:.5rem}
.werkzeug.senkrecht .knopf{flex:none}
.werkzeug .knopf.schmal{flex:0 0 auto;min-width:0}

/* Room above a block, in five steps. Views used to carry the value inline
   (`style="margin-top:.7rem"`, thirteen different values across the pages);
   a step is a decision the stylesheet makes once. */
.oben-0{margin-top:0}
.oben-1{margin-top:.4rem}
.oben-2{margin-top:.7rem}
.oben-3{margin-top:1rem}
.oben-4{margin-top:1.5rem}

/* ------------------------------------------------------------ Figures */
.zitat{font-weight:300;color:var(--graphit);font-size:1.12rem;line-height:1.5;
  border-left:1px solid var(--linie);padding-left:1.1rem;margin:0 0 1.4rem}
/* The tally. It draws the whole course now, so most of it is usually still
   ahead: a unit not done yet is the same stroke in --linie and filling it in is
   what finishing does. `--gb` is the width of one group — full size up to ten
   groups, smaller past that, so a hundred and fifty units stay a couple of rows
   inside a card instead of four. The gap follows it, or a shrunken group would
   sit in a hole the size of a full one. */
.strichliste{display:flex;flex-wrap:wrap;align-items:flex-start;
  gap:calc(var(--gb, 24px) * .23);color:var(--tinte)}
.strichliste svg{width:var(--gb, 24px);height:auto}
.strichliste .leer{stroke:var(--linie)}
/* The day strip across the top of the start page: twenty-eight strokes, one a
   day, as wide as whatever holds it. Twenty-eight of them whatever the history
   is, which is the whole reason it exists — the tally of every session ever
   that stood here wrapped into a column of loose marks down the side of a
   phone, and repeated a number that was already written beside it. */
.streifenband{width:100%;min-width:0}
.streifen{display:block;width:100%;height:18px;color:var(--tinte);max-width:24rem}
.streifen .leer{stroke:var(--linie)}
/* The stroke that is still being earned. --roetel means now, and today is the
   only thing in the drawing that can still change. */
.streifen .jetzt{stroke:var(--roetel)}
.streifen .jetzt.leer{stroke:var(--roetel);opacity:.5}
.streifenband>span{display:block;margin-top:.45rem;font-family:var(--sans);font-size:10px;
  font-weight:600;letter-spacing:.18em;text-transform:uppercase;color:var(--grau)}
.zahlen{display:flex;gap:2.4rem;margin:1.6rem 0 0;flex-wrap:wrap}
.zahl b{display:block;font-family:var(--mono);font-size:1.7rem;font-weight:400;line-height:1.1;
  font-variant-numeric:tabular-nums}
.zahl span{font-family:var(--sans);font-size:10px;font-weight:600;letter-spacing:.18em;text-transform:uppercase;color:var(--grau)}
/* The streak is the only one of the three figures that can still change
   today, and --roetel is the colour kept for exactly that. */
.zahl.jetzt b{color:var(--roetel)}

/* The three figures and the tally across the top of the start page. Under each
   other on a phone, side by side with a rule between them once there is room —
   the tally is a drawing of the first number, so they belong on one line. */
.zahlenband{display:flex;flex-wrap:wrap;align-items:center;gap:1.4rem 2.4rem;
  border-top:1px solid var(--linie);border-bottom:1px solid var(--linie);
  padding:1.3rem 0;margin:1.6rem 0 2rem}
/* On a phone the strip is its own row under the figures, full width, because
   it is a drawing of twenty-eight days and squeezing it into whatever the three
   numbers leave over is what broke the tally that stood here. Once there is
   room it takes the rest of the line beside them. */
.zahlenband .streifenband{flex:1 1 100%}
@media(min-width:48rem){ .zahlenband .streifenband{flex:1 1 16rem} }
/* Rules that separate sections in the one-column layout and would be a line
   through the middle of nothing once the sections stand beside each other. */
@media(min-width:64rem){ .nur-schmal{display:none} }

/* The courses under way. Three at most, so the row never wraps into a second. */
.weiter-raster{display:grid;grid-template-columns:repeat(auto-fill,minmax(16rem,1fr));gap:.9rem;margin-top:.4rem}
.weiterkarte{display:flex;flex-direction:column}
/* The button sits at the bottom edge whatever the title above it did, so a row
   of cards has one line of buttons rather than three. */
.weiterkarte .knopf{margin-top:auto}

/* ------------------------------------------------- The loading rule
   A thin line under the header for as long as a view is loading. It
   appears only after roughly two hundred milliseconds — a fast answer
   should not flicker. */
.ladebalken{position:fixed;left:0;right:0;top:0;height:2px;z-index:45;overflow:hidden;background:var(--linie-zart)}
.ladebalken::after{content:'';position:absolute;top:0;bottom:0;left:-40%;width:40%;background:var(--roetel);
  animation:laden 1s ease-in-out infinite}
@keyframes laden{to{left:100%}}

/* ============================================================
   The shell: header, signpost, tabs
   ============================================================ */

.kopfleiste{position:sticky;top:0;z-index:35;background:color-mix(in srgb,var(--papier) 88%,transparent);
  -webkit-backdrop-filter:saturate(140%) blur(14px);backdrop-filter:saturate(140%) blur(14px);
  border-bottom:1px solid var(--linie-zart);padding-top:env(safe-area-inset-top)}
/* The header lines up with whatever the view below it is: a reading column by
   default, the band width on the launch page, the editor's width in the
   editor. Without this the signpost sat in the middle of a page whose content
   started two hundred pixels to its left. Both read --breite off <body>, which
   is where the sheet publishes the width the current view asked for. */
.kopf-innen{max-width:var(--breite);margin:0 auto;padding:.7rem var(--rand);display:flex;align-items:center;
  justify-content:space-between;gap:1rem}

/* The word mark: the drawn mark, then the name. `Studio` in italic is
   the same distinction the logo makes — the minute is set, the studio
   is written. */
.wortmarke{display:inline-flex;align-items:center;gap:.55rem;font-family:var(--plakat);font-weight:800;
  font-stretch:75%;font-size:1.3rem;letter-spacing:-.01em;line-height:1;padding:.2rem;margin:-.2rem;
  border-radius:var(--rund);transition:opacity .2s}
.wortmarke:hover{opacity:.7}
.wortmarke em{font-style:normal;font-family:var(--sans);font-weight:300;font-stretch:100%;letter-spacing:-.02em}
.wortmarke .zeichen{width:22px;height:22px;flex:none;display:block}
.wortmarke .zeichen svg{width:100%;height:100%;display:block;stroke:var(--tinte);fill:none;
  stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}

.kopf-rechts{display:flex;align-items:center;gap:.4rem}
.kopfknopf{font-family:var(--sans);font-size:10.5px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;
  color:var(--grau);border:1px solid var(--linie);border-radius:var(--rund-voll);padding:.35rem .7rem;
  background:none;transition:border-color .18s,color .18s}
.kopfknopf:hover{border-color:var(--tinte);color:var(--tinte)}
select.sprachwahl{appearance:none;padding-right:.7rem;font-family:var(--mono);letter-spacing:.06em;
  text-transform:none;font-size:11px;font-weight:400}
/* On a narrow phone the two header controls together were as wide as the name
   they sit beside. The words stay — an icon for "colour scheme" would have to
   be learnt — but the setting they are given loses its air. */
@media(max-width:30rem){
  .kopf-innen{gap:.6rem}
  .kopfknopf{font-size:9.5px;letter-spacing:.08em;padding:.3rem .5rem}
  .wortmarke{font-size:1.02rem;gap:.45rem}
  .wortmarke .zeichen{width:19px;height:19px}
}

/* The signpost is centred exactly the way the sheet is — one track of --breite
   in the middle of whatever is left once the rail and the gutters have taken
   theirs — so the path and the title under it start at the same pixel. The row
   itself is the inner node, because a grid would otherwise stack the crumbs. */
.wegweiser{display:grid;grid-template-columns:minmax(0,var(--breite));justify-content:center;
  padding:0 var(--rand) .6rem;padding-left:calc(var(--schiene) + var(--rand))}
.weg-innen{display:flex;align-items:center;gap:.45rem;font-family:var(--sans);font-size:11.5px;
  letter-spacing:.03em;color:var(--grau);min-height:1.4rem}
.wegweiser a,.wegweiser button{color:var(--grau);border:none;background:none;padding:0;font:inherit}
.wegweiser button:hover{color:var(--tinte)}
.wegweiser .hier{color:var(--tinte);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.wegweiser .pfeil{opacity:.45}
.zurueck{display:inline-flex;align-items:center;gap:.35rem;margin-right:.2rem;color:var(--graphit)}

/* The tabs. The active one is a filled pill rather than an underline:
   on a blurred bar a one-pixel dash disappears, and the pill also gives
   the tap target a visible shape. */
.reiter{position:fixed;left:0;right:0;bottom:0;z-index:40;display:flex;justify-content:space-around;
  background:color-mix(in srgb,var(--papier) 90%,transparent);
  -webkit-backdrop-filter:saturate(150%) blur(16px);backdrop-filter:saturate(150%) blur(16px);
  border-top:1px solid var(--linie-zart);padding:.5rem .4rem calc(env(safe-area-inset-bottom) + .45rem)}
.reiter button{font-family:var(--sans);font-size:9.5px;font-weight:600;letter-spacing:.12em;text-transform:uppercase;
  color:var(--grau);padding:.4rem .7rem;position:relative;display:flex;flex-direction:column;align-items:center;
  gap:.3rem;border-radius:var(--rund-gross);transition:color .18s,background .18s}
.reiter button svg{width:19px;height:19px;stroke:currentColor;fill:none;stroke-width:1.4;
  stroke-linecap:round;stroke-linejoin:round}
.reiter button.aktiv{color:var(--tinte);
  background:color-mix(in srgb,var(--salbei) var(--wasch),var(--papier-tief))}
/* An admin who also writes has six tabs, and a phone is as wide as it was:
   the same type, less air around it. Only in the bar; the rail has room. */
@media(max-width:47.99rem){
  .reiter:has(> :nth-child(6)) button{padding:.4rem .3rem;letter-spacing:.08em}
}

/* ------------------------------------------------- The same tabs, standing up
   One set of destinations, three shapes, and the window picks. Under 48rem the
   bar sits at the bottom edge, where a thumb is. From 48rem there is no thumb
   to plan for and the bar becomes a rail down the left, which is also the only
   way the page beside it gets to be wider than a phone. From 72rem the rail is
   wide enough to write the labels out beside the icons instead of under them.

   The rail is the same <nav> with the same buttons — nothing is drawn twice and
   nothing is hidden and rebuilt, so the tab you are on stays the tab you are on
   as the window changes. --schiene is what the rest of the page reads to know
   how much room it took; it stays 0 while the nav is hidden, which is the case
   for everyone who is not signed in, and therefore on the launch page. */
@media(min-width:48rem){
  body:has(#reiter:not([hidden])){--schiene:5.5rem}

  /* With a rail under it the header is an app bar rather than a column head:
     the mark stands in the corner above the rail and the controls at the far
     right, at the same place on every view. Centred on the content it moved
     two hundred pixels sideways every time a view asked for a different
     width. The signpost keeps the centring, because it names the page and
     belongs over it. */
  body:has(#reiter:not([hidden])) .kopf-innen{max-width:none;margin:0}

  .reiter{top:var(--kopfhoehe,3.4rem);bottom:0;right:auto;width:var(--schiene);
    flex-direction:column;justify-content:flex-start;gap:.2rem;overflow-y:auto;overscroll-behavior:contain;
    border-top:0;border-right:1px solid var(--linie-zart);
    /* Against the page's own paper there is nothing behind it to blur. */
    background:var(--papier);-webkit-backdrop-filter:none;backdrop-filter:none;
    padding:1.1rem .5rem calc(env(safe-area-inset-bottom) + 1.1rem)}
  .reiter button{width:100%;padding:.65rem .3rem}
  /* The landing strip at the bottom of the page was room for the bar. */
  .blatt{padding-bottom:4.5rem}
}

@media(min-width:72rem){
  body:has(#reiter:not([hidden])){--schiene:14rem}
  .reiter{padding:1.4rem .7rem calc(env(safe-area-inset-bottom) + 1.4rem);gap:.1rem}
  /* One line of text is 38 pixels tall with this padding, and a pointer target
     is 44. The row grows rather than the type. */
  .reiter button{flex-direction:row;justify-content:flex-start;gap:.8rem;padding:.62rem .85rem;min-height:44px;
    font-size:11px;letter-spacing:.1em;border-radius:var(--rund-voll)}
  .reiter button svg{width:18px;height:18px;flex:none}
}

/* A button is a target, not a banner. Full width is right in a column of
   35rem and wrong in one of 53: past a certain width it stops reading as
   something you press. The sheet and the session set their own width and are
   not on the sheet, so they keep their full-width buttons. */
@media(min-width:64rem){
  .blatt.weit .knopf,.blatt.mittel .knopf{max-width:28rem}
}

/* From here on the page has all the room it is going to use. The paper widens
   around it instead — a line of text that keeps growing stops being readable
   long before the window stops growing. */
@media(min-width:90rem){
  .blatt{padding-top:calc(env(safe-area-inset-top) + 2.4rem)}
}

/* ============================================================
   Lists: catalogue, phases, units, rows
   ============================================================ */

.eintrag{border-top:1px solid var(--linie-zart)}
.eintrag:last-child{border-bottom:1px solid var(--linie-zart)}
.eintrag-kopf{display:flex;justify-content:space-between;align-items:center;width:100%;text-align:left;
  padding:1.05rem 0;gap:1rem}
.eintrag-kopf .pfeil{color:var(--grau);font-size:.85rem;transition:transform .3s var(--schwung)}
.eintrag.offen .pfeil{transform:rotate(90deg)}
.eintrag-text{display:none;padding-bottom:1.2rem;color:var(--graphit);font-size:1rem}
.eintrag.offen .eintrag-text{display:block}
.eintrag-text ul{padding-left:1.1rem;margin:.4rem 0 1rem}

@media (hover:hover){.tagzeile:hover .tt,.zeile-knopf:hover,.eintrag-kopf:hover,.phase-kopf:hover b{color:var(--payne)}}
.tagzeile,.zeile-knopf,.eintrag-kopf,.phase-kopf{transition:color .15s}
/* Title, subtitle and the figure at the end: the same three parts wherever a
   course is named — in the list, on a card in the catalogue, on the launch
   page. */
/* German compounds are longer than a card is wide. `hyphens` breaks them where
   the language says they break — the document's `lang` is kept in step by
   i18n.js — and `overflow-wrap` catches whatever the browser has no dictionary
   for, so a title is never cut off at the edge of its card. */
.kt{font-size:1.08rem;font-weight:500;line-height:1.28;hyphens:auto;overflow-wrap:break-word}
.ku{font-weight:300;color:var(--graphit);font-size:.98rem;line-height:1.4;hyphens:auto;overflow-wrap:break-word}
.kl{font-family:var(--mono);font-size:11.5px;color:var(--grau)}

.phase{border-top:1px solid var(--linie-zart)}
.phase:last-of-type{border-bottom:1px solid var(--linie-zart)}
.phase-kopf{display:flex;align-items:baseline;gap:.8rem;width:100%;text-align:left;padding:1.1rem 0}
.phase-kopf b{font-weight:400;font-size:1.12rem;flex:1}
.phase-kopf .spanne{font-family:var(--mono);font-size:11.5px;color:var(--grau);font-variant-numeric:tabular-nums}
.phase-kopf .pfeil{color:var(--grau);font-size:.9rem;transition:transform .3s var(--schwung)}
.phase.offen .pfeil{transform:rotate(90deg)}
.phase-inhalt{display:none;padding-bottom:.8rem}
.phase.offen .phase-inhalt{display:block}

.tagzeile{display:flex;align-items:baseline;gap:.9rem;width:100%;text-align:left;padding:.68rem .5rem;
  margin:0 -.5rem;border-top:1px dotted var(--linie-zart);border-radius:var(--rund);
  transition:background .18s,color .15s}
@media (hover:hover){.tagzeile:hover{background:var(--papier-tief)}}
.tagzeile .nr{font-family:var(--mono);font-size:11.5px;color:var(--grau);width:1.8rem;flex:none;
  font-variant-numeric:tabular-nums}
.tagzeile .tt{flex:1;font-size:1rem;line-height:1.35}
.tagzeile.fertig .tt{color:var(--graphit)}
.tagzeile .haken{color:var(--payne);font-size:.85rem}
.tagzeile.gesperrt{opacity:.5}
/* Today is the one thing on this page that is happening now, and
   --roetel is the colour reserved for exactly that. */
.tagzeile.heute .tt::after{content:attr(data-heute);font-family:var(--sans);font-size:9px;font-weight:600;
  letter-spacing:.16em;text-transform:uppercase;color:var(--roetel);margin-left:.6rem;
  border:1px solid var(--roetel);border-radius:var(--rund-voll);padding:.1rem .4rem;white-space:nowrap}
.raute{color:var(--roetel);font-size:.7rem}

.zeile-knopf{display:flex;align-items:center;justify-content:space-between;gap:1rem;width:100%;text-align:left;
  padding:1.05rem 0;border-top:1px solid var(--linie-zart)}
.zeile-knopf:last-of-type{border-bottom:1px solid var(--linie-zart)}
.zeile-knopf .pfeil{color:var(--grau)}
.listenkopf{display:flex;align-items:center;justify-content:space-between;gap:1rem;margin:1.6rem 0 .5rem}
.listenkopf .mini{margin:0}
.leerhinweis{border:1px dashed var(--linie);border-radius:var(--rund-gross);padding:1.8rem 1.4rem;
  text-align:center;color:var(--grau);font-weight:300}

/* ============================================================
   Atelier, forms, chips, flags
   ============================================================ */

.runde{border-top:1px solid var(--linie-zart);padding:1.3rem 0}
.raster{display:grid;grid-template-columns:repeat(3,1fr);gap:.6rem}
.reihe{display:flex;gap:.5rem;overflow-x:auto;padding-bottom:.5rem;-webkit-overflow-scrolling:touch}
.reihe .feld{flex:0 0 32%}
.feld{position:relative;aspect-ratio:3/4;border:1px solid var(--linie);border-radius:var(--rund);
  background:var(--papier-hell);overflow:hidden;display:flex;align-items:center;justify-content:center;
  transition:border-color .18s}
.feld:hover{border-color:var(--tinte)}
.feld img{width:100%;height:100%;object-fit:cover;display:block}
.feld .leer{font-family:var(--sans);font-size:10px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;
  color:var(--grau);text-align:center;padding:0 .3rem;line-height:1.7}
.feld .schild{position:absolute;left:0;right:0;bottom:0;padding:.35rem .45rem;font-family:var(--sans);
  font-size:9px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;
  background:linear-gradient(transparent,rgba(10,9,7,.6));color:#fff}

/* Was eine frühere Einheit hinterlassen hat, unter dem Block, der sie aufruft.
   Die Bilder werden verglichen, nicht bewundert: `contain` statt `cover`, weil
   eine beschnittene Zeichnung die Frage nicht beantwortet, um die es geht. Eine
   Haarlinie, kein Strich — man liest sie, man drückt sie nicht. */
.rueckgriff{margin-top:1.3rem}
.rueckgriff .mini{display:block;margin:.9rem 0 .4rem}
.rueckgriff > .mini:first-child{margin-top:0}
.rueckgriff .zitat{margin-bottom:.8rem}
.rueckblicke{margin-bottom:.2rem;display:grid;grid-template-columns:repeat(auto-fit,minmax(7.5rem,11rem));
  gap:.7rem;justify-content:start}
.rueckblicke figure{margin:0}
.rueckblicke img{width:100%;aspect-ratio:4/5;object-fit:contain;display:block;
  background:var(--papier-hell);border:1px solid var(--linie);border-radius:var(--rund)}
.rueckblicke figcaption{font-family:var(--sans);font-size:10px;font-weight:600;letter-spacing:.14em;
  text-transform:uppercase;color:var(--grau);margin-top:.35rem;line-height:1.5}

label.feld-zeile{display:block;margin-bottom:1.1rem}
label.feld-zeile .marke{margin-bottom:.4rem}
input[type=text],input[type=email],input[type=password],input[type=search],textarea,select{
  width:100%;background:var(--papier-tief);border:1px solid var(--linie);border-radius:var(--rund);
  padding:.75rem .85rem;font-size:1rem;font-family:var(--sans);transition:border-color .18s,background .18s}
input[type=text]:focus,input[type=email]:focus,input[type=password]:focus,textarea:focus,select:focus{
  background:var(--papier-hell);border-color:var(--tinte)}
textarea.quelltext{font-family:var(--mono);font-size:12.5px;line-height:1.6;min-height:22rem}
input[type=file]{display:none}
.feld-zeile .pflicht{float:right;font-family:var(--sans);font-size:9.5px;font-weight:600;letter-spacing:.14em;
  text-transform:uppercase;color:var(--roetel);opacity:.8;margin-top:-1.5rem}

.chip{font-family:var(--sans);font-size:12px;font-weight:500;padding:.4rem .85rem;border:1px solid var(--linie);
  border-radius:var(--rund-voll);color:var(--graphit);transition:border-color .18s,color .18s,background .18s}
.chip:hover{border-color:var(--tinte);color:var(--tinte)}
.chip.an{background:var(--tinte);color:var(--papier);border-color:var(--tinte)}
.fahne{font-family:var(--sans);font-size:9.5px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;
  border:1px solid var(--linie);border-radius:var(--rund-voll);padding:.22rem .55rem;color:var(--grau);white-space:nowrap}
.fahne-in_review,.fahne-approved{border-color:var(--payne);color:var(--payne)}
.fahne-changes_requested{border-color:var(--roetel);color:var(--roetel)}
.fahne-frei{border-color:var(--gold);color:var(--gold)}
/* Finished, in words, on the back — the frame and the medallion said it in gold
   on the front, and this is the half a screen reader gets.

   Struck rather than outlined: ink on the metal's own surface, where every
   other flag is ink or colour on paper. That is what makes it the loudest thing
   on the back, and it also settles the one collision gold had — .fahne-frei is
   brass *as ink* on paper, so a free course that is finished shows two flags
   nobody can confuse. --nacht on --gold-hell is 9.30:1 by day and 10.18:1 at
   night, well above the 4.5 a flag's text owes, and it is the same pair in both
   schemes because neither half of it turns over. The stylesheet test measures
   it per scheme all the same, since --nacht does change value even though it
   never changes side. */
.fahne-fertig{border-color:var(--nacht);background:var(--gold-hell);color:var(--nacht)}
/* A house course file against the database: unchanged is settled, changed is "now". */
.fahne-aktuell{border-color:var(--payne);color:var(--payne)}
.fahne-geaendert,.fahne-fehlerhaft{border-color:var(--roetel);color:var(--roetel)}
.haus-sprache{margin:.2rem 0;white-space:nowrap}
.haus-sprache .hinweis{white-space:normal}
.fahnen{display:flex;flex-wrap:wrap;gap:.3rem;justify-content:flex-end}
/* The subscription badge is a stamp from the posters: a shape in the plan's
   tint — a disc for the learner plan, a square for the creator plan, the
   Bauhaus pair — carrying the plan's initial in the poster cut, ink on tint.
   No pill and no hairline: on the posters a ground is a shape, and here the
   shape is the whole badge. Where there is room the name stands beside it in
   the label voice; in the header below 30rem the shape stands alone and the
   name goes to the label. The header badge is a button, so it is touchable,
   and touchable means the 2px ink stroke — drawn round the shape on hover
   and focus, not around a box. */
.abozeichen{display:flex;align-items:center;gap:.5rem}
.abozeichen:empty{display:none}
.abo{display:inline-flex;align-items:center;gap:.45rem;background:none;border:0;padding:0;margin:0;
  color:var(--tinte);font:inherit;cursor:default}
.abo-form{display:inline-flex;align-items:center;justify-content:center;flex:none;box-sizing:border-box;
  width:26px;height:26px;padding-top:1px;
  font-family:var(--plakat);font-weight:800;font-stretch:75%;font-size:15px;line-height:1;color:var(--tinte);
  background:color-mix(in srgb,var(--ton,var(--salbei)) var(--wasch),var(--papier-hell));
  border:var(--strich) solid transparent;transition:border-color .18s}
.abo-learner{--ton:var(--salbei)}
.abo-learner .abo-form{border-radius:50%}
.abo-creator{--ton:var(--apricot)}
.abo-creator .abo-form{border-radius:var(--rund)}
.abo-wort{font-family:var(--sans);font-size:10.5px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;
  white-space:nowrap}
button.abo{cursor:pointer}
button.abo:hover .abo-form,button.abo:focus-visible .abo-form{border-color:var(--tinte)}
.abo.gross .abo-form{width:44px;height:44px;font-size:26px}
.abo.gross .abo-wort{font-size:11px;letter-spacing:.2em}
.konto-abos{display:flex;flex-direction:column;gap:.7rem;margin:.6rem 0 1rem}
.abo-zeile{display:flex;align-items:center;gap:1rem}
.abo-zeile .abo{min-width:9.5rem}
.abo-zeile p{margin:0}
@media(max-width:30rem){
  .kopfleiste .abo-wort{display:none}
  .abo-zeile{flex-wrap:wrap;gap:.4rem 1rem}
  .abo-zeile .abo{min-width:0}
  .abo-zeile p{flex-basis:100%}
}
details summary{cursor:pointer;padding:.4rem 0}

/* ============================================================
   The session — the one full-screen surface
   ============================================================ */

.sitzung{position:fixed;inset:0;z-index:60;background:var(--papier);display:none;flex-direction:column;
  padding:calc(env(safe-area-inset-top) + 1rem) var(--sp) calc(env(safe-area-inset-bottom) + 1.4rem)}
.sitzung.an{display:flex;animation:auf .4s var(--schwung) both}
.fortschritt{height:2px;background:var(--linie-zart);position:relative;margin-bottom:1.8rem;flex:none;
  border-radius:2px;overflow:hidden}
.fortschritt i{position:absolute;left:0;top:0;bottom:0;background:var(--tinte);width:0;transition:width .3s linear}
.sitzung-kopf{display:flex;justify-content:space-between;align-items:baseline;gap:1.2rem;flex:none;
  margin:0 auto 2rem;max-width:var(--spalte);width:100%}
/* A long course title must not push the way out off the screen. */
.sitzung-kopf #s-tag{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
/* Two buttons at the right of the session's head: keeping the screen, and
   leaving. Both are pressed, so both are pills; neither is drawn until it is
   under a finger, because the head is a line you read past. */
.sitzung-knoepfe{flex:none;display:flex;gap:.3rem;align-items:baseline}
.sitzung-kopf #s-schliessen,.sitzung-kopf #s-merken{flex:none;padding:.3rem .6rem;
  border:1px solid transparent;border-radius:var(--rund-voll)}
.sitzung-kopf #s-schliessen:hover,.sitzung-kopf #s-merken:hover{border-color:var(--linie);color:var(--tinte)}
.sitzung-tasten{flex:none;text-align:center;margin:.9rem 0 0;min-height:1em;font-family:var(--mono);font-size:11px}
.sitzung-tasten:empty{display:none}
.sitzung-mitte{flex:1;display:flex;flex-direction:column;justify-content:center;min-height:0;overflow-y:auto;
  max-width:var(--spalte);width:100%;margin:0 auto}
.schrittzahl{font-family:var(--sans);font-size:10.5px;font-weight:600;letter-spacing:.2em;text-transform:uppercase;
  color:var(--grau);margin-bottom:1.1rem}
.schritttext{font-size:1.45rem;font-weight:300;line-height:1.4;margin:0 0 1.4rem;text-wrap:pretty}
/* The clock is the loudest thing in the product and the reason the mono
   is worth its download. Tabular figures so the last digit does not
   shift the whole number sideways every second. */
.uhr{font-family:var(--mono);font-size:3.6rem;letter-spacing:-.03em;line-height:1;font-variant-numeric:tabular-nums;
  transition:color .3s}
.uhr.pause{color:var(--grau)}
.uhr-zeile{display:flex;align-items:flex-end;gap:1rem;margin-top:.4rem}
.uhr-hinweis{font-family:var(--sans);font-size:10px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;
  color:var(--grau);padding-bottom:.55rem}
.sitzung-fuss{flex:none;display:flex;gap:.7rem;margin:1.8rem auto 0;max-width:var(--spalte);width:100%}
.sitzung-fuss .knopf{flex:1}
.notizfeld{width:100%;background:transparent;border:none;border-bottom:1px solid var(--linie);padding:.7rem 0;
  font-family:var(--sans);font-size:1.08rem;resize:none;outline:none;border-radius:0}
.notizfeld:focus{border-bottom-color:var(--tinte);background:transparent}
.notizfeld::placeholder{color:var(--grau);font-weight:300}

/* ------------------------------------------------- The sheet from below */
/* Over the session (60), under the message (80) and the fanfare (90). The
   session is the only full-screen surface, and until the + in its head there
   was no sheet that could be open while it was up — 50 was never wrong, it was
   never exercised. It is now: keeping a screen opens a sheet from inside the
   session, and at 50 it came up behind it, invisible. */
.sheet{position:fixed;inset:0;z-index:70;display:none}
.sheet.an{display:block}
.sheet .dunkel{position:absolute;inset:0;background:rgba(10,9,7,.38);animation:auf .3s ease both}
.sheet .inhalt{position:absolute;left:0;right:0;bottom:0;max-height:88%;overflow-y:auto;overscroll-behavior:contain;
  background:var(--papier);border-top-left-radius:26px;border-top-right-radius:26px;
  border-top:1px solid var(--linie);
  padding:1.6rem var(--sp) calc(env(safe-area-inset-bottom) + 1.6rem);
  animation:hoch .38s var(--schwung) both;max-width:var(--spalte);margin:0 auto}
@keyframes hoch{from{transform:translateY(28px);opacity:.5}to{transform:none;opacity:1}}
/* The handle closes the sheet. The visible line is narrow, the tappable
   surface is not — 44 pixels of height sit under it. */
.griff{display:block;width:100%;height:2.4rem;margin:-.6rem 0 .6rem;padding:0;background:none;position:relative}
.griff::after{content:'';position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:38px;height:4px;border-radius:2px;background:var(--linie);transition:background .2s,width .2s}
@media (hover:hover){.griff:hover::after{background:var(--graphit);width:48px}}
.schrittliste{margin:0;padding:0;list-style:none}
.schrittliste li{display:flex;gap:.9rem;padding:.6rem 0;border-top:1px dotted var(--linie-zart);font-size:1rem}
.schrittliste .dauer{font-family:var(--mono);font-size:11.5px;color:var(--grau);flex:none;width:2.8rem;
  padding-top:.28rem;font-variant-numeric:tabular-nums}

/* Above an open sheet, or over a running session, the message moves to the
   top: at the bottom it covered exactly the buttons it was reporting on — in
   the session it landed on "Weiter", dark on dark and half-unreadable. */
#sheet.an ~ .toast,#sitzung.an ~ .toast{bottom:auto;top:calc(env(safe-area-inset-top) + 1rem)}
.toast{position:fixed;left:50%;transform:translateX(-50%) translateY(6px);
  bottom:calc(env(safe-area-inset-bottom) + 5.5rem);
  background:var(--tinte);color:var(--papier);padding:.65rem 1.2rem;border-radius:var(--rund-voll);z-index:80;
  font-family:var(--sans);font-size:12px;font-weight:500;letter-spacing:.04em;opacity:0;pointer-events:none;
  transition:opacity .3s,transform .3s var(--schwung);max-width:calc(100vw - 2rem);text-align:center}
.toast.an{opacity:1;transform:translateX(-50%) translateY(0)}

/* --------------------------------------------- The same two, standing up
   These two belong with the rail and are written here rather than beside it,
   because they have to come after the rules they replace.

   A sheet rising from the bottom edge is a phone's idea of a dialogue: it is
   there because a thumb is at the bottom of a phone. On a desk the same
   content is a card in the middle of the screen. What is in it does not
   change, and neither does the way out of it — the handle still closes it,
   Escape still closes it, the ground behind it still closes it.

   The message moves with the page it reports on, so it is centred over the
   content rather than over the window the rail also stands in. */
@media(min-width:48rem){
  .sheet .inhalt{left:50%;right:auto;top:50%;bottom:auto;margin:0;
    width:min(var(--spalte),calc(100vw - 4rem));max-height:82dvh;
    border:1px solid var(--linie);border-radius:var(--rund-gross);
    padding:1.5rem 1.7rem 1.7rem;animation:mitte .34s var(--schwung) both}
  .toast{left:calc(50% + var(--schiene) / 2);bottom:calc(env(safe-area-inset-bottom) + 1.7rem)}
}
@keyframes mitte{from{opacity:0;transform:translate(-50%,calc(-50% + 14px))}
                 to{opacity:1;transform:translate(-50%,-50%)}}

.geld{width:100%;border-collapse:collapse;font-size:1rem}
.geld td{padding:.6rem 0;border-bottom:1px solid var(--linie-zart)}
.geld td:last-child{text-align:right;font-family:var(--mono);font-size:12.5px;font-variant-numeric:tabular-nums}

@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *{animation:none!important;transition:none!important}
  .ladebalken::after{left:0;width:100%;opacity:.4}
  .enthuellen{opacity:1!important;transform:none!important}
}

/* ============================================================
   Interactive elements inside a course
   ============================================================ */
.element{margin:1.6rem 0}
.element-kopf{display:flex;align-items:baseline;justify-content:space-between;gap:1rem;margin-bottom:.6rem}
.element-kopf .marke{margin-bottom:0}
.medium img,.medium video{width:100%;border:1px solid var(--linie);border-radius:var(--rund-gross);display:block}
.medium audio{width:100%;margin:.5rem 0}
figure.medium{margin:1.6rem 0}
.rahmen-16-9{position:relative;padding-top:56.25%;border:1px solid var(--linie);border-radius:var(--rund-gross);overflow:hidden}
.rahmen-16-9 iframe{position:absolute;inset:0;width:100%;height:100%;border:0}

.piano-leiste{display:flex;flex-wrap:wrap;gap:.4rem;margin-bottom:.8rem}
.element .piano-leiste .chip{font-family:var(--mono);letter-spacing:.02em}
.klaviatur{position:relative;height:126px;margin:.2rem 0 .9rem;user-select:none;touch-action:manipulation;
  border:1px solid var(--linie);border-radius:var(--rund-gross);background:var(--papier-tief);overflow:hidden}
.taste{position:absolute;top:0;padding:0;border-radius:0 0 3px 3px}
.taste.weiss{height:100%;background:#FFFFFF;border-right:1px solid rgba(22,22,22,.22);
  display:flex;align-items:flex-end;justify-content:center;padding-bottom:.4rem}
.taste.weiss span{font-family:var(--mono);font-size:9.5px;color:#77756F}
.taste.schwarz{height:62%;background:#161616;z-index:2;border-radius:0 0 3px 3px}
.taste.markiert.weiss{background:var(--payne)}
.taste.markiert.weiss span{color:rgba(255,255,255,.8)}
.taste.markiert.schwarz{background:var(--payne)}
.taste.gedrueckt{filter:brightness(1.35)}

.wahlfeld{display:flex;flex-wrap:wrap;gap:.5rem;margin:.9rem 0}
.wahl{border:1px solid var(--linie);border-radius:var(--rund-voll);padding:.6rem 1rem;font-size:.98rem;
  font-family:var(--sans);color:var(--graphit);transition:border-color .18s,color .18s}
.wahl:hover:not(:disabled){border-color:var(--tinte);color:var(--tinte)}
.wahl:disabled{opacity:.65}
.wahl.richtig{border-color:var(--payne);color:var(--payne);border-width:var(--strich)}
.wahl.falsch{border-color:var(--roetel);color:var(--roetel);text-decoration:line-through}

/* Was beim ersten Mal saß, dieser Durchgang und die davor. Keine eigene Farbe
   und keine Fläche: es ist eine Angabe zum Lesen, kein Abzeichen. */
.notenzeile{margin:.7rem 0 0;display:flex;flex-wrap:wrap;gap:.2rem 1rem;align-items:baseline}
.notenzeile .note-jetzt{font-size:.95rem;color:var(--graphit)}
.notenzeile .note-frueher{font-family:var(--mono);font-size:.78rem;color:var(--grau)}

/* Die Wiederkehr steht oben in der Sitzung und sagt, woher sie kommt. Sie
   trägt keine eigene Farbe: --roetel heißt jetzt, und ein Gegenstand von
   vorletzter Woche ist das Gegenteil davon. */
.wiederkehr-kopf{padding-bottom:.7rem;margin-bottom:1.1rem;border-bottom:1px solid var(--linie-zart)}
.wiederkehr-kopf .hinweis{margin:.25rem 0 0}

/* Was hielt, Monat für Monat: eine dünne Säule je Monat, die Achse tritt
   zurück, die Schrift trägt Textfarben. Kein --roetel -- ein Monat ist nicht
   jetzt, und die Zahl soll als Verlauf gelesen werden, nicht als Alarm. */
.metrik-monate{display:flex;gap:.5rem;align-items:flex-end;flex-wrap:wrap;margin:.9rem 0 0}
.metrik-monate .monat{display:flex;flex-direction:column;align-items:center;gap:.2rem;min-width:2.6rem}
.metrik-monate .saeule{width:100%;height:56px;display:flex;align-items:flex-end;
  border-bottom:1px solid var(--linie)}
.metrik-monate .saeule i{display:block;width:100%;background:var(--payne);min-height:1px}
.metrik-monate .mini{font-size:10px;letter-spacing:.06em;color:var(--grau)}
.metrik-monate .mini.zart{color:var(--graphit);font-variant-numeric:tabular-nums}

/* Die Bilanz am Ende einer Übung: je Item, aus welchem Kurs es kam und wann es
   wiederkommt. Kein Zählwerk -- das wäre ein Zeugnis über einen Menschen; hier
   steht je Zeile eine Tatsache über eine Frage. --roetel nur dort, wo etwas
   heute noch einmal drankommt, denn nur das ist jetzt. */
.wiederkehr-bilanz{border-top:1px solid var(--linie-zart)}
.wiederkehr-bilanz .zeile{display:flex;align-items:baseline;justify-content:space-between;gap:1rem;
  padding:.6rem 0;border-bottom:1px solid var(--linie-zart)}
.wiederkehr-bilanz .zeile .hinweis{margin:0}
.wiederkehr-bilanz .gehalten{color:var(--graphit);white-space:nowrap}
.wiederkehr-bilanz .wieder{color:var(--roetel);white-space:nowrap}

/* Der Verlauf: die eigene Zahl je Einheit, als Linie. Dünn gezeichnet, die
   Achse tritt zurück, die Schrift trägt Textfarben und nie die der Linie.
   --roetel nur auf dem Punkt von heute, denn nur der ist jetzt. */
.verlauf-feld{display:flex;align-items:center;gap:.7rem;margin:.9rem 0;flex-wrap:wrap}
input.verlauf-eingabe{width:9rem;font-family:var(--mono);font-variant-numeric:tabular-nums;text-align:right}
.verlauf-linie{margin:.6rem 0 0}
.verlauf-linie svg{display:block;width:100%;max-width:34rem;height:auto;overflow:visible}
.verlauf-linie .zug{fill:none;stroke:var(--payne);stroke-width:2;stroke-linejoin:round;stroke-linecap:round}
.verlauf-linie .punkt{fill:var(--payne);stroke:var(--papier);stroke-width:2}
.verlauf-linie .punkt.heute{fill:var(--roetel)}
.verlauf-linie .achse{stroke:var(--linie-zart);stroke-width:1}
.verlauf-linie .beschriftung{font-family:var(--sans);font-size:10px;fill:var(--grau)}
.verlauf-linie .wert{font-family:var(--mono);font-size:10.5px;fill:var(--graphit);font-variant-numeric:tabular-nums}

/* Lückentext, Zahl, Reihenfolge: geschrieben statt angeklickt. Die Lücke sitzt
   im Satz und bleibt deshalb inline und eng; sie ist so breit wie das, was
   darin steht, nie so breit wie die Antwort. */
.luecken-satz{font-size:1.06rem;line-height:2.4;margin:.9rem 0}
input.luecke{display:inline-block;width:8.5rem;vertical-align:baseline;background:var(--papier-tief);
  border:0;border-bottom:var(--strich) solid var(--linie);border-radius:0;padding:.05rem .4rem;
  font-size:1rem;font-family:var(--sans);text-align:center;transition:border-color .18s,background .18s}
input.luecke:focus{background:var(--papier-hell);border-bottom-color:var(--tinte);outline:none}
input.luecke:disabled{opacity:1;color:var(--graphit)}
input.luecke.richtig{border-bottom-color:var(--payne);color:var(--payne)}
input.luecke.falsch{border-bottom-color:var(--roetel);color:var(--roetel)}

.zahlfeld{display:flex;align-items:center;gap:.7rem;margin:.9rem 0}
input.zahl-eingabe{width:11rem;font-family:var(--mono);font-variant-numeric:tabular-nums;text-align:right}
input.zahl-eingabe:disabled{opacity:1;color:var(--graphit)}
input.zahl-eingabe.richtig{border-color:var(--payne);border-width:var(--strich)}
input.zahl-eingabe.falsch{border-color:var(--roetel);border-width:var(--strich)}

.reihe-liste{list-style:none;margin:.9rem 0;padding:0}
.reihe-zeile{display:flex;gap:.75rem;align-items:center;padding:.55rem 0;
  border-top:1px dotted var(--linie-zart);font-size:1rem;line-height:1.45}
.reihe-nr{flex:none;width:1.4rem;font-family:var(--mono);font-size:.82rem;color:var(--grau);
  font-variant-numeric:tabular-nums}
.reihe-text{flex:1}
.reihe-zeile.richtig .reihe-nr{color:var(--payne)}
.reihe-zeile.falsch .reihe-nr{color:var(--roetel)}
.reihe-pfeile{flex:none;display:flex;gap:.25rem}
.reihe-pfeil{width:2rem;height:2rem;border:1px solid var(--linie);border-radius:var(--rund);
  color:var(--graphit);font-size:.9rem;line-height:1;transition:border-color .18s,color .18s}
.reihe-pfeil:hover:not(:disabled){border-color:var(--tinte);color:var(--tinte)}
.reihe-pfeil:disabled{opacity:.35}

.metro{display:flex;align-items:center;gap:1.3rem;margin:.7rem 0}
.metro-zahl{font-family:var(--mono);font-size:2.6rem;line-height:1;font-variant-numeric:tabular-nums}
.metro-zahl small{font-family:var(--sans);font-size:.72rem;font-weight:600;letter-spacing:.14em;
  text-transform:uppercase;color:var(--grau);margin-left:.4rem}
.metro-punkte{display:flex;gap:.5rem}
.metro-punkte i{width:10px;height:10px;border-radius:50%;border:1px solid var(--linie);display:block;
  transition:background .08s,border-color .08s,transform .08s}
.metro-punkte i.an{background:var(--roetel);border-color:var(--roetel);transform:scale(1.25)}
.muster{display:flex;gap:.3rem;font-family:var(--mono);margin:.5rem 0}
.muster b{font-weight:400;color:var(--grau);width:1.15rem;text-align:center}
.muster b.an{color:var(--tinte)}
.muster b.jetzt{color:var(--roetel)}
.regler{width:100%;accent-color:var(--payne);margin:.5rem 0}

.hakenzeile{display:flex;gap:.75rem;align-items:flex-start;width:100%;text-align:left;padding:.55rem 0;
  border-top:1px dotted var(--linie-zart);font-size:1rem;line-height:1.45}
.hakenzeile .kasten{flex:none;width:1.15rem;height:1.15rem;border:1px solid var(--linie);border-radius:var(--rund);
  display:flex;align-items:center;justify-content:center;font-size:.72rem;color:var(--payne);margin-top:.2rem;
  transition:border-color .18s,background .18s}
.hakenzeile.an{color:var(--graphit)}
.hakenzeile.an .kasten{border-color:var(--payne);border-width:var(--strich)}

.raster-tabelle{width:100%;border-collapse:collapse;font-size:.98rem}
.raster-tabelle th{font-family:var(--sans);font-size:10px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;
  color:var(--grau);text-align:left;padding:.45rem .6rem .45rem 0;border-bottom:1px solid var(--linie)}
.raster-tabelle th:last-child,.raster-tabelle td:last-child{padding-right:0}
.raster-tabelle td{padding:.55rem .6rem .55rem 0;border-bottom:1px solid var(--linie-zart);vertical-align:top}
.raster-tabelle td.sp-erste{white-space:nowrap}
.raster-tabelle td.sp-zeit{font-family:var(--mono);font-size:12px;color:var(--grau);white-space:nowrap}

.notensatz{overflow-x:auto;background:var(--papier-hell);border:1px solid var(--linie);
  border-radius:var(--rund-gross);padding:.8rem}
.notensatz pre{margin:0;font-family:var(--mono);font-size:11.5px;color:var(--graphit);white-space:pre}
.notensatz svg{max-width:100%;height:auto}

/* ============================================================
   Trophies, notebook, symbol tile
   ============================================================ */
.regal{display:grid;grid-template-columns:repeat(auto-fill,minmax(88px,1fr));gap:.9rem;margin:.6rem 0 0}
/* The cup draws in currentColor (pokal() in ui.js), so its colour is given
   here rather than baked into the file: gold where it stands on paper, paper
   where the catalogue's medallion knocks it out of solid gold. */
.pokal{color:var(--gold)}
.pokal.leer{color:var(--grau)}
.trophaee{text-align:center}
.trophaee svg{width:48px;height:48px;display:block;margin:0 auto .45rem}
.trophaee .tname{font-family:var(--sans);font-size:9.5px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;
  color:var(--graphit);line-height:1.4;display:block}
.trophaee.leer svg{opacity:.22}
.trophaeen-fanfare{position:fixed;inset:0;z-index:90;display:flex;align-items:center;justify-content:center;
  background:color-mix(in srgb,var(--papier) 92%,transparent);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  animation:auf .4s var(--schwung) both;text-align:center;padding:2rem}
.trophaeen-fanfare svg{width:132px;height:132px;margin-bottom:1.4rem;animation:pokalauf .7s var(--schwung) both}
@keyframes pokalauf{from{opacity:0;transform:scale(.8) rotate(-6deg)}to{opacity:1;transform:none}}

/* A day's entries. One under the other while there is one column, and in two
   once the notebook has the width for it — a page of a notebook, not a feed.
   The closing rule is on the container rather than on the last entry, because
   in two columns the last entry is only one of the two at the bottom. */
.notizen{border-bottom:1px solid var(--linie-zart)}
@media(min-width:64rem){
  .notizen{display:grid;grid-template-columns:repeat(auto-fill,minmax(19rem,1fr));gap:0 1.6rem}
}
.notiz{border-top:1px solid var(--linie-zart);padding:1rem 0;display:flex;gap:1rem;align-items:flex-start;
  width:100%;text-align:left}
.notiz-bild{flex:0 0 78px}
.notiz-bild img{width:78px;height:98px;object-fit:cover;border:1px solid var(--linie);border-radius:var(--rund);display:block}
.notiz-text{flex:1;min-width:0}
.notiz-text p{margin:0 0 .35rem;white-space:pre-wrap}
.notiz-wann{font-family:var(--sans);font-size:10px;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--grau)}
.notiz-quelle{border:1px solid var(--linie);border-radius:var(--rund-voll);padding:.08rem .45rem;margin-left:.45rem}
/* The question a reflection answers. Set the way the session set it when it
   was asked — italic and a shade back from the answer — so the leaf reads as
   the same exchange rather than as two sentences of the person's own. */
.notiz-frage{display:block;font-style:italic;color:var(--graphit);margin:0 0 .3rem}
.notiz-frage.gross{font-size:1.12rem;line-height:1.5;margin:.5rem 0 .9rem}
/* A session that is no longer there. Roetel, like the missing image in the
   export: the one line on the leaf that is not true any more. */
.hinweis.fort{color:var(--roetel);margin-top:.8rem}
.ausfuhr{border-top:1px solid var(--linie-zart);padding-top:1.1rem;margin-top:.4rem}
.tagkopf{display:flex;align-items:baseline;justify-content:space-between;margin:1.8rem 0 .3rem;gap:1rem}
.tagkopf b{font-weight:600;font-size:1.02rem}
.tagkopf span{font-family:var(--mono);font-size:11.5px;color:var(--grau)}
.schreibfeld{width:100%;background:var(--papier-tief);border:1px solid var(--linie);border-radius:var(--rund);
  padding:.8rem .9rem;font-family:var(--sans);font-size:1.02rem;resize:vertical;min-height:4.8rem}

/* ------------------------------------------- The notebook, opened at one entry
   A card you only read, so a hairline holds it and nothing is raised. The lid
   over the answer is dashed, because a dashed edge is the one border in this
   stylesheet that already means "nothing here yet" (.leerhinweis, the empty
   shelf) -- and that is exactly what a covered answer is until you have tried
   to remember it. The radius follows the taxonomy: the card is held
   (--rund-gross), the lid and the picture are incidental (--rund), the button
   is pressed and keeps the pill it gets from .knopf. */
.zettel{background:var(--papier-hell);border:1px solid var(--linie);border-radius:var(--rund-gross);
  padding:1.1rem 1.15rem 1rem;display:flex;flex-direction:column;gap:.7rem}
.zettel.leer{border-style:dashed;color:var(--grau);font-size:13.5px;line-height:1.5}
.zettel .frage{font-family:var(--sans);font-size:10px;font-weight:600;letter-spacing:.18em;
  text-transform:uppercase;color:var(--grau)}
.zettel .gefragt{font-weight:300;font-size:1.02rem;line-height:1.45;margin:0}
/* The quotation is the same object as everywhere else, one size down: in a
   20rem column the page's measure would give it three words to a line. */
.zettel .zitat{font-size:1rem;line-height:1.5;margin:0}
.zettel .deckel{border:1px dashed var(--linie);border-radius:var(--rund);padding:.75rem .8rem;
  display:flex;flex-direction:column;gap:.55rem;align-items:flex-start}
.zettel .deckel .hinweis{margin:0}
.zettel img{width:100%;aspect-ratio:4/3;object-fit:cover;border-radius:var(--rund);
  border:1px solid var(--linie);display:block}
.zettel .quelle{font-family:var(--mono);font-size:11px;line-height:1.4;color:var(--grau)}
.zettel .zeile-knopf{margin-top:.1rem}
/* A row of rows closes itself with a rule underneath (`.zeile-knopf:last-of-type`).
   There is only one row here and the card's own edge is right below it, so that
   rule would be a hairline drawn a few pixels above another one. The rule above
   it stays: it does separate the entry from the way out of it. */
.zettel .zeile-knopf:last-of-type{border-bottom:0}

/* The card that says how far you are and leads into the next unit. In one
   column it is the first thing on the page; in two it is the rail, and stays
   in view while the course scrolls past it. */
.startkarte{margin:0 0 1.4rem}
@media(min-width:64rem){ .startkarte{margin:0} }

/* ============================================================
   A view in two columns

   Two shapes and one class. `.lage` puts a side column at the left and
   the work at the right, which is what a catalogue is: the questions you
   ask of a list stand still while the list under them changes.
   `.lage.rechts` turns it round for a page that is read rather than
   searched — the text keeps the left, and the rail at the right carries
   what belongs beside it rather than in it.

   Under 60rem there is only one column and the side column goes back to
   being what it was: a row of filters above the list. Nothing is drawn
   twice; the same nodes stand in a different order.

   64rem rather than 48rem because the rail at the left has already taken
   its share by then, and a side column in the 15rem that would be left
   is a slot, not a column. It is the same number the administration and
   the editor split their own two panes at, and deliberately: three
   different answers to "is there room for a column beside this" would
   be three different pages.
   ============================================================ */
.lage{display:grid;gap:1.4rem}
.nebenspalte{display:flex;flex-direction:column;gap:.9rem;min-width:0}
@media(min-width:64rem){
  .lage{grid-template-columns:15rem minmax(0,1fr);gap:0 2.4rem;align-items:start}
  .lage.rechts{grid-template-columns:minmax(0,1fr) 20rem}
  /* Which side each half stands on is said here rather than left to the order
     in the markup, because the two orders are not the same order: the start
     card of a course belongs at the top of a phone and at the right of a desk,
     and a view should be free to write whichever of them reads better. */
  .lage>.nebenspalte{grid-area:1/1}
  .lage>:not(.nebenspalte){grid-area:1/2}
  .lage.rechts>.nebenspalte{grid-area:1/2}
  .lage.rechts>:not(.nebenspalte){grid-area:1/1}
  /* The column stands still while the list scrolls past it, and gets its
     own scrollbar if it is longer than the window rather than pushing the
     bottom of itself out of reach. */
  .nebenspalte{position:sticky;top:calc(var(--kopfhoehe,0px) + 1.4rem);
    max-height:calc(100dvh - var(--kopfhoehe,0px) - 3rem);overflow-y:auto;overscroll-behavior:contain}
  .nebenspalte .filterzeile{grid-template-columns:1fr;gap:.5rem;margin:0}
  .nebenspalte .piano-leiste{margin:0}
}

/* ============================================================
   Catalogue and planner grids
   ============================================================ */
.filterzeile{display:grid;grid-template-columns:repeat(3,1fr);gap:.5rem;margin-bottom:1rem}
.filterzeile input[type=search]{grid-column:1/-1}
.filterzeile input[type=search],.filterzeile select{
  width:100%;min-width:0;border:1px solid var(--linie);border-radius:var(--rund-voll);padding:.65rem 1rem;
  background:var(--papier-tief);font-family:var(--sans);font-size:12.5px}
@media (max-width:32rem){.filterzeile{grid-template-columns:1fr 1fr}}
/* The level, the tag and the length filters fold away on a phone: for a
   catalogue of a dozen courses they took the first screen before the first
   poster. On a wider screen the summary is not shown and the details stay
   open; katalog.js closes them on a phone at first paint. */
.filter-mehr>summary{list-style:none;cursor:pointer;margin-bottom:.6rem;display:none}
.filter-mehr>summary::-webkit-details-marker{display:none}
@media (max-width:32rem){.filter-mehr>summary{display:inline-flex}}

.kurs-raster{display:grid;grid-template-columns:repeat(auto-fill,minmax(16rem,1fr));gap:.9rem;margin-top:1rem}
/* Two posters to a row on a phone rather than one filling the screen: a shelf
   is read by scanning, and nine courses were nine screens of scrolling. */
@media (max-width:32rem){.kurs-raster{grid-template-columns:1fr 1fr;gap:.6rem}}
/* "Nothing matched" belongs across the whole grid, not in the first cell of it. */
.kurs-raster>.leerhinweis,.plan-raster>.leerhinweis{grid-column:1/-1}
/* On the launch page the grid sits in a band twice as wide as the catalogue's
   column. Left as it is, two courses would huddle at the left edge of a very
   long row; the cap keeps the row the width of a few cards. */
.band .kurs-raster{grid-template-columns:repeat(auto-fill,minmax(19rem,1fr));max-width:60rem;gap:1rem}
/* A course card is a picture with its name under it.

   The band is the same 3:2 in every card whether or not the course has a
   cover, so a row of cards lines up and covers can arrive one course at a
   time. Where there is none the band is the symbol tile grown to fill it —
   one of the four tints, picked from the id, so a course keeps its colour
   either way and keeps it in the planner too. A tint and not a free hue:
   at this size an arbitrary angle is oxblood as often as it is anything
   in the palette, and it is mixed at --wasch rather than --wasch-stark
   because the symbol is standing on it.

   It bleeds to the card's edges by pulling back the card's own padding, and
   its top corners are the card's radius less the 1px border, or the ground
   shows as a bright hairline inside the curve. Nothing is written on the
   picture: the title sits underneath on ordinary paper, which is what keeps
   the contrast check measuring something it can measure and what saves the
   card from needing a scrim — a scrim being a shadow with a different name. */
.kurskarte{display:flex;flex-direction:column;align-items:stretch;text-align:left;width:100%;
  transition:transform .2s var(--schwung),border-color .2s,background .2s}
@media (hover:hover){
  .kurskarte:hover{transform:translateY(-2px);border-color:var(--tinte)}
}
.kursband{display:block;margin:-1.5rem -1.4rem 1.1rem;aspect-ratio:3/2;max-width:calc(100% + 2.8rem);
  overflow:hidden;position:relative;isolation:isolate;
  border-radius:calc(var(--rund-gross) - 1px) calc(var(--rund-gross) - 1px) 0 0;
  border-bottom:1px solid var(--linie);
  background:color-mix(in srgb,var(--ton,var(--salbei)) var(--wasch),var(--papier-hell))}
/* The cover, shown.

   It used to be printed: pulled in as a luminance mask and laid down in ink,
   which is what let a title stand on it — and which threw away every colour in
   the file. The title stands on its own plate now (see the card above), so the
   picture can be a picture: a poster in flat colour, the way
   `courses/MEDIA.md` asks for it.

   The mask had a second problem worth writing down, because it argues against
   ever going back. A luminance mask inks the *light* part of a file, which is
   backwards for a drawing on white paper, so the polarity was turned with a
   second layer composited `exclude`. That is exact where `mask-mode` is
   honoured and silent where it is not: a browser reading an image mask as
   alpha sees an opaque layer, `exclude` cancels it against the opaque second
   one, and the ink never lands. The band then shows its bare tint — an
   uploaded cover looking exactly like a course that has none, with nothing
   anywhere reporting it. WebKit does this, so it was every browser on iOS.
   A picture shown as a picture has neither problem, and the stylesheet test
   refuses `mask-mode` and `mask-composite` outright so the technique cannot
   come back by accident.

   It fills its window (`cover`) and loses a sliver at the sides where the file
   is not exactly 3:2. The `<img>` beside it is hidden; it only reports whether
   the file exists (ui.js). */
.kursdruck{position:absolute;inset:0;
  background-image:var(--bild);background-size:cover;background-position:center}
/* Where there is no cover, a composition of shapes (geometrie() in ui.js):
   the tints at --geometrie, ink at --druck. The two are separate strengths
   because they are separate cases for the title that stands on them — a tint
   is far lighter than ink by day, so it may be drawn at full strength where
   ink may not; at night the tints are dark and the ink is cream, and both
   have to come down. The test mixes each tint at --geometrie over each card
   ground and measures the title's ink against it. */
.kursband .geometrie{position:absolute;inset:0;width:100%;height:100%;opacity:var(--geometrie)}
.kursband .geometrie .druck{opacity:calc(var(--druck) / var(--geometrie))}

/* The catalogue turns its cards over.

   The front is the course's picture across the whole sheet — the cover as it
   was drawn, in colour, or a composition of shapes where there is none — and
   at the foot of it a plate carrying the name in bold, as large as the plate
   allows; the size is measured per card by passeTitel() in ui.js, because only
   the box and the words together know it. The theme stands in the lower right
   corner of the plate, the symbol of a course without a cover in the upper
   left of the sheet, above it. The card is a little taller than wide, the
   proportion of a card in a drawer rather than of a screen. Everything else — subtitle, flags,
   author — is on the back, which is the same tint, so the card is one colour
   front and back.

   The plate is how writing and picture share a sheet. The cover used to be
   pulled in as a luminance mask and printed in ink at `--druck`, which made
   the ground under the name predictable and threw away every colour in the
   file; then the picture was shown and the name moved under it, which kept
   the colour and made the card a caption with an illustration. The picture
   fills the sheet again and the name stands on `--schleier` (see .tafel
   below), which is measured for the worst cover anybody could upload. That
   is a scrim, and a scrim was called a shadow with a different name here for
   a while — the difference is that this one carries a number, and the number
   is checked.

   The plate covers a share of the sheet and not all of it (`--tafel-anteil`).
   Those are two different questions and only one of them has a measured
   answer: how opaque the ground has to be is settled by the contrast test, how
   much of the picture the writing is allowed to take is a composition and is
   settled by looking. Over the whole sheet the answer was "all of it", which
   is what made every cover look washed.

   Under the pointer, or with the focus on it, the card turns on its vertical
   axis. A turn, not a lift. No shadow and no shading: two drawn faces that
   swap, `backface-visibility` hiding whichever points away, and a little
   `perspective` on the button so the near edge grows as it comes round, which
   is what makes it read as a card turning rather than a picture squashing.
   The faces carry the border, because the border has to turn with them; the
   button itself is bare, and gives the card its proportion. The faces are laid
   over it, so no percentage height has to resolve against anything.

   A finger cannot hover, so on touch the front is the card and a tap goes to
   the course page, where everything on the back is written out again — the
   back is a foretaste, never the only place. The planner's card is the
   exception (.tippbar): its back holds the controls, so there the front is a
   button that turns the card, the back has a button that turns it back, and
   a card with something on its shelf starts turned. Reduced motion makes
   the turn a cut, through the global rule at the end of this file. The same
   card stands on the launch page, three of them under a headline. */
.wendekarte{display:block;position:relative;aspect-ratio:4/5;padding:0;border:0;background:none;perspective:60rem}
.wendekarte:hover{transform:none}
.wendekarte:focus-visible{outline-offset:4px;border-radius:var(--rund-gross)}
.wende{position:absolute;inset:0;transform-style:preserve-3d;transition:transform .65s var(--schwung)}
.wende-vorn,.wende-hinten{position:absolute;inset:0;display:flex;flex-direction:column;box-sizing:border-box;
  border:1px solid var(--linie);border-radius:var(--rund-gross);overflow:hidden;
  background:color-mix(in srgb,var(--ton,var(--salbei)) var(--wasch),var(--papier-hell));
  backface-visibility:hidden;transition:border-color .2s}
.wende-vorn{padding:1.1rem 1.2rem .95rem}
/* The band is the sheet itself: laid under everything, edge to edge, no
   margins, no edge, no ground of its own. The upper left of it is where a
   finished course's seal stands; it used to hold a character the course chose,
   and that field is retired (see kursBild() in ui.js). */
.wende-vorn .kursband{position:absolute;inset:0;margin:0;aspect-ratio:auto;max-width:none;
  border:0;border-radius:0;background:none}
/* And everything else on the front stands on it. The band is positioned and
   the plate was not, so the picture painted over the plate's ground and the
   name stood on the bare cover — the scrim was in the stylesheet, measured,
   and invisible. Positioned siblings paint in document order, so the band
   coming first is enough; .plakat and .weiterkarte carry the same rule for
   the same reason.

   Two children are exempt because they place themselves: the band, which has
   to stay behind everything, and the arrow, which has to sit in a corner. A
   two-class selector cannot override this one from below — it is worth an
   exemption here rather than a specificity contest down the file. */
.wende-vorn>*:not(.kursband):not(.wende-drehen):not(.kurssiegel){position:relative}
/* A word is never broken where it happens to run out of room: with
   overflow-wrap at its default a word too long for the line sticks out, the
   measurement sees it, and the size comes down until the whole word fits —
   or until the browser finds a hyphenation point of its own, where it has
   a dictionary for the page's language. */
.wende-vorn .kt{position:relative;flex:1;min-height:0;overflow:hidden;display:flex;flex-direction:column;
  justify-content:safe center;line-height:.96;hyphens:auto;overflow-wrap:normal;word-break:normal}
.wende-vorn .laut+.leise,.wende-vorn .leise+.laut{margin-top:0}
.kartenfuss{position:relative;flex:none;display:flex;justify-content:flex-end;min-height:1rem;margin-top:.5rem}
.kursthema{font-family:var(--sans);font-size:10px;font-weight:600;
  letter-spacing:.18em;text-transform:uppercase;color:var(--tinte)}
.wende-hinten{transform:rotateY(180deg);padding:1.25rem 1.3rem 1.05rem;gap:.3rem}
.wende-hinten .kt{font-size:1.02rem}
.wende-hinten .fahnen{margin-top:.3rem}
.wende-zu{margin-top:auto;padding-top:.7rem;font-family:var(--sans);font-size:11.5px;font-weight:600;
  letter-spacing:.12em;text-transform:uppercase}
@media (hover:hover){
  .wendekarte:hover .wende{transform:rotateY(180deg)}
  .wendekarte:hover .wende-vorn,.wendekarte:hover .wende-hinten{border-color:var(--tinte)}
}
.wendekarte:focus-visible .wende{transform:rotateY(180deg)}
.wendekarte:focus-visible .wende-vorn,.wendekarte:focus-visible .wende-hinten{border-color:var(--tinte)}
.wendekarte.gedreht .wende{transform:rotateY(180deg)}
/* A course this person has finished.

   The frame is a **mat**, not a line: --passepartout of brass, and the sheet
   mounted inside it. That is the whole idea and it is why the width matters.
   This started as a line and was twice made heavier, and a heavier line does
   not help — the question a shelf of cards is asked is "which of these are
   done", and answering it from a line means looking *at* each card's edge in
   turn. A mat changes the card's proportions, so the answer arrives from the
   corner of the eye. Measured three ways side by side (2px, 3px, a 7px mat)
   the first two were told apart by the medallion rather than by the frame.

   A finished course is a print you have hung, which is the other reason this is
   a mat and not a thicker rule: it is the one card on the shelf that is
   finished work rather than an offer.

   It goes on the faces and not on the card, because the faces are what turns —
   a frame on the button would sit still while the sheet inside it rotated. The
   faces are absolutely positioned and box-sized, so the mat eats into the sheet
   instead of growing the card: a finished card keeps its place in the grid and
   its 4:5, and the plate and the title inside it come down by the few pixels
   the mount takes. passeTitel() re-fits the name to whatever box is left, so
   nothing has to be told about this.

   Gold because the cup on the shelf is drawn in gold: the catalogue and the
   start page say the same thing with the same colour rather than each
   inventing one. It is a boundary and not a text colour, so the bar is WCAG
   1.4.11's 3:1 for a graphical object; against the four card grounds it
   measures 3.29 / 3.10 / 4.23 / 3.38 by day and 6.5 to 7.9 at night, against
   1.36 for the hairline it replaces. tests/oberflaeche.test.mjs holds it to
   the 3, because "the frame is visible" is a claim and not a preference.

   Not --roetel, which means now and nothing else, and not --tinte, which is
   what a card goes on hover — a finished card would have looked permanently
   hovered, and there would have been nothing left for the hover to say.

   It stands *below* the hover and focus rules on purpose. Those name the same
   two faces under one class and a pseudo-class, which is the same specificity
   as this one, so order is the whole of it: written above them the frame went
   to ink the moment a pointer touched the card — the mark disappearing exactly
   when somebody looked at it. Below them, gold holds through both. A finished
   card is still visibly hovered (it turns) and still visibly focused (the
   card's own outline, which is not a border), so nothing is lost by the
   border staying what it is. */
.wendekarte.fertig .wende-vorn,.wendekarte.fertig .wende-hinten{
  border-width:var(--passepartout);border-color:var(--gold)}
/* And the cup, in the plate's foot. The foot is flush right and carries the
   theme, so the cup pushes itself to the other end rather than the rule being
   rewritten for the one card that has both.

   It stands on an opaque disc of its own. The plate is paper at --schleier
   over the cover, a ground measured for ink and for ink only: gold on it over
   the worst cover anybody could upload is 1.80:1 by day. Opaque paper is the
   ground gold is measured against everywhere else (5.83:1), and a disc is the
   smallest thing that gives it one. --rund-voll for the same reason a .fahne
   has it: it is a mark, not something to press. The ring is what keeps the
   disc from disappearing: --papier-hell on a pale cover is paper on paper,
   and without an edge the cup read as a speck floating on the drawing.

   The stroke comes up because the file is drawn for the 48px object on the
   shelf; at 20px its 1.6 would land near half a pixel and go pale. */
/* The seal of a finished course. This rule is what it *is*; where it goes is
   the caller's, because it goes in two different kinds of place — a corner
   stamp on a catalogue card's sheet, and in the flow of a start-page card where
   there is no sheet to stamp. Everything scales off --siegel so a context can
   say how big without touching the drawing. */
.kurssiegel{--siegel:2.7rem;
  position:relative;flex:none;
  display:flex;align-items:center;justify-content:center;
  width:var(--siegel);height:var(--siegel);border-radius:var(--rund-voll);
  background:var(--gold-hell);border:var(--strich) solid var(--nacht)}
/* The mark, struck into the metal. It is strichliste(5) — the same drawing the
   start page uses for work under way and the same one marke/zeichen.svg holds,
   so a closed group in brass is that sentence finished rather than a second
   picture meaning the same thing. The strokes come up because the tally is
   drawn for 24px at stroke-width 1.5 and this is a stamp, not a bar chart. */
.kurssiegel .strichliste{color:var(--nacht);gap:0}
.kurssiegel .strichliste svg{width:calc(var(--siegel) * .56);height:calc(var(--siegel) * .54);stroke-width:2.2}
/* On a catalogue card it is a corner stamp, in the upper left of the sheet.
   Where the shelf goes two-up the card is about two thirds as wide and the seal,
   being in rem, does not know that. */
.wende-vorn .kurssiegel{position:absolute;z-index:1;inset:1.1rem auto auto 1.2rem}
@media (max-width:32rem){
  .wende-vorn .kurssiegel{--siegel:2rem;inset:.7rem auto auto .75rem;border-width:1.5px}
}
/* The rule struck inside the rim. Two concentric things are what make a disc
   read as a medal rather than as a dot, and it is the whole of the relief there
   is going to be: a stamped edge catches light on brass, and light is the one
   thing this stylesheet does not have. */
.kurssiegel::before{content:'';position:absolute;inset:2px;border-radius:inherit;
  border:1px solid var(--nacht);opacity:.4}

.tippbar .wende-vorn{width:100%;cursor:pointer;text-align:left;font:inherit;color:inherit}
.tippbar .wende-vorn:focus-visible{outline-offset:-6px;border-radius:var(--rund-gross)}
.tippbar .wende-hinten{overflow:auto}
.wende-fuss{margin-top:auto;padding-top:.7rem;display:flex;justify-content:space-between;align-items:baseline;gap:.6rem}
.wende-fuss .wende-zu{margin-top:0;padding-top:0}
button.wende-zu{cursor:pointer}
.wende-zurueck{font-family:var(--sans);font-size:11px;color:var(--grau);cursor:pointer}
.wende-zurueck:hover{color:var(--tinte)}
.wende-hinten .planzeile{margin-top:.5rem;display:flex;flex-wrap:wrap;gap:.4rem}
.wende-hinten .erinnerung{display:block;margin-top:.6rem;padding-top:.6rem;border-top:1px dotted var(--linie-zart)}
.wende-hinten .erinnerung-zeile{display:flex;flex-wrap:wrap;gap:.4rem;margin-bottom:.4rem}
.wende-hinten .erinnerung .hinweis{display:block}

/* The arrow that turns a card, for a finger.

   A pointer turns a card by hovering it and a keyboard by focusing it. Touch
   can do neither, and the card's answer to that was to not turn at all: the
   front was the card, a tap went to the course, and everything on the back was
   written out there again. That is still true and is why this is an
   afterthought rather than a necessity — but a card that visibly has a back
   and no way to reach it reads as broken, so the arrow. It appears only where
   there is no hover, which is the same condition the turn itself is written
   against, rather than at a width: a narrow window on a laptop can still
   hover, and a tablet at desk width cannot.

   It stands on the plate's ground, `--schleier`, which is the one ground
   already measured against the worst a cover could put under it — the arrow is
   `--tinte` on it, exactly the pair `tests/oberflaeche.test.mjs` measures. And
   it is `--rund-voll`, because it is pressed.

   It places itself, which is why `.wende-vorn>*` exempts it (above): that rule
   lifts the front's children out of the static flow, and an arrow that took
   `position:relative` from it landed in the flex column at the top left,
   shifted the wrong way by its own `right`. */
.wende-drehen{display:none}
@media (hover:none){
  .wende-drehen{position:absolute;z-index:1;top:.6rem;right:.65rem;
    display:flex;align-items:center;justify-content:center;
    width:2.3rem;height:2.3rem;border-radius:var(--rund-voll);color:var(--tinte);
    background:color-mix(in srgb,var(--papier-hell) var(--schleier),transparent)}
  .wende-drehen svg{width:1.2rem;height:1.2rem;fill:none;stroke:currentColor;
    stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
  /* On the back the arrow lands on the title's line — it is the only thing up
     there; the subtitle and the flags start below the arrow's foot. So the
     title gives up that corner, and only that corner: a float clears the lines
     it actually stands beside, where a padding would narrow every line of the
     title and break a long word ("MinuteStudio") that otherwise fits. The
     front needs none of this — its plate is at the foot and the symbol sits
     in the other corner. */
  .wende-hinten .kt::before{content:'';float:right;width:1.9rem;height:1.9rem}
}

/* The same picture at the head of a course, framed like any other image in a
   course (.medium img) rather than bled like the card's band: here it stands
   inside the reading column and is read, not pressed. */
/* The head of a course page and the "continue" cards on the start page are
   the catalogue's card grown or shrunk: the same tint, the same picture or
   composition laid under everything (.kursband at the back), the same two
   voices in the name, and the same plate under whatever is written. */
.plakat{position:relative;overflow:hidden;display:flex;flex-direction:column;justify-content:flex-end;
  min-height:clamp(14rem,36vw,20rem);margin:0 0 1.8rem;padding:2.2rem 2rem 1.7rem;
  border:1px solid var(--linie);border-radius:var(--rund-gross);
  background:color-mix(in srgb,var(--ton,var(--salbei)) var(--wasch),var(--papier-hell))}
.plakat>*{position:relative}
.plakat .titel.gross{margin:0 0 .3rem;max-width:22ch}
.plakat .unter{margin:0;max-width:40ch}
.plakat .kursband,.weiterkarte .kursband{position:absolute;inset:0;margin:0;aspect-ratio:auto;max-width:none;
  border:0;border-radius:0;background:none}
.weiterkarte{position:relative;overflow:hidden;background:color-mix(in srgb,var(--ton,var(--salbei)) var(--wasch),var(--papier-hell))}
.weiterkarte>*:not(.kursband){position:relative}

/* The plate. A picture fills the card and the writing stands on it, so the
   writing needs a ground of its own: paper at `--schleier`, which is not a
   number anybody chose. The worst thing a cover can put under the name is the
   opposite of the paper — black under white by day, white under the dark paper
   at night — and the plate has to hold 4.5:1 against ink even then. Measured,
   that is 50 % by day and 63.5 % at night; the tokens are 56 % and 70 %, and
   tests/oberflaeche.test.mjs mixes exactly that case and fails if either drops
   below the line. Anything less is a scrim that looks like a guarantee and is
   not one, over a picture nobody has uploaded yet. */
.tafel{background:color-mix(in srgb,var(--papier-hell) var(--schleier),transparent);
  border-radius:var(--rund-gross)}
/* On a card the plate is a band at the foot rather than the whole sheet.
   `--tafel-anteil` is the one number here that is chosen and not measured, and
   it is worth saying which is which: `--schleier` is the ground's opacity and
   answers "can this be read" — it is derived from the worst cover and checked.
   This answers "how much of the picture does the writing get", which no
   contrast test can settle. The picture keeps the rest at full strength, and
   with a plate over the whole sheet it kept none.
   It has to be a share of the sheet and not a size that follows the words,
   because passeTitel() fits the type to this box: a box that sized itself to
   its text could not also decide it. So the box is fixed first and the title
   is still as large as it allows — just as large as a band allows now. */
.wende-vorn .tafel{--tafel-anteil:56%;
  flex:none;margin-top:auto;height:var(--tafel-anteil);
  min-height:0;display:flex;flex-direction:column;padding:.7rem .8rem .5rem}
.plakat .tafel{padding:1.1rem 1.2rem 1rem;align-self:flex-start;max-width:100%}
.weiterkarte .tafel{padding:1rem 1.1rem .9rem}
/* A finished course on the start page is mounted the way the catalogue mounts
   it: the same mat, in the same brass. The two shelves sit one above the other,
   so this is what says which one is being looked at before the heading is read.
   The card has no bare picture to stamp — the plate fills its top and the button
   its bottom, seventeen pixels apart — so the seal stands in the plate, where
   the tally stood. It is a shade smaller than the catalogue's, because there it
   is a stamp on a sheet and here it is a mark in a line of text. */
.weiterkarte.fertig{border-width:var(--passepartout);border-color:var(--gold)}
.weiterkarte.fertig .kurssiegel{--siegel:2.2rem}
.weiter-titel{font-size:1.45rem;margin-bottom:.5rem}

.plan-raster{display:grid;grid-template-columns:repeat(auto-fill,minmax(16rem,1fr));gap:1rem;margin-top:.4rem}
.planzeile{display:flex;flex-wrap:wrap;gap:.45rem;margin-top:.6rem}
.erinnerung{margin-top:.7rem;padding-top:.7rem;border-top:1px dotted var(--linie-zart)}
.erinnerung-zeile{display:flex;flex-wrap:wrap;gap:.45rem;margin-bottom:.45rem}
.erinnerung-zeile input[type=datetime-local]{flex:1;min-width:9.5rem;border:1px solid var(--linie);
  border-radius:var(--rund);padding:.45rem .6rem;font-family:var(--sans);font-size:12px;background:var(--papier-tief)}

/* ============================================================
   The studio: review bench, editor, help
   ============================================================ */
/* A course in the overview is a button all over — the whole row leads
   in, not a small "edit" underneath it. */
.kursstand{display:block;width:100%;text-align:left;border:0;border-top:1px solid var(--linie-zart);
  padding:1.1rem .6rem;margin:0 -.6rem;border-radius:var(--rund);transition:background .18s}
.kursstand:last-of-type{border-bottom:1px solid var(--linie-zart)}
.kursstand:hover{background:var(--papier-tief)}
.kursstand-kopf{display:flex;align-items:baseline;justify-content:space-between;gap:1rem;margin-bottom:.3rem}
.kursstand-kopf b{font-weight:600;font-size:1.05rem}
.kursstand .hinweis,.kursstand .fehler{display:block}

ul.meldungen{list-style:none;margin:.5rem 0 0;padding:0;display:flex;flex-direction:column;gap:.7rem}
ul.meldungen li{line-height:1.5}
code.zitat-zeile{display:inline-block;margin-top:.3rem;font-family:var(--mono);font-size:12px;
  background:var(--papier-tief);border-left:var(--strich) solid var(--linie);padding:.2rem .55rem;
  border-radius:0 var(--rund) var(--rund) 0;color:var(--graphit);max-width:100%;overflow-x:auto;white-space:pre}

/* Editor: form rather than source. Two intentions — the course should
   look like a text, not a database mask, and only what is on the table
   right now should be visible. Everything else sits behind a triangle. */
.modus{display:flex;gap:.4rem;margin:.4rem 0 1rem}
.modus-knopf{font-family:var(--sans);font-size:10px;font-weight:600;letter-spacing:.16em;text-transform:uppercase;
  color:var(--grau);border:1px solid var(--linie);border-radius:var(--rund-voll);padding:.45rem .9rem;background:none;
  transition:border-color .18s,color .18s}
.modus-knopf.aktiv{color:var(--tinte);border-color:var(--tinte);border-width:var(--strich)}

.formteil{margin:2.6rem 0}
/* When switching, the section should start below the sticky bar rather
   than behind it. */
.formular{scroll-margin-top:calc(var(--kopfhoehe,0px) + 4.6rem)}
.formteil>.marke{margin-bottom:.3rem}
.hinweis.leise{color:var(--grau);opacity:.9;margin:0 0 .9rem}

/* The course head has many short fields — side by side the content
   stays in view. */
@media(min-width:34rem){
  .formular .formkopf{display:grid;grid-template-columns:1fr 1fr;gap:0 1rem}
  .formular .formkopf>.marke,
  .formular .formkopf>details,
  .formular .formkopf>label:has(textarea){grid-column:1 / -1}
  .formular .formkopf>details .mehr-inhalt{display:grid;grid-template-columns:1fr 1fr;gap:0 1rem}
}
/* ------------------------------------------- The author's own note
   The `#` comments of the source file, one box per container, and the only
   place they are ever shown: the server takes them out of the document for
   anybody who is not the author.

   A wash of --apricot into --papier-hell — the sanctioned way to a yellow
   ground, since a tint is a ground and never a text colour. Smaller than the
   fields around it and set in the mono, so it reads as a margin note on the
   work rather than as part of the course. A hairline, not --strich: it is
   something you read past far more often than you write in. */
.autorennotiz{display:block;margin:0 0 1rem;padding:.6rem .8rem;border-radius:var(--rund);
  background:color-mix(in srgb,var(--apricot) var(--wasch),var(--papier-hell));
  border:1px solid color-mix(in srgb,var(--apricot) 50%,var(--linie))}
.autorennotiz>.marke{margin-bottom:.25rem}
.autorennotiz textarea{width:100%;background:transparent;border:none;outline:none;resize:vertical;
  font-family:var(--mono);font-size:12.5px;line-height:1.5;color:var(--tinte);padding:0}
.autorennotiz textarea::placeholder{color:var(--graphit);font-family:var(--sans);font-size:12px}
/* Inside a unit card the note sits under the left rule with the rest of it. */
.formular .formgruppe>.autorennotiz{margin-bottom:.8rem}

.formular .formgruppe{border-left:1px solid var(--linie-zart);padding-left:1rem;margin-bottom:1.5rem}
.formular .formblock{margin-bottom:1rem;padding:1.2rem 1.2rem .7rem}
.formblock-kopf{display:flex;align-items:baseline;gap:.7rem;margin-bottom:.9rem}
.formblock-kopf b{font-size:1.05rem;font-weight:600;flex:0 0 auto}
.formblock-kopf .hinweis{flex:1;min-width:0}
.formblock-knoepfe{display:flex;gap:.5rem;flex:0 0 auto}
.formblock-knoepfe button{padding:0 .2rem}
.formliste{display:flex;flex-direction:column;gap:.45rem;margin-bottom:.5rem}
.formzeile{display:flex;gap:.5rem;align-items:center}
.formzeile input[type=text]{flex:1;min-width:0}
.formzeile input[type=radio]{width:auto;flex:0 0 auto}
.formzeile-kopf{font-family:var(--sans);font-size:10px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:var(--grau)}
.formzeile-kopf span{flex:1;min-width:0}
.formzeile-kopf span:last-child{flex:0 0 1.2rem}
.formzeile-haken{display:flex;gap:.6rem;align-items:center;margin-bottom:1rem;font-family:var(--sans);
  font-size:12.5px;color:var(--graphit)}
.formzeile-haken input{width:auto}

/* "More details": everything you rarely need but have to be able to find. */
details.mehr{margin:.2rem 0 1rem;border-top:1px solid var(--linie-zart);padding-top:.7rem}
details.mehr>summary{list-style:none;cursor:pointer;font-family:var(--sans);font-size:10px;font-weight:600;
  letter-spacing:.16em;text-transform:uppercase;color:var(--grau);display:flex;align-items:center;gap:.5rem}
details.mehr>summary::-webkit-details-marker{display:none}
details.mehr>summary::before{content:"▸";font-size:9px;transition:transform .18s var(--schwung);display:inline-block}
details.mehr[open]>summary::before{transform:rotate(90deg)}
details.mehr>summary:hover{color:var(--tinte)}
details.mehr .anzahl{font-family:var(--mono);letter-spacing:0;opacity:.7}
details.mehr[open]>summary{margin-bottom:.9rem}

/* The palette: blocks in four drawers instead of nineteen in one menu. */
details.palette{margin:.4rem 0 1.8rem}
details.palette>summary{list-style:none;cursor:pointer;text-align:center;font-family:var(--sans);font-size:11px;
  font-weight:600;letter-spacing:.16em;text-transform:uppercase;color:var(--graphit);
  border:1px dashed var(--linie);border-radius:var(--rund-voll);padding:.8rem 1rem;
  transition:border-color .2s,color .2s}
details.palette>summary::-webkit-details-marker{display:none}
details.palette>summary:hover{border-color:var(--tinte);color:var(--tinte)}
details.palette[open]>summary{border-style:solid;color:var(--tinte);border-color:var(--tinte);margin-bottom:1.1rem}
.palette-gruppe{margin-bottom:1.2rem}
.palette-gruppe .marke{margin-bottom:.5rem}
.palette-kacheln{display:grid;grid-template-columns:repeat(auto-fill,minmax(10rem,1fr));gap:.5rem}
.kachel{text-align:left;border:1px solid var(--linie-zart);border-radius:var(--rund-gross);
  background:var(--papier-hell);padding:.7rem .8rem;transition:border-color .18s,transform .18s var(--schwung)}
.kachel:hover{border-color:var(--tinte);transform:translateY(-2px)}
.kachel b{display:block;font-size:1rem;font-weight:600;margin-bottom:.2rem}
.kachel span{display:block;font-family:var(--sans);font-size:11px;line-height:1.45;color:var(--grau)}

/* The sections of a course. Twenty-one units were not surveyable as one
   page; now the left says what it consists of and the right holds only
   the part being worked on. Narrow below one another, wide beside. */
.teilenav{display:flex;gap:.35rem;overflow-x:auto;margin:0 0 1.4rem;padding-bottom:.4rem;
  -webkit-overflow-scrolling:touch;scrollbar-width:none}
.teilenav::-webkit-scrollbar{display:none}
.teilenav button{display:flex;align-items:center;gap:.45rem;flex:0 0 auto;font-family:var(--sans);font-size:11px;
  font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--grau);
  border:1px solid var(--linie-zart);border-radius:var(--rund-voll);padding:.5rem .85rem;
  transition:border-color .15s,color .15s}
.teilenav button:hover{border-color:var(--linie);color:var(--graphit)}
.teilenav button.aktiv{color:var(--tinte);border-color:var(--tinte)}
.teilenav button .zahl{font-family:var(--mono);letter-spacing:0;opacity:.65}
.teilenav-neu{border-style:dashed!important}

@media(min-width:64rem){
  .formular{display:grid;grid-template-columns:14rem 1fr;gap:0 2.6rem;align-items:start}
  .teilenav{flex-direction:column;overflow:visible;margin:0;position:sticky;top:calc(var(--kopfhoehe,0px) + 4.2rem)}
  .teilenav button{width:100%;justify-content:space-between;text-align:left;border:0;
    border-left:1px solid var(--linie-zart);border-radius:0;padding:.55rem .9rem}
  .teilenav button.aktiv{border-left-color:var(--tinte);border-left-width:var(--strich);background:var(--papier-tief)}
  .teilenav-neu{border:0!important;border-left:1px dashed var(--linie)!important}
}

/* Side ways into a course: there, but not as loud as check and save. */
.nebenwege{display:flex;flex-wrap:wrap;gap:1.3rem;justify-content:center;margin:1rem 0 0;padding-top:1rem;
  border-top:1px solid var(--linie-zart)}
.nebenwege button{font-family:var(--sans);font-size:11px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;
  color:var(--grau);border-bottom:1px solid transparent;padding-bottom:.1rem}
.nebenwege button:hover{color:var(--tinte);border-bottom-color:var(--linie)}

/* Switching and saving stay in reach, even after two metres of form. */
.editorleiste{position:sticky;top:var(--kopfhoehe,0px);z-index:5;display:flex;align-items:center;
  justify-content:space-between;gap:.8rem;flex-wrap:wrap;background:var(--papier);margin:.4rem 0 1rem;
  padding:.6rem 0;border-bottom:1px solid var(--linie-zart)}
.editorleiste .modus{margin:0}
.leiste-tat{display:flex;gap:.5rem}

/* The range of a phase: two menus with a word between them. */
.spannwahl{display:flex;align-items:center;gap:.6rem}
.spannwahl select{flex:1;min-width:0}
.spannwahl span{font-family:var(--sans);font-size:11.5px;color:var(--grau)}

/* A file field: the picture that is in it, and the two ways to change it.
   Shown rather than named, because a filename is not what anybody recognises
   a picture by. A hairline, not a raised edge: the box is read, not pressed. */
.medienzeile{display:block;margin-bottom:1.1rem}
.medienzeile>.marke{display:block;margin-bottom:.4rem}
/* `--rund`, not `--rund-gross`: this is a field, however much content it
   holds — an input's corner, not a plate you pick up (assets.md, "Radius says
   what a thing is"). */
.medienfeld{display:flex;align-items:center;gap:.8rem;flex-wrap:wrap;
  border:1px solid var(--linie);border-radius:var(--rund);
  padding:.6rem .7rem;background:var(--papier-tief)}
.medien-bild{flex:0 0 auto;width:4.5rem;aspect-ratio:3/2;overflow:hidden;
  border-radius:var(--rund);background:var(--papier-hell)}
.medien-bild img{width:100%;height:100%;object-fit:cover;display:block}
.medien-stand{flex:1 1 8rem;min-width:0;font-family:var(--sans);font-size:12px;overflow-wrap:anywhere}
.medien-stand code{font-size:11.5px}
/* The buttons take a line of their own, and the picker gives way rather than
   pushing the one button that is only a cross onto a third line. */
.medien-knoepfe{flex:1 1 100%;display:flex;align-items:center;gap:.5rem}
.medien-knoepfe select{flex:1 1 5rem;width:auto;min-width:0;padding:.45rem .6rem;font-size:12px}
input.medienquelle{margin-top:.5rem}

/* The file room: one section per course, the files of each under its name.
   The heading is a rule the eye can stop at, not a box — a course here is a
   grouping, not a card you press. */
.dateikurs{margin:0 0 2.2rem}
.dateikurs-kopf{display:flex;gap:.8rem;align-items:baseline;flex-wrap:wrap;
  border-bottom:1px solid var(--linie);padding-bottom:.5rem;margin-bottom:.3rem}
.dateikurs-kopf b{font-size:1.05rem}
.dateikurs .notiz .fahne{margin-left:.5rem}

/* The width a view is given comes from `breite` in the route table and is
   published as --breite on <body>; see "Width and room" at the top. */

/* Help for authors: running text, not a mask. */
.hilfeteil{margin:2.6rem 0}
.hilfe-h2{font-size:1.4rem;margin:0 0 .8rem}
.hilfeteil p{color:var(--graphit);margin:0 0 .8rem}
.hilfe-gruppe{margin:1.3rem 0}
.hilfe-liste{margin:0;display:grid;grid-template-columns:auto 1fr;gap:.4rem 1.1rem;align-items:baseline}
.hilfe-liste dt{font-size:1.02rem}
.hilfe-liste dd{margin:0;font-family:var(--sans);font-size:12px;color:var(--grau);line-height:1.5}
.hilfe-punkte{margin:0;padding-left:1.15rem;color:var(--graphit)}
.hilfe-punkte li{margin-bottom:.6rem}
.verweis{color:var(--payne);border-bottom:1px solid var(--linie);font:inherit;padding:0;background:none}
.verweis:hover{border-bottom-color:var(--payne)}

/* ============================================================
   Sign-in and account administration
   ============================================================ */
.oder{display:flex;align-items:center;gap:.9rem;margin:1.3rem 0;color:var(--grau);font-family:var(--sans);
  font-size:10px;font-weight:600;letter-spacing:.16em;text-transform:uppercase}
.oder::before,.oder::after{content:"";flex:1;height:1px;background:var(--linie-zart)}
a.knopf.anbieter{text-decoration:none;margin-bottom:.5rem}
.anbieterliste{display:flex;flex-wrap:wrap;gap:.5rem;margin:.4rem 0 1rem}
.anbieterliste span{font-family:var(--sans);font-size:11px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;
  color:var(--graphit);border:1px solid var(--linie-zart);border-radius:var(--rund-voll);padding:.35rem .7rem}

/* The three subscriptions. Under each other you compare them by scrolling,
   which is not comparing; beside each other the differences are on one line.
   The button sits at the foot of every card whatever the sentences above it
   did, so there is one row of buttons rather than three. */
/* The consent in the subscription sheet: the box beside its sentence, the
   sentence in the small type of a note, because it is read once and signed. */
.zustimmung{display:flex;gap:.6rem;align-items:flex-start;margin:1.2rem 0}
.zustimmung input{margin-top:.2rem;flex:none}
.zustimmung .hinweis{margin:0}
.tarifraster{display:grid;grid-template-columns:repeat(auto-fit,minmax(15rem,1fr));gap:.8rem;margin-bottom:.8rem}
.tarifkarte{display:flex;flex-direction:column}
.tarifkarte .knopf{margin-top:auto}
/* Where a card has no button — the tier already being paid for — the sentence
   that says so takes the button's place, so the three cards end level. */
.tarifkarte>.hinweis:last-child{margin-top:auto}
/* The plans page: the tier somebody is already on is marked by the card's own
   hairline taking the ink colour, not by a second weight of border — a card is
   read, not pressed, and 2px is reserved for what you can touch. */
.tarifkarte.laeuft{border-color:var(--tinte)}
.tarifpreis{font-family:var(--sans);font-size:1.05rem;font-weight:600;margin:.2rem 0 .7rem;line-height:1.35}
.tarifpreis .hinweis{display:block;font-weight:400;margin-top:.15rem}
.abo-zeitraum{max-width:26rem}
ul.enthalten{list-style:none;padding:0;margin:0 0 1.1rem;font-family:var(--sans);font-size:12.5px;
  color:var(--graphit);line-height:1.55}
ul.enthalten li{position:relative;padding-left:1.15rem;margin-bottom:.5rem}
ul.enthalten li::before{content:"";position:absolute;left:.05rem;top:.42em;width:.42rem;height:.24rem;
  border-left:1.5px solid var(--payne);border-bottom:1.5px solid var(--payne);transform:rotate(-45deg)}

.regalwahl{display:flex;gap:.35rem;margin-bottom:1.6rem}
.regalwahl button{flex:1;padding:.7rem;font-family:var(--sans);font-size:10.5px;font-weight:600;letter-spacing:.16em;
  text-transform:uppercase;color:var(--graphit);background:none;border:1px solid var(--linie);
  border-radius:var(--rund-voll);transition:background .18s,color .18s,border-color .18s}
.regalwahl button[aria-selected=true]{background:var(--tinte);color:var(--papier);border-color:var(--tinte)}
.hakenreihe{display:flex;flex-wrap:wrap;gap:.5rem 1.3rem;margin:.3rem 0 .7rem}
.hakenreihe label{display:flex;align-items:center;gap:.45rem;font-family:var(--sans);font-size:12.5px;color:var(--graphit)}
.hakenreihe label.gesperrt{opacity:.45}
.hakenreihe.senkrecht{flex-direction:column;gap:.5rem}
.gruppenliste{display:flex;flex-wrap:wrap;gap:.5rem;margin:.5rem 0}
.gruppenmarke{display:inline-flex;align-items:center;gap:.5rem;border:1px solid var(--linie-zart);
  border-radius:var(--rund-voll);padding:.35rem .7rem;font-family:var(--sans);font-size:11.5px;color:var(--graphit)}
.gruppenmarke .hinweis{font-size:10px;font-weight:600;letter-spacing:.12em;text-transform:uppercase}
.gruppenmarke .verweis{border:0;color:var(--roetel);font-size:15px;line-height:1}
.gruppenwahl{margin:.9rem 0 0}
.gruppenwahl select{font-family:var(--sans);font-size:12.5px;padding:.65rem .8rem}

/* ============================================================
   The admin backend

   A second surface behind the same tokens: no new colour, no new radius
   rule, no shadow — only a denser layout. A sidebar replaces the tab bar
   because there are six rooms instead of five, and a real <table> replaces
   the card list because a backend is read a column at a time.
   ============================================================ */
.admin{display:flex;gap:2rem;align-items:flex-start}
.admin-nav{flex:0 0 11rem;position:sticky;top:calc(var(--kopfhoehe,0px) + 1.4rem)}
.admin-raeume{display:flex;flex-direction:column;gap:.15rem}
.admin-raeume button{display:block;width:100%;text-align:left;padding:.55rem .7rem;border-radius:var(--rund);
  font-family:var(--sans);font-size:12.5px;font-weight:600;letter-spacing:.03em;color:var(--grau);
  border:1px solid transparent;transition:background .15s,color .15s,border-color .15s}
@media (hover:hover){.admin-raeume button:hover{color:var(--tinte)}}
.admin-raeume button[aria-current=page]{color:var(--tinte);background:var(--papier-tief);border-color:var(--linie-zart)}
/* The burger exists only where the sidebar does not. */
.admin-menue{display:none}
.admin-inhalt{flex:1;min-width:0}
/* The launch page's editor: a text once per language, a picture with its
   preview beside the choice. */
.tabelle td.sp-inhalt{max-width:18rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.feldgruppe{margin-bottom:1.3rem}
.feldgruppe>.marke{margin-bottom:.5rem}
label.feld-zeile.sprachzeile{display:flex;gap:.6rem;align-items:flex-start;margin-bottom:.5rem}
.sprachzeile .fahne{flex:0 0 auto;margin-top:.9rem}
.bildwahl{display:flex;gap:1rem;flex-wrap:wrap;align-items:flex-start}
.bildvorschau{flex:0 0 12rem}
.bildvorschau .platte.leer{aspect-ratio:3/2;border-style:dashed}
@media (max-width:64rem){
  /* `align-items:flex-start` above is a row-layout choice (so the sidebar
     does not stretch to the content's height); in the column layout the
     same property is the cross axis, so it must go back to `stretch` or
     `.admin-inhalt` shrinks to its widest child — the table — instead of
     filling the screen. */
  .admin{flex-direction:column;align-items:stretch;gap:.6rem}
  /* One bar naming the room, stuck under the header so the way to another
     room is at hand however deep into a table you have scrolled. It carries
     its own paper, because what scrolls under it must not show through. */
  .admin-nav{flex:none;width:100%;position:sticky;top:var(--kopfhoehe,0px);z-index:30;
    padding:.5rem 0;margin-top:-.5rem;background:var(--papier)}
  .admin-menue{display:flex;align-items:center;gap:.75rem;width:100%;text-align:left;
    padding:.6rem 1rem;border:var(--strich) solid var(--linie);border-radius:var(--rund-voll);
    background:var(--papier);font-family:var(--sans);font-size:12.5px;font-weight:600;letter-spacing:.03em;
    color:var(--tinte);transition:border-color .15s}
  .admin-menue svg{width:18px;height:18px;flex:none;stroke:currentColor;fill:none;stroke-width:1.6;stroke-linecap:round}
  .admin-menue[aria-expanded=true]{border-color:var(--tinte)}
  /* The list of rooms drops over the page rather than pushing it down, so
     the page is where you left it when the menu closes again. */
  .admin-raeume{display:none;position:absolute;left:0;right:0;top:calc(100% - .1rem);
    padding:.4rem;background:var(--papier);border:1px solid var(--linie);border-radius:var(--rund-gross)}
  .admin-nav.offen .admin-raeume{display:flex}
  .admin-raeume button{padding:.7rem .8rem;min-height:44px}
}

.kachel-raster{display:grid;grid-template-columns:repeat(auto-fit,minmax(9.5rem,1fr));gap:.8rem;margin:0 0 1.6rem}
.kachel{border:1px solid var(--linie);border-radius:var(--rund-gross);padding:1rem 1.1rem}
.kachel .marke{display:block;margin-bottom:.3rem}
.kachel b{display:block;font-family:var(--mono);font-size:1.7rem;line-height:1;font-variant-numeric:tabular-nums}
.kachel .hinweis{margin-top:.3rem;display:block}

.tabelle-rahmen{overflow-x:auto;-webkit-overflow-scrolling:touch}
.tabelle{width:100%;border-collapse:collapse;font-size:13px}
.tabelle th{font-family:var(--sans);font-size:10px;font-weight:600;letter-spacing:.12em;text-transform:uppercase;
  color:var(--grau);text-align:left;padding:.5rem .7rem;border-bottom:1px solid var(--linie);white-space:nowrap}
.tabelle td{padding:.6rem .7rem;border-bottom:1px solid var(--linie-zart);vertical-align:middle}
.tabelle td.sp-zahl,.tabelle th.sp-zahl{font-family:var(--mono);font-variant-numeric:tabular-nums;text-align:right}
.tabelle.klickbar tbody tr{cursor:pointer;transition:background .12s}
@media (hover:hover){.tabelle.klickbar tbody tr:hover{background:var(--papier-tief)}}

/* ============================================================
   The launch page

   The one surface that is not a reading column. It alternates cream and
   ink in full-width bands, which is the rhythm both reference sites use
   and the reason a visitor keeps scrolling: every band is a new room.

   A dark band does not paint over the tokens, it *rebinds* them. Every
   component below it — button, card, flag, hint — then reads as if the
   dark scheme were switched on, without a single override of its own.

   Rebinding is all or nothing, and `--druck` and `--geometrie` were the two
   left out of it. A card in this band therefore printed its cover at the
   daylight strength in cream ink, which is the one combination nobody chose:
   at night the print *lightens* the ground and the title is light too, so
   the darkest cover took the name to 3.4:1 where the house floor is 4.5.
   Nothing said so, because the contrast test reads both strengths out of the
   block it is measuring and skips the check where it finds neither — a band
   that declared no strength was asked no question. It declares both now.
   ============================================================ */
.band{position:relative;padding:clamp(3.5rem,9vw,6.5rem) 0}
/* The gutter is --rand, the same one the app pages use, so the mark in the
   header stands over the first letter of the band under it at every width. */
.band-innen{max-width:72rem;margin:0 auto;padding:0 var(--rand)}
.band-eng{max-width:46rem;margin:0 auto;padding:0 var(--rand)}
.band+.band{border-top:1px solid var(--linie-zart)}

.band-nacht{
  --papier:#161616; --papier-hell:#1F1F1F; --papier-tief:#0C0C0C;
  --tinte:#FAFAF8; --graphit:#C9C6BF; --grau:#A9A69F;
  --linie:rgba(250,250,248,.22); --linie-zart:rgba(250,250,248,.11);
  --payne:#8FBDF5; --roetel:#FF6A55; --gold:#E6BC55;
  --salbei:#006A4E; --lavendel:#5A2E96; --apricot:#A87000; --himmel:#0A6A88;
  --wasch:26%; --wasch-stark:38%; --druck:24%; --geometrie:90%; --schleier:70%;
  background:#161616;color:#FAFAF8;border-top:0}

/* ------------------------------------------------------------- The tints
   Four washed grounds, and the one rule that keeps them from turning the
   page into a paint chart: **a tint is a ground, never a text colour and
   never an action.** Whatever stands on one is ink, graphite or grey, and
   whatever you press is still ink. That is what lets there be four of them
   and still only one accent — --roetel is the only colour that means
   something, and the tints only mean "a different room".

   The strength is a token rather than a number at each use, because the two
   schemes want different amounts of it: 48% of the tint in daylight, 20% at
   night, where the same wash would glow. --wasch-stark is for a surface with
   no text on it at all, which in practice means a plate.

   The hue is set with .ton-*, and nothing hard-codes one, so a band and the
   plate standing on it differ by a single class. The ink band rebinds all
   four to their night values above, or a plate inside it would mix daylight
   sage into a dark ground and come out chalky. */
.ton-salbei{--ton:var(--salbei)}
.ton-lavendel{--ton:var(--lavendel)}
.ton-apricot{--ton:var(--apricot)}
.ton-himmel{--ton:var(--himmel)}
.band.getont{background:color-mix(in srgb,var(--ton,var(--salbei)) var(--wasch),var(--papier));border-top:0}
.karte.getont{background:color-mix(in srgb,var(--ton,var(--salbei)) var(--wasch),var(--papier-hell))}
.platte.getont{background:color-mix(in srgb,var(--ton,var(--salbei)) var(--wasch-stark),var(--papier-hell))}

/* The hero. The headline is the largest thing in the product: the two
   voices at their largest, the poster cut and the light sans side by side. */
.held{padding:clamp(2.5rem,7vw,4.5rem) 0 clamp(3rem,8vw,5rem)}
.held-marke{font-family:var(--mono);font-size:11.5px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--grau);display:flex;align-items:center;gap:.6rem;margin-bottom:1.6rem}
.held-marke::after{content:'';flex:1;height:1px;background:var(--linie-zart);max-width:8rem}
.held h1{font-size:clamp(3rem,9vw,6rem);margin:0 0 1.3rem;max-width:14ch}
.held .unter{font-size:clamp(1.1rem,2.4vw,1.4rem);max-width:34ch;margin-bottom:2.2rem}
/* The sign-in: two buttons in a row and a line of small print under them.
   Not a band of its own — a block carries it, and it closes whatever that
   block just said, which is why it sits flush with the text above it in
   the hero and a paragraph's breath below it everywhere else. After the
   three steps it takes the same distance the steps took from their intro,
   so it reads as the fourth beat rather than a footnote. */
.zugang{display:flex;flex-wrap:wrap;gap:.7rem;align-items:center;margin-top:2rem}
.zugang .knopf{width:auto;min-width:11rem}
.zugang .hinweis{width:100%;margin-top:.4rem}
.held-text .zugang{margin-top:0}
.schritte+.zugang{margin-top:3rem}

/* A plate is a composition in its frame: a drawn border, a tinted ground,
   and the shapes bleeding to its edge. The pictures are in
   public/js/core/plakate.js, drawn in the same vocabulary as a course's
   composition and filled with tokens, so they follow the scheme. */
.platte{border:1px solid var(--linie);border-radius:var(--rund-gross);background:var(--papier-hell);
  overflow:hidden;display:block;position:relative}
.platte img,.platte svg{display:block;width:100%;height:auto}
.held-platte{margin-top:clamp(2.2rem,5vw,3rem)}
/* The plate is a companion to the headline, not a wall under it: on a narrow
   screen it lies below and is capped in height, and once there is room it
   moves alongside. */
.held-platte .plakat-bild{max-height:min(42vh,360px)}
.held-raster{display:grid;gap:clamp(2rem,5vw,3rem)}
@media(min-width:62rem){
  .held-raster{grid-template-columns:1.08fr .92fr;align-items:center;gap:4rem}
  .held-platte{margin-top:0}
  .held-platte .plakat-bild{max-height:none}
}

/* The three figures under the hero: five minutes, so many courses, so
   much of every subscription to the authors. Mono, because they are
   there to be compared. */
.beweis{display:grid;grid-template-columns:repeat(auto-fit,minmax(11rem,1fr));gap:1.6rem 2rem;
  border-bottom:1px solid var(--linie);padding:0 0 1.8rem;margin:0}
/* One grey rule over all three said "here is a row". Three coloured ones say
   "here are three things", which is what the row is for. */
.beweis div{display:flex;flex-direction:column;gap:.35rem;
  border-top:4px solid var(--ton,var(--salbei));padding-top:1.1rem}
.beweis b{font-family:var(--mono);font-size:2.2rem;font-weight:400;line-height:1;letter-spacing:-.03em;
  font-variant-numeric:tabular-nums}
.beweis span{font-family:var(--sans);font-size:10.5px;font-weight:600;letter-spacing:.16em;text-transform:uppercase;
  color:var(--grau);line-height:1.5}

/* A band headline is a sentence, not a title, so it is one voice: the
   quiet one, set large. That is the third size in the system — shout,
   statement, reading — and a statement is never in the poster cut. */
.band-titel{font-weight:300;font-size:clamp(1.9rem,4.6vw,2.9rem);line-height:1.12;letter-spacing:-.02em;
  margin:0 0 1rem;max-width:22ch;text-wrap:balance}
.band-vor{font-family:var(--mono);font-size:11px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--grau);display:block;margin-bottom:1.1rem}
.band-lauf{max-width:44ch;color:var(--graphit);font-size:1.08rem;margin-bottom:0}

/* Steps: number, rule, title, sentence. The number is mono and large
   because the order is the point. */
.schritte{display:grid;grid-template-columns:repeat(auto-fit,minmax(15rem,1fr));gap:2.2rem 2rem;margin-top:3rem}
.schritt{display:flex;flex-direction:column;gap:.6rem}
.schritt-nr{font-family:var(--mono);font-size:12px;letter-spacing:.16em;color:var(--grau);
  padding-bottom:.7rem;border-bottom:1px solid var(--linie)}
.schritt b{font-family:var(--plakat);font-weight:800;font-stretch:75%;font-size:1.5rem;line-height:1}
.schritt p{color:var(--graphit);font-size:1rem;margin:0}
.schritt .platte{margin-bottom:.4rem}

/* Two columns that swap sides down the page: picture, text, picture. */
.wechsel{display:grid;gap:2.2rem;align-items:center;margin-top:3rem}
@media(min-width:52rem){
  .wechsel{grid-template-columns:1fr 1fr;gap:3.5rem}
  .wechsel.gedreht>*:first-child{order:2}
}

/* A pull quote at band width: a statement, so the quiet voice set large. */
.grosszitat{font-weight:300;font-size:clamp(1.5rem,3.4vw,2.2rem);line-height:1.3;color:var(--tinte);margin:0;max-width:26ch}
.grosszitat+.hinweis{margin-top:1.2rem}

/* The newsletter sits in the last band, wide enough to type in. */
.brief{display:flex;gap:.6rem;flex-wrap:wrap;margin-top:1.4rem;max-width:30rem}
.brief input[type=email]{flex:1;min-width:13rem;border-radius:var(--rund-voll);padding:.85rem 1.2rem;
  border-width:1px}
.brief .knopf{width:auto;flex:0 0 auto}

.fuss{padding:2.6rem 0;font-family:var(--sans);font-size:12px;color:var(--grau);
  display:flex;flex-wrap:wrap;gap:.8rem 2rem;align-items:center;justify-content:space-between}
.fuss .wortmarke{font-size:1rem}
/* The footer is a block of its own now; its own padding is all the room it needs. */
.band.band-fuss{padding:0}

/* Scroll reveal. Wild's pages earn most of their motion this way: a
   band arrives rather than being already there. `--verzug` staggers the
   children of a group; anything past the fourth would only be waiting.
   The class is removed under prefers-reduced-motion further up. */
.enthuellen{opacity:0;transform:translateY(16px);
  transition:opacity .75s var(--schwung),transform .75s var(--schwung);transition-delay:var(--verzug,0s)}
.enthuellen.da{opacity:1;transform:none}
/* On paper there is no scrolling to reveal anything, so nothing may be
   waiting to be revealed. */
@media print{.enthuellen{opacity:1!important;transform:none!important}}

/* ------------------------------------------------- The plate pictures
   Every plate is 3:2 and bleeds to its frame, so a row of them is one
   height without any rule saying so. */
.plakat-bild{display:block;width:100%;height:auto}

/* ============================================================
   The numbers room: one series per chart, ink on paper, a table beneath
   ============================================================ */
.metrik-balken{display:flex;align-items:flex-end;gap:2px;height:6rem;margin:.6rem 0 .3rem;
  border-bottom:1px solid var(--linie-zart)}
.metrik-balken i{flex:1;min-width:2px;background:var(--tinte);border-radius:3px 3px 0 0;min-height:1px}
.metrik-balken i.leer{background:transparent}
.metrik-achse{display:flex;justify-content:space-between;font-family:var(--mono);font-size:10.5px;color:var(--grau)}
/* A section's name and, beside it, when its figure was computed. On one line
   while there is room, because the two belong to each other: the heading says
   what is being looked at and the note says as of when. */
.metrik-kopf{display:flex;gap:.6rem;align-items:baseline;flex-wrap:wrap}
.metrik-anteil{position:relative;height:.55rem;background:var(--papier-tief);border-radius:var(--rund);min-width:5rem}
.metrik-anteil i{display:block;height:100%;background:var(--tinte);border-radius:inherit}
.metrik-summe{display:flex;gap:1.6rem;flex-wrap:wrap;font-family:var(--mono);font-size:12px;color:var(--grau);margin-top:.4rem}
.metrik-summe b{color:var(--tinte);font-weight:400}
