/* NeoGerman.

   Two voices, and each one has a job.
   Source Serif carries the German under study: the sentence, the headword,
   the example. Nunito carries everything else: navigation, labels, features,
   tables, buttons. A reader can tell at a glance whether they are looking at
   German or at the machinery around it, and that is most of the hierarchy.

   Colour never carries meaning alone. Every underlined value is named in the
   key under the sentence and again in the panel that opens when you pick it.

   The theme starts light and stays light until somebody asks for dark. The
   system preference is not consulted: a study tool that opens near-black
   because the operating system is in dark mode is the thing this palette
   replaced. The toggle in the masthead remembers the choice. */

:root{
  color-scheme:light;

  --paper:#FAFCFA;
  --raise:#FFFFFF;
  --surface:#F0F5F1;
  --surface-2:#E2EDE6;
  --ink:#0F1F1A;
  --ink-2:#485B53;
  --ink-3:#63736C;
  --rule:#DEE9E2;
  --rule-2:#C2D3C9;
  /* A hairline between cards is decoration and a control's own border is not:
     the second is the thing a person has to find before they can type in it.
     So the field border is its own token, held at 3:1 against the page, and
     --rule-2 stays light enough to be a divider. */
  --field:#759B85;

  --primary:#047857;
  --primary-hi:#03624A;
  --primary-edge:#025038;
  --primary-ink:#FFFFFF;
  --primary-wash:#E3F6EE;

  --accent:#D11B43;
  --accent-soft:#FB7185;
  --accent-edge:#BE123C;
  --accent-ink:#FFFFFF;
  --accent-wash:#FFE8ED;

  --good:#059669;
  --warn:#B45309;
  --warn-wash:#FEF3C7;

  --serif:"Source Serif 4",Georgia,"Times New Roman",serif;
  --sans:"Nunito","Nunito Sans",system-ui,-apple-system,"Segoe UI",sans-serif;

  --t-2xs:11.5px; --t-xs:13px; --t-sm:14.5px; --t-base:16.5px;
  --t-md:18px; --t-lg:22px; --t-xl:28px; --t-2xl:36px; --t-3xl:48px;

  --s-1:4px; --s-2:8px; --s-3:12px; --s-4:18px; --s-5:26px;
  --s-6:38px; --s-7:56px; --s-8:80px; --s-9:112px;

  --r-sm:8px; --r:12px; --r-lg:18px; --r-xl:26px;
  --lift:4px;
  --shadow:0 2px 4px rgba(6,58,40,.05),0 12px 30px -14px rgba(6,58,40,.18);
  --shadow-sm:0 1px 2px rgba(6,58,40,.06),0 4px 12px -8px rgba(6,58,40,.14);

  --c-noun:#1D4ED8;        --c-verb:#C2410C;
  --c-adjective:#7C3AED;   --c-adverb:#BE185D;
  --c-pronoun:#0F766E;     --c-determiner:#4D7C0F;
  --c-preposition:#B45309; --c-conjunction:#A16207;
  --c-numeral:#0E7490;     --c-particle:#64748B;
  --c-interjection:#9333EA;

  --c-subject:#1D4ED8;              --c-direct-object:#4D7C0F;
  --c-indirect-object:#B45309;      --c-genitive-object:#7C3AED;
  --c-prepositional-object:#0F766E; --c-predicate:#BE185D;
  --c-modifier:#A16207;             --c-complement:#0E7490;
  --c-connector:#64748B;            --c-other:#78877F;
}

:root[data-theme="dark"]{
  color-scheme:dark;

  --paper:#0E1A16;
  --raise:#152520;
  --surface:#1B2E27;
  --surface-2:#254036;
  --ink:#E9F4ED;
  --ink-2:#A2BCB0;
  --ink-3:#86A093;
  --rule:#253931;
  --rule-2:#375245;
  --field:#527866;

  --primary:#34D399;
  --primary-hi:#6EE7B7;
  --primary-edge:#127A56;
  --primary-ink:#04231A;
  --primary-wash:#14382C;

  --accent:#FDA4AF;
  --accent-soft:#FB7185;
  --accent-edge:#9F1239;
  --accent-ink:#3F0716;
  --accent-wash:#3B2027;

  --good:#34D399;
  --warn:#FBBF24;
  --warn-wash:#3A2E12;

  --shadow:0 2px 4px rgba(0,0,0,.35),0 14px 32px -16px rgba(0,0,0,.7);
  --shadow-sm:0 1px 2px rgba(0,0,0,.35),0 6px 14px -10px rgba(0,0,0,.6);

  --c-noun:#7FB0F0;        --c-verb:#FB9E76;
  --c-adjective:#C4A6F5;   --c-adverb:#F594BF;
  --c-pronoun:#5FD3C0;     --c-determiner:#A9D97C;
  --c-preposition:#F3B366; --c-conjunction:#E2C55E;
  --c-numeral:#67C7DC;     --c-particle:#A2BCB0;
  --c-interjection:#D29CEE;

  --c-subject:#7FB0F0;              --c-direct-object:#A9D97C;
  --c-indirect-object:#F3B366;      --c-genitive-object:#C4A6F5;
  --c-prepositional-object:#5FD3C0; --c-predicate:#F594BF;
  --c-modifier:#E2C55E;             --c-complement:#67C7DC;
  --c-connector:#A2BCB0;            --c-other:#8FA79B;
}

*,*::before,*::after{box-sizing:border-box}
[hidden]{display:none !important}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;background:var(--paper);color:var(--ink);
  font:400 var(--t-base)/1.6 var(--sans);
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
  font-feature-settings:"kern" 1;
  overflow-x:hidden;
}
.col{width:100%;max-width:1160px;margin:0 auto;padding-left:32px;padding-right:32px}
#view-popular,#view-rules,#view-list,#view-about,#view-account,#view-word,#view-admin,#view-rule{
  max-width:960px;margin:0 auto}
.skip{position:absolute;left:-9999px;background:var(--raise);color:var(--ink);
  padding:12px 16px;z-index:99;border-radius:var(--r)}
.skip:focus{left:12px;top:12px}
:where(a,button,input,select,textarea):focus-visible{
  outline:3px solid var(--primary);outline-offset:2px;border-radius:var(--r-sm)}
::selection{background:var(--primary-wash);color:var(--ink)}

/* ---------- type ---------- */
h1{font:800 var(--t-2xl)/1.14 var(--sans);letter-spacing:-.022em;margin:0 0 var(--s-3);color:var(--ink)}
h2{font:800 var(--t-lg)/1.28 var(--sans);letter-spacing:-.014em;margin:0 0 var(--s-4);
   display:flex;align-items:baseline;gap:var(--s-3);flex-wrap:wrap}
h3{font:700 var(--t-md)/1.35 var(--sans);letter-spacing:-.008em;margin:0 0 var(--s-2)}
p{margin:0 0 var(--s-4)}
.prose{max-width:66ch}
.prose p{font:400 var(--t-base)/1.7 var(--sans);color:var(--ink-2);margin:0 0 var(--s-4)}
.prose p:last-child{margin-bottom:0}
.prose strong{color:var(--ink);font-weight:700}
.prose-wrap{max-width:74ch}
.standfirst{font:400 var(--t-md)/1.55 var(--sans);color:var(--ink-2);letter-spacing:-.004em;
  margin:0 0 var(--s-6);max-width:58ch}
.hint{font:400 var(--t-sm)/1.55 var(--sans);color:var(--ink-3);margin:0 0 var(--s-4)}
.tally{font:700 var(--t-xs) var(--sans);color:var(--ink-3);letter-spacing:.04em;
  text-transform:uppercase}
.label{display:block;font:700 var(--t-xs)/1.4 var(--sans);color:var(--ink-3);
  letter-spacing:.07em;text-transform:uppercase;margin:0 0 var(--s-2)}
.label.inline{display:inline;margin:0}
.lexstat{font:400 var(--t-sm)/1.6 var(--sans);color:var(--ink-3);max-width:64ch;margin:var(--s-4) 0 0}
strong{font-weight:700}
em{font-style:italic}

/* ---------- masthead ---------- */
.masthead{position:sticky;top:0;z-index:50;
  background:color-mix(in srgb,var(--paper) 90%,transparent);
  -webkit-backdrop-filter:saturate(180%) blur(12px);backdrop-filter:saturate(180%) blur(12px);
  border-bottom:1px solid var(--rule)}
.masthead-in{display:flex;align-items:center;justify-content:space-between;gap:var(--s-4);
  min-height:68px;flex-wrap:wrap}
.wordmark{font:800 var(--t-md) var(--sans);letter-spacing:-.028em;color:var(--ink);
  text-decoration:none;white-space:nowrap;display:inline-flex;align-items:center;gap:9px}
.wordmark::before{content:"";width:26px;height:26px;border-radius:9px;flex:0 0 auto;
  background:linear-gradient(150deg,var(--primary),var(--primary-hi));
  box-shadow:inset 0 -2px 0 rgba(0,0,0,.14)}
.wordmark:hover{color:var(--primary)}
.nav{display:flex;gap:2px;flex-wrap:wrap;align-items:center}
.navlink{font:700 var(--t-sm)/1 var(--sans);color:var(--ink-3);background:none;border:0;
  padding:11px 14px;cursor:pointer;border-radius:999px;position:relative;white-space:nowrap;
  transition:color .12s ease,background-color .12s ease}
.navlink:hover{color:var(--ink);background:var(--surface)}
.navlink.is-on{color:var(--primary);background:var(--primary-wash)}

/* the theme switch sits at the end of the nav and says what it will do */
.theme-toggle{font:700 var(--t-xs)/1 var(--sans);color:var(--ink-3);background:var(--surface);
  border:0;border-radius:999px;padding:10px 14px;cursor:pointer;margin-left:var(--s-2);
  display:inline-flex;align-items:center;gap:6px;min-height:36px;white-space:nowrap;
  transition:color .12s ease,background-color .12s ease}
.theme-toggle:hover{color:var(--ink);background:var(--surface-2)}

main{padding-top:var(--s-7);padding-bottom:var(--s-9);display:block}
.view>h1:first-child{margin-top:0}
.block{margin-top:var(--s-7);padding-top:var(--s-6);border-top:1px solid var(--rule)}
.block:first-child{margin-top:0;padding-top:0;border-top:0}
.backline{margin:0 0 var(--s-5)}

/* ---------- the hero and the composer ---------- */
.hero{display:grid;gap:var(--s-7);align-items:start;
  grid-template-columns:minmax(0,1fr) minmax(0,1.05fr)}
.hero-copy h1{font-size:var(--t-3xl);max-width:13ch;margin-bottom:var(--s-4)}
.hero-copy .standfirst{margin-bottom:var(--s-5);max-width:42ch}
.composer{background:var(--raise);border:2px solid var(--rule);border-radius:var(--r-xl);
  padding:var(--s-5);box-shadow:var(--shadow-sm)}
.composer-row{margin-bottom:0;align-items:center;justify-content:flex-end;gap:var(--s-4)}
/* The message takes the room left of the button and the button keeps its size,
   so a short message costs no layout at all and a long progress line wraps
   inside the space rather than pushing anything down. */
.composer-row .status{flex:1 1 180px;min-width:0;margin:0;text-align:left}
.composer .btn{flex:0 0 auto}

/* the badges under the hero copy: what a reader gets, without a paragraph */
.hero-points{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--s-3)}
.hero-points li{display:flex;gap:var(--s-3);align-items:flex-start;
  font:600 var(--t-sm)/1.5 var(--sans);color:var(--ink-2)}
.hero-points svg{flex:0 0 auto;width:22px;height:22px;margin-top:1px;color:var(--primary)}

/* ---------- controls ---------- */
textarea,select,input[type=email],input[type=password],input[type=text]{
  width:100%;font:400 var(--t-base)/1.5 var(--sans);color:var(--ink);
  background:var(--paper);border:2px solid var(--field);border-radius:var(--r);
  padding:12px 14px;margin:0 0 var(--s-4);
  transition:border-color .12s ease,box-shadow .12s ease}
textarea{resize:vertical;min-height:112px;font:400 var(--t-lg)/1.5 var(--serif);
  border-radius:var(--r-lg)}
textarea::placeholder{color:var(--ink-3);font-style:italic}
input::placeholder{color:var(--ink-3)}
input:hover,textarea:hover,select:hover{border-color:var(--ink-3)}
input:focus,textarea:focus,select:focus{border-color:var(--primary);outline:none;
  box-shadow:0 0 0 4px var(--primary-wash)}

/* A select is drawn by the browser and its own arrow sat against the text.
   The arrow is ours now, and the padding on the right is what keeps a long
   option from running into it. */
select{
  -webkit-appearance:none;appearance:none;cursor:pointer;
  min-width:150px;max-width:230px;min-height:48px;
  padding:12px 44px 12px 14px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%2363736C' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 8l5 5 5-5'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 13px center;background-size:19px 19px}
:root[data-theme="dark"] select{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%2386A093' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 8l5 5 5-5'/%3E%3C/svg%3E")}
select::-ms-expand{display:none}

.row{display:flex;gap:var(--s-4);align-items:flex-end;flex-wrap:wrap;margin-bottom:var(--s-4)}
.row>*{margin-bottom:0}
.inline-field{display:block}
.inline-field select{margin-bottom:0}
.toolbar{display:inline-flex;width:auto;max-width:100%;padding:var(--s-4) var(--s-5);
  background:var(--surface);border-radius:var(--r-lg);margin-bottom:var(--s-6);
  gap:var(--s-5);align-items:flex-end;flex-wrap:wrap}
.toolbar .label{margin-bottom:6px}

/* The button has a solid edge under it and loses the edge when pressed, so a
   tap has somewhere to go. Height and padding are the same on every one of
   them, which is what stops the row of controls looking assembled by hand. */
.btn{font:800 var(--t-base)/1 var(--sans);color:var(--primary-ink);background:var(--primary);
  border:0;border-radius:var(--r-lg);padding:0 26px;min-height:52px;
  display:inline-flex;align-items:center;justify-content:center;gap:9px;
  cursor:pointer;white-space:nowrap;letter-spacing:.005em;
  box-shadow:0 var(--lift) 0 var(--primary-edge);
  transition:background-color .12s ease,box-shadow .08s ease,transform .08s ease}
.btn:hover{background:var(--primary-hi)}
.btn:active{transform:translateY(var(--lift));box-shadow:0 0 0 var(--primary-edge)}
.btn:disabled{opacity:.5;cursor:not-allowed;transform:none;
  box-shadow:0 var(--lift) 0 var(--primary-edge)}
.btn svg{width:20px;height:20px;flex:0 0 auto}
.btn-quiet{background:var(--surface);color:var(--ink);box-shadow:0 var(--lift) 0 var(--rule-2)}
.btn-quiet:hover{background:var(--surface-2)}
.btn-quiet:active{box-shadow:0 0 0 var(--rule-2)}
.btn-quiet:disabled{box-shadow:0 var(--lift) 0 var(--rule-2)}
.btn-accent{background:var(--accent);color:var(--accent-ink);box-shadow:0 var(--lift) 0 var(--accent-edge)}
.btn-accent:hover{background:var(--accent-soft)}
.btn-accent:active{box-shadow:0 0 0 var(--accent-edge)}
.btn-sm{min-height:42px;padding:0 18px;font-size:var(--t-sm);border-radius:var(--r)}

.linkish{font:700 var(--t-sm)/1.4 var(--sans);color:var(--primary);background:none;border:0;
  padding:7px 11px;margin:0 -11px;cursor:pointer;border-radius:999px;
  display:inline-flex;align-items:center;gap:6px;min-height:36px;
  transition:color .12s ease,background-color .12s ease}
.linkish:hover{color:var(--primary-hi);background:var(--primary-wash)}
.linkish.is-on{color:var(--primary-hi);background:var(--primary-wash)}
.linkish:disabled{opacity:.5;cursor:default;background:none}
.linkish.danger{color:var(--accent)}
.linkish.danger:hover{color:var(--accent);background:var(--accent-wash)}

.chip{font:700 var(--t-sm)/1 var(--sans);color:var(--ink-2);background:var(--surface);
  border:2px solid transparent;border-radius:999px;padding:11px 17px;cursor:pointer;
  min-height:44px;display:inline-flex;align-items:center;
  transition:background-color .12s ease,color .12s ease,border-color .12s ease}
.chip:hover{color:var(--ink);background:var(--surface-2)}
.chip.is-on{background:var(--primary-wash);color:var(--primary-hi);border-color:var(--primary)}

/* "Try one of the example sentences" is a line of its own, and the chips are
   a row under it. They used to share a line, which read as though the label
   were the first chip. */
.tries{display:block;margin:var(--s-5) 0 0}
.tries .label{display:block;margin:0 0 var(--s-3)}
.tries-row{display:flex;gap:var(--s-2);flex-wrap:wrap}

/* The status belongs beside the control that produced it. It sits inside the
   composer, under the button, so an empty box tells you so where you are
   looking rather than at the bottom of the page. */
.status{font:600 var(--t-sm)/1.5 var(--sans);color:var(--ink-2);margin:var(--s-4) 0 0}
.status:empty{display:none}
.status.err{color:var(--accent);background:var(--accent-wash);border-radius:var(--r);
  padding:12px 14px;display:flex;gap:9px;align-items:flex-start}
/* Inside the composer it is a line of text with a mark beside it, not a filled
   panel. A mistyped box is a nudge and the panel was shouting. */
.composer .status.err{background:none;padding:0;font-size:var(--t-sm);align-items:center}
/* The message and the button share a row, so the message is centred on the
   button rather than sitting under its middle. It had a top margin left over
   from when it was a line of its own below the row, and a margin inside a
   centred flex row is an offset from centre and nothing else. */
.composer-row .status{margin:0;align-self:center}
.status.err::before{content:"";flex:0 0 auto;width:19px;height:19px;margin-top:1px;
  background:currentColor;
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7v6M12 16.5v.01'/%3E%3C/svg%3E") center/contain no-repeat;
  mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7v6M12 16.5v.01'/%3E%3C/svg%3E") center/contain no-repeat}

/* ---------- the reading: sentence, rail, body ---------- */
.result{display:grid;gap:0 var(--s-7);align-items:start;
  grid-template-columns:minmax(0,1fr) minmax(280px,340px);
  grid-template-areas:"sent rail" "body rail"}
.sent-block{grid-area:sent}
.rail{grid-area:rail;position:sticky;top:92px}
.result-body{grid-area:body;min-width:0;padding-top:var(--s-7)}

.meta{font:700 var(--t-xs)/1 var(--sans);color:var(--ink-3);letter-spacing:.06em;
  text-transform:uppercase;margin:0 0 var(--s-4);display:flex;gap:var(--s-3);
  flex-wrap:wrap;align-items:center}
.meta span+span::before{content:"";display:inline-block;width:3px;height:3px;border-radius:50%;
  background:var(--rule-2);vertical-align:middle;margin-right:var(--s-3)}

.sentence{font:400 clamp(24px,2.5vw,33px)/1.95 var(--serif);letter-spacing:-.004em;
  color:var(--ink);margin:0 0 var(--s-5);max-width:26em;text-wrap:pretty}
.tok{display:inline;font:inherit;color:inherit;background:none;border:0;border-radius:3px;
  padding:0 .04em 2px;margin:0;cursor:pointer;-webkit-appearance:none;appearance:none;
  border-bottom:3px solid var(--tok,var(--rule-2));
  transition:color .1s ease,background-color .1s ease,border-color .1s ease}
.tok:hover{color:var(--primary-hi);border-bottom-color:var(--primary)}
/* A word marked because its class was picked in the key. Before the states
   that mean something a reader did to that one word, so an open word still
   reads as the open word. */
.tok.picked{background:color-mix(in srgb,var(--tok) 26%,transparent)}
.tok.sel{background:var(--primary);color:var(--primary-ink);border-bottom-color:var(--primary)}
.tok.linked{background:var(--primary-wash);border-bottom-color:var(--primary)}
.tok.evidence{background:var(--warn-wash)}
.tok.punct{cursor:default;border-bottom-color:transparent;padding:0}
/* A sentence still being read is set in full ink like any other, because it is
   the thing the reader asked for and the minute they wait is spent looking at
   it. What marks it as unfinished is the panel under it and the fact that no
   word in it can be opened yet, rather than the text being greyed out. */
.sentence.is-waiting{color:var(--ink)}

/* Putting this sentence on your own list. Under the key, where the reading
   stops being about this sentence and turns to the grammar behind it. */
.sent-save{margin:var(--s-4) 0 0}

.switch{display:flex;gap:var(--s-2);align-items:center;flex-wrap:wrap;margin:var(--s-5) 0 var(--s-4)}
.key{display:flex;gap:var(--s-2) var(--s-3);flex-wrap:wrap;margin:0;
  font:700 var(--t-xs) var(--sans);color:var(--ink-3)}
.key i{font-style:normal;border-bottom:3px solid var(--tok,var(--rule-2));padding-bottom:2px}
/* Each name in the key is the control that marks its own words in the
   sentence. It carries its class colour in --tok, which is what the underline
   under the name and the wash behind a picked one are both drawn from, so the
   name and the words it lit are the same colour by construction. The gap above
   is a little tighter than it was because each name now has padding of its
   own, and the two together read as too far apart. */
.key-pick{font:inherit;color:inherit;background:none;border:0;border-radius:var(--r-sm);
  padding:3px var(--s-2) 4px;margin:0;cursor:pointer;-webkit-appearance:none;appearance:none;
  transition:background-color .1s ease,color .1s ease}
.key-pick:hover{color:var(--ink)}
.key-pick.is-on{background:color-mix(in srgb,var(--tok) 26%,transparent);color:var(--ink)}

.rail .reading{position:relative;background:var(--raise);border:2px solid var(--rule);
  border-radius:var(--r-xl);padding:var(--s-5);box-shadow:var(--shadow)}
.reading .headword{font:700 var(--t-xl)/1.15 var(--serif);letter-spacing:-.012em;
  margin:0 0 var(--s-1);color:var(--ink)}
.reading .from{font:600 var(--t-sm) var(--sans);color:var(--ink-3);margin:0 0 var(--s-3)}
.reading .gloss{font:400 var(--t-base)/1.55 var(--sans);color:var(--ink-2);margin:0 0 var(--s-4);
  padding-bottom:var(--s-4);border-bottom:1px solid var(--rule)}
.feats{display:flex;flex-direction:column;gap:var(--s-2);margin:0 0 var(--s-4);
  font:400 var(--t-sm) var(--sans)}
.feats span{display:flex;justify-content:space-between;gap:var(--s-3);color:var(--ink-3);
  letter-spacing:.01em}
.feats b{font-weight:700;color:var(--ink);text-align:right}
.feats span+span::before{content:none}
/* Picking a word is easy and putting it down was not: the only way back was to
   find the same word and click it again, and once the sentence had scrolled
   past, the word stayed marked in the rail copy with no panel to explain it.
   So the panel carries its own way out on every screen, not only on a phone
   where it is a sheet. Escape and a click outside the sentence do the same. */
.sheet-close{position:absolute;top:10px;right:10px;
  font:700 var(--t-2xs) var(--sans);letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-3);background:var(--surface);border:0;border-radius:999px;
  padding:8px 13px;cursor:pointer;min-height:32px;
  transition:color .12s ease,background-color .12s ease}
.sheet-close:hover{background:var(--surface-2);color:var(--ink)}
.rail .reading .headword{padding-right:76px}
.rail-idle{background:var(--surface);border:2px dashed var(--rule-2);border-radius:var(--r-xl);
  padding:var(--s-5);margin:0;text-align:center;color:var(--ink-3);font-size:var(--t-sm)}
#token-detail:not([hidden])+.rail-idle{display:none}
.reading .gl-actions{margin:0;padding-top:var(--s-4);border-top:1px solid var(--rule)}

.translation{font:700 var(--t-lg)/1.45 var(--sans);letter-spacing:-.014em;
  margin:0 0 var(--s-2);max-width:48ch;color:var(--ink)}
.literal{font:400 var(--t-sm)/1.6 var(--sans);color:var(--ink-3);margin:0 0 var(--s-5)}
.credit{font:400 var(--t-xs)/1.6 var(--sans);color:var(--ink-3);background:var(--surface);
  border-radius:var(--r);padding:var(--s-3) var(--s-4);margin:0 0 var(--s-4);max-width:64ch}
.credit a{color:var(--primary)}
.credit-note{display:block;color:var(--ink-3);margin-top:var(--s-1);opacity:.85}

.thin{background:var(--warn-wash);border:2px solid color-mix(in srgb,var(--warn) 32%,transparent);
  border-radius:var(--r-lg);padding:var(--s-4);margin:0 0 var(--s-4);max-width:64ch}
.thin p{font:400 var(--t-sm)/1.6 var(--sans);color:var(--ink-2);margin:0 0 var(--s-3)}
.thin p:last-child{margin:0}

/* The sentence, kept in the rail while you read about it. Smaller than the
   real one, because it is a reminder rather than the thing itself.

   It grows to whatever the sentence needs. It used to stop at 38vh, which is
   about a third of the room the rail actually has, so a long news sentence was
   cut off mid-word with nothing saying so. The cap is the viewport now, minus
   the masthead and a little air, because the rail is sticky and a box taller
   than the screen stops sticking. Where even that is not enough, is-clipped
   fades the last line and says the rest is below, rather than ending the
   sentence with a straight edge. */
.rail-sentence{background:var(--surface);border-radius:var(--r-xl);
  padding:var(--s-4) var(--s-5);margin:0 0 var(--s-4);
  max-height:calc(100vh - 132px);overflow-y:auto;overscroll-behavior:contain}
.rail-sentence.is-clipped{
  -webkit-mask-image:linear-gradient(to bottom,#000 calc(100% - 34px),transparent);
  mask-image:linear-gradient(to bottom,#000 calc(100% - 34px),transparent)}
.rail-sentence.is-clipped .rail-cap::after{content:" · scroll for the rest";
  font-weight:700;color:var(--ink-3);letter-spacing:.03em}
.rail-sentence .rail-cap{display:block;font:700 var(--t-2xs) var(--sans);
  letter-spacing:.07em;text-transform:uppercase;color:var(--ink-3);margin:0 0 var(--s-2)}
.rail-sentence .sentence{font:400 var(--t-base)/1.85 var(--serif);margin:0;max-width:none}
.rail-sentence .tok{border-bottom-width:2px;cursor:pointer}

/* A word or a rule under the pointer lights up where it lives in the sentence.
   Same mark in the real sentence and in the rail copy, so whichever one you can
   see is the one that answers. */
.tok.hot{background:var(--warn-wash);
  box-shadow:inset 0 -2px 0 color-mix(in srgb,var(--warn) 55%,transparent)}
.word-card.is-hot,.rules li.is-hot .rc-head{background:var(--surface)}

/* The page a reader lands on when they ask for a sentence nobody has read yet.
   Not an error: nothing has gone wrong, this one simply has to be paid for. */
.newbox{background:var(--raise);border:2px solid var(--rule);border-radius:var(--r-xl);
  padding:var(--s-6);margin:var(--s-6) 0 0;max-width:70ch;box-shadow:var(--shadow-sm)}
.newbox h1,.newbox h2{margin-bottom:var(--s-3)}
.newbox .quoted{font:400 var(--t-md)/1.6 var(--serif);color:var(--ink);
  background:var(--surface);border-radius:var(--r);padding:var(--s-4);margin:0 0 var(--s-4)}
.newbox p{font:400 var(--t-base)/1.65 var(--sans);color:var(--ink-2);margin:0 0 var(--s-4)}
.newbox .newbox-actions{display:flex;gap:var(--s-3);flex-wrap:wrap;align-items:center;margin:var(--s-5) 0 0}
.newbox ul{margin:0 0 var(--s-4);padding-left:var(--s-5);color:var(--ink-2)}
.newbox li{margin:0 0 var(--s-2);font:400 var(--t-base)/1.6 var(--sans)}

/* ---------- the news feed ---------- */
.feed{list-style:none;margin:0;padding:0;display:grid;gap:var(--s-4)}
@media (min-width:900px){.feed{grid-template-columns:1fr 1fr;gap:var(--s-4)}}
/* Each item is a card that is entirely clickable, rather than a stack of text
   with one link in it and a hairline between the stacks. */
.feed li{margin:0}
.feed-card{display:block;width:100%;text-align:left;cursor:pointer;
  background:var(--raise);border:2px solid var(--rule);border-radius:var(--r-lg);
  padding:var(--s-4) var(--s-5);text-decoration:none;color:inherit;
  transition:border-color .12s ease,transform .1s ease,box-shadow .12s ease}
.feed-card:hover{border-color:var(--primary);transform:translateY(-2px);box-shadow:var(--shadow-sm)}
.feed-de{display:block;font:400 var(--t-md)/1.5 var(--serif);letter-spacing:-.002em;
  color:var(--ink);
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.feed-en{margin:var(--s-2) 0 0;color:var(--ink-2);font:400 var(--t-sm)/1.6 var(--sans);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.feed-cite{margin:var(--s-3) 0 0;font:600 var(--t-xs)/1.5 var(--sans);color:var(--ink-3);
  display:flex;gap:var(--s-2);align-items:center;flex-wrap:wrap}
.feed-lvl{display:inline-block;font:800 var(--t-2xs) var(--sans);font-variant-numeric:tabular-nums;
  background:var(--primary-wash);color:var(--primary-hi);
  border-radius:999px;padding:3px 9px;letter-spacing:.05em}

/* ---------- rules ---------- */
.rules{list-style:none;margin:0;padding:0;display:grid;gap:var(--s-3)}
.rules li{margin:0}
/* The catalogue is a grid of cards a reader opens, not rows with a hairline.
   Each card is one control, so the whole of it is the target. */
.rule-card{display:flex;width:100%;text-align:left;gap:var(--s-4);align-items:flex-start;
  background:var(--raise);border:2px solid var(--rule);border-radius:var(--r-lg);
  padding:var(--s-4) var(--s-5);cursor:pointer;color:inherit;
  font:400 var(--t-base) var(--sans);text-decoration:none;
  transition:border-color .12s ease,transform .1s ease,box-shadow .12s ease}
.rule-card:hover{border-color:var(--primary);transform:translateY(-2px);box-shadow:var(--shadow-sm)}
.rule-main{flex:1 1 auto;min-width:0}
.rule-card .rc-name{font:800 var(--t-md)/1.35 var(--sans);letter-spacing:-.01em;color:var(--ink);
  display:block;margin:0 0 2px}
.rule-card .rc-name em{display:block;font-style:normal;font:400 var(--t-sm) var(--serif);
  color:var(--ink-3);margin-top:2px}
.rule-card .rc-why{font:400 var(--t-sm)/1.6 var(--sans);color:var(--ink-2);margin:var(--s-2) 0 0;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.rule-side{flex:0 0 auto;display:flex;flex-direction:column;gap:6px;align-items:flex-end}
.pill{display:inline-block;font:800 var(--t-2xs)/1 var(--sans);letter-spacing:.05em;
  border-radius:999px;padding:6px 10px;white-space:nowrap}
.pill-level{background:var(--primary-wash);color:var(--primary-hi)}
.pill-count{background:var(--surface);color:var(--ink-3)}
.pill-central{background:var(--accent-wash);color:var(--accent)}
.pill-warn{background:var(--warn-wash);color:var(--warn)}

/* the rules inside one reading stay a disclosure list */
.rc-head{width:100%;display:flex;align-items:baseline;gap:var(--s-4);background:none;
  border:0;color:var(--ink);text-align:left;cursor:pointer;padding:var(--s-4);
  font:400 var(--t-base) var(--sans);border-radius:var(--r);
  transition:background-color .12s ease}
.rc-head:hover{background:var(--surface)}
.rc-name{flex:1 1 auto;font:700 var(--t-base)/1.4 var(--sans);letter-spacing:-.008em;color:var(--ink)}
.rc-head:hover .rc-name{color:var(--primary-hi)}
.rc-name em{display:block;font-style:normal;font:400 var(--t-sm) var(--sans);
  color:var(--ink-3);margin-top:2px}
.rc-side{font:700 var(--t-xs) var(--sans);color:var(--ink-3);white-space:nowrap;
  letter-spacing:.03em;text-transform:uppercase}
.rc-body{padding:0 var(--s-4) var(--s-5);max-width:70ch}
.rc-ev{font:600 var(--t-lg)/1.45 var(--serif);color:var(--ink);margin:0 0 var(--s-3)}
.rc-why{font:400 var(--t-base)/1.65 var(--sans);color:var(--ink-2);margin:0 0 var(--s-3)}
.rc-rule{font:400 var(--t-sm)/1.65 var(--sans);color:var(--ink-3);margin:0;
  padding-left:var(--s-4);border-left:3px solid var(--rule)}
.result-body .rules{gap:0}
.result-body .rules li{border-top:1px solid var(--rule)}
.result-body .rules li:first-child{border-top:0}
.central .rc-name::after{content:"central";display:inline-block;margin-left:var(--s-3);
  font:800 var(--t-2xs) var(--sans);letter-spacing:.05em;text-transform:uppercase;
  color:var(--accent);background:var(--accent-wash);border-radius:999px;padding:3px 9px;
  vertical-align:middle}

/* The shape of a rule card, held while the catalogue answers. Blocks of the
   right size in the right places, so nothing moves when the real text lands. */
.rule-card.is-skeleton{cursor:default;pointer-events:none}
.rule-card.is-skeleton:hover{border-color:var(--rule);transform:none;box-shadow:none}
.sk{display:block;border-radius:6px;background:var(--surface-2);
  animation:sk-pulse 1.4s ease-in-out infinite}
.sk-name{width:42%;height:19px;margin:0 0 10px}
.sk-line{width:100%;height:12px;margin:0 0 7px}
.sk-short{width:64%}
.sk-pill{width:44px;height:22px;border-radius:999px}
@keyframes sk-pulse{0%,100%{opacity:1}50%{opacity:.45}}
@media (prefers-reduced-motion:reduce){.sk{animation:none}}

/* One row of a reading that has not arrived: a rule, or a word. The same pieces
   at the size the real thing will be, so the page keeps its layout while it
   waits instead of jumping when the answer lands.

   Which is why there are two of them. A word is a bordered card and a rule is a
   flat row over a hairline, so one shape standing in for both would have held
   the wrong amount of room for one of them and moved the page anyway. */
.sk-row{list-style:none;display:flex;gap:var(--s-4);align-items:center;
  justify-content:space-between;background:var(--raise);border:2px solid var(--rule);
  border-radius:var(--r-lg);padding:var(--s-4) var(--s-5);margin:0}
.sk-row.sk-flat{background:none;border:0;border-bottom:1px solid var(--rule);
  border-radius:0;padding:var(--s-4) 0}
.sk-row .sk-name{width:38%;margin:0}
.sk-row .sk-line{margin:0}
.sk-row .sk-short{width:30%}

/* ---------- a sentence while it is being read ---------- */
/* The wait has a shape of its own. It says what is happening in a sentence a
   person can read, and it counts the seconds, which is the only number here
   that anything actually knows. */
.analysing{background:var(--surface);border-radius:var(--r-lg);
  padding:var(--s-4) var(--s-5);margin:0 0 var(--s-5);max-width:54ch}
.analysing-stage{display:flex;gap:var(--s-3);align-items:baseline;margin:0 0 var(--s-3);
  font:600 var(--t-sm)/1.5 var(--sans);color:var(--ink)}
.analysing-note{font:400 var(--t-xs)/1.6 var(--sans);color:var(--ink-3);margin:var(--s-3) 0 0}
/* Pushed to the far end of the stage row rather than floated into the prose
   under it, where it landed beside whichever word happened to end the last
   line. Tabular figures so the row does not twitch every second. */
.analysing-clock{margin-left:auto;padding-left:var(--s-3);flex:0 0 auto;
  font-variant-numeric:tabular-nums;font-weight:800;color:var(--ink-3)}

/* Three dots filling in turn: the smallest thing that says "working" without
   claiming to know how far along the work is. */
.pulse{display:inline-flex;gap:5px;align-items:center;flex:0 0 auto;position:relative;top:-2px}
.pulse i{width:6px;height:6px;border-radius:50%;background:var(--primary);opacity:.3;
  animation:pulse-dot 1.2s ease-in-out infinite}
.pulse i:nth-child(2){animation-delay:.15s}
.pulse i:nth-child(3){animation-delay:.3s}
@keyframes pulse-dot{0%,100%{opacity:.3;transform:scale(.85)}40%{opacity:1;transform:scale(1)}}

/* Indeterminate on purpose. Nothing knows how far through the model is, so the
   bar travels rather than fills. A bar that filled would be inventing a number,
   and it would sit at the far end for minutes on the sentences that take them. */
.analysing-track{height:4px;border-radius:999px;background:var(--surface-2);overflow:hidden}
.analysing-track i{display:block;height:100%;width:38%;border-radius:999px;
  background:linear-gradient(90deg,transparent,var(--primary),transparent);
  animation:track-run 1.9s ease-in-out infinite}
@keyframes track-run{0%{transform:translateX(-105%)}100%{transform:translateX(370%)}}
@media (prefers-reduced-motion:reduce){
  .pulse i{animation:none;opacity:.75}
  .analysing-track i{animation:none;width:100%;opacity:.35;background:var(--primary)}
}

/* Being read now, in the line that will carry the level and the word count. */
.meta .is-live{color:var(--primary);font-weight:800}

/* ---------- one rule's own page ---------- */
.rule-hero{background:var(--surface);border-radius:var(--r-xl);padding:var(--s-5) var(--s-6);
  margin:0 0 var(--s-6)}
.rule-hero h1{margin-bottom:var(--s-2)}
.rule-german{font:400 var(--t-lg) var(--serif);color:var(--ink-3);margin:0 0 var(--s-4)}
.rule-explain{font:400 var(--t-md)/1.65 var(--sans);color:var(--ink-2);margin:0;max-width:66ch}
.rule-tags{display:flex;gap:var(--s-2);flex-wrap:wrap;margin:0 0 var(--s-4)}
.examples{list-style:none;margin:0;padding:0;display:grid;gap:var(--s-4)}
.example{position:relative;background:var(--raise);border:2px solid var(--rule);
  border-radius:var(--r-lg);padding:var(--s-5);margin:0;
  transition:border-color .12s ease,transform .1s ease,box-shadow .12s ease}
.example:has(.card-hit):hover{border-color:var(--primary);transform:translateY(-2px);
  box-shadow:var(--shadow-sm)}
.example>.card-hit{position:absolute;inset:0;z-index:0;pointer-events:auto;
  border-radius:inherit;background:none;border:0;cursor:pointer;
  font:inherit;color:transparent;padding:0}
.example>.card-hit:focus-visible{outline:3px solid var(--primary);outline-offset:2px}
.example>*:not(.card-hit){position:relative;z-index:1;pointer-events:none}
.example .ex-foot,.example .ex-foot *{pointer-events:auto}
.example.is-central{border-color:color-mix(in srgb,var(--primary) 40%,transparent)}
.ex-top{display:flex;gap:var(--s-3);align-items:center;flex-wrap:wrap;margin:0 0 var(--s-3)}
.ex-de{font:400 var(--t-md)/1.7 var(--serif);color:var(--ink);margin:0 0 var(--s-2);
  text-wrap:pretty}
.ex-de mark{background:var(--warn-wash);color:inherit;border-radius:4px;padding:1px 3px;
  box-shadow:inset 0 -2px 0 color-mix(in srgb,var(--warn) 45%,transparent)}
.ex-en{font:400 var(--t-sm)/1.6 var(--sans);color:var(--ink-2);margin:0 0 var(--s-3)}
.ex-why{font:400 var(--t-sm)/1.6 var(--sans);color:var(--ink-3);margin:0 0 var(--s-3);
  padding-left:var(--s-4);border-left:3px solid var(--rule)}
.ex-foot{display:flex;gap:var(--s-3);align-items:center;flex-wrap:wrap}
.related{list-style:none;margin:0;padding:0;display:flex;gap:var(--s-2);flex-wrap:wrap}
/* An anchor now, for the reason on catalogueCard: a related rule that is only
   a button is a rule no crawler can reach and no reader can open in a tab.
   display:inline-flex holds the 44px hit area an anchor does not get on its
   own from min-height alone. */
.related a{display:inline-flex;align-items:center;font:700 var(--t-sm) var(--sans);
  color:var(--ink-2);background:var(--surface);text-decoration:none;
  border:2px solid transparent;border-radius:999px;padding:11px 17px;cursor:pointer;min-height:44px;
  transition:background-color .12s ease,color .12s ease,border-color .12s ease}
.related a:hover{background:var(--primary-wash);color:var(--primary-hi);border-color:var(--primary)}

/* ---------- word lists ---------- */
.glossary{list-style:none;margin:0;padding:0;display:grid;gap:var(--s-3)}
.glossary>li{margin:0}
/* One row of the lexicon is a card, and the card itself opens the word. The
   two links that used to be the only targets are a button on the card now. */
.word-card{position:relative;background:var(--raise);border:2px solid var(--rule);
  border-radius:var(--r-lg);padding:var(--s-4) var(--s-5);display:flex;gap:var(--s-5);
  align-items:flex-start;flex-wrap:wrap;
  transition:border-color .12s ease,transform .1s ease,box-shadow .12s ease}
.word-card:hover{border-color:var(--primary);transform:translateY(-2px);box-shadow:var(--shadow-sm)}
/* The whole card is the target. The hit button is stretched over the card and
   sits beneath the content; the content takes no clicks of its own, so a click
   anywhere lands on the button. The actions row is the exception, because Save
   has its own job.

   Both rules below are written against `.word-card>` on purpose. `>*` and
   `.card-hit` on their own tie on specificity, and `>*` comes later, so it won
   and turned the hit button back to position:relative. An absolutely positioned
   overlay that is no longer absolutely positioned is a zero by zero button, and
   the card silently stopped being clickable at all. */
.word-card>*{position:relative;z-index:1;pointer-events:none}
.word-card>.card-hit{position:absolute;inset:0;z-index:0;pointer-events:auto;
  border-radius:inherit;background:none;border:0;cursor:pointer;
  font:inherit;color:transparent;padding:0}
.word-card>.card-hit:focus-visible{outline:3px solid var(--primary);outline-offset:2px}
.word-card .gl-actions,.word-card .gl-actions *{pointer-events:auto}
.gl-head{font:700 var(--t-lg)/1.3 var(--serif);letter-spacing:-.006em;min-width:180px;color:var(--ink)}
/* A saved sentence is the head of its own row, so it needs the room a lemma
   does not: a whole German sentence on one 180 pixel column would be a column
   of two word lines. */
.gl-head.is-sentence{flex:1 1 100%;min-width:0;font-weight:400;text-wrap:pretty}
.gl-head .art{color:var(--ink-3);font-weight:400}
.gl-body{flex:1 1 300px;min-width:0}
.gl-body p{margin:0 0 var(--s-2);font:400 var(--t-base)/1.55 var(--sans);color:var(--ink-2)}
.gl-facts{font:600 var(--t-xs)/1.7 var(--sans) !important;color:var(--ink-3) !important;
  display:flex;gap:var(--s-1) var(--s-3);flex-wrap:wrap}
.gl-facts span{white-space:nowrap}
.gl-facts span+span::before{content:"";display:inline-block;width:3px;height:3px;
  border-radius:50%;background:var(--rule-2);vertical-align:middle;margin-right:var(--s-3)}
.gl-actions{display:flex;gap:var(--s-3);flex-wrap:wrap;margin-top:var(--s-3);align-items:center}
.rank{font:800 var(--t-sm) var(--sans);font-variant-numeric:tabular-nums;color:var(--ink-3);
  min-width:34px;padding-top:6px}

/* my list, grouped so a verb with twenty forms is one entry */
.grouped>li{margin:0}
.grp{position:relative;background:var(--raise);border:2px solid var(--rule);
  border-radius:var(--r-lg);padding:var(--s-4) var(--s-5);
  transition:opacity .18s ease,transform .18s ease,border-color .12s ease}
.grp:hover{border-color:var(--primary)}
/* The row opens the word. The lemma and its facts are text rather than
   controls, so clicks on them fall through to the hit area; the buttons keep
   their own jobs. */
.grp>.card-hit{position:absolute;inset:0;z-index:0;pointer-events:auto;
  border-radius:inherit;background:none;border:0;cursor:pointer;
  font:inherit;color:transparent;padding:0}
.grp>.card-hit:focus-visible{outline:3px solid var(--primary);outline-offset:2px}
.grp>*:not(.card-hit){position:relative;z-index:1}
.grp-head .gl-head,.grp-head .grp-meta{pointer-events:none}
.grp.is-going{opacity:0;transform:translateY(-6px)}
.grp-head{display:flex;align-items:center;gap:var(--s-4);flex-wrap:wrap;width:100%}
.grp-head .gl-head{min-width:0;flex:0 1 auto}
.grp-meta{font:600 var(--t-xs) var(--sans);color:var(--ink-3);display:flex;gap:var(--s-3);flex-wrap:wrap}
.grp-meta .due{color:var(--accent);font-weight:800}
.grp-toggle{font:700 var(--t-xs) var(--sans);color:var(--ink-2);background:var(--surface);
  border:0;border-radius:999px;padding:9px 15px;cursor:pointer;margin-left:auto;min-height:38px}
.grp-toggle:hover{background:var(--surface-2);color:var(--ink)}
.grp-cards{list-style:none;margin:var(--s-4) 0 0;padding:0 0 0 var(--s-5);
  border-left:3px solid var(--rule);display:grid;gap:var(--s-2)}
.grp-cards li{display:flex;gap:var(--s-4);align-items:center;flex-wrap:wrap;
  padding:var(--s-3) 0;border-top:1px solid var(--rule);
  transition:opacity .18s ease,transform .18s ease}
.grp-cards li:first-child{border-top:0;padding-top:0}
.grp-cards li.is-going{opacity:0;transform:translateX(10px)}
.card-prompt{font:700 var(--t-base) var(--sans);color:var(--ink-2);min-width:180px;flex:0 1 auto}
.card-answer{font:400 var(--t-md) var(--serif);color:var(--ink);flex:1 1 160px}
.card-side{font:600 var(--t-xs) var(--sans);color:var(--ink-3);white-space:nowrap}
.card-side .due{color:var(--accent);font-weight:800}

/* how much of the list is done, said as a bar rather than as a sentence */
.streak{display:flex;gap:var(--s-5);align-items:center;flex-wrap:wrap;
  background:var(--surface);border-radius:var(--r-lg);padding:var(--s-4) var(--s-5);
  margin:0 0 var(--s-5)}
.streak-stat{display:flex;flex-direction:column;gap:2px}
.streak-stat b{font:800 var(--t-xl)/1 var(--sans);font-variant-numeric:tabular-nums;color:var(--ink)}
.streak-stat span{font:700 var(--t-2xs) var(--sans);letter-spacing:.07em;
  text-transform:uppercase;color:var(--ink-3)}
.streak-stat.due b{color:var(--accent)}
.bar{flex:1 1 180px;height:14px;border-radius:999px;background:var(--surface-2);overflow:hidden}
.bar i{display:block;height:100%;border-radius:999px;
  background:linear-gradient(90deg,var(--primary),var(--primary-hi));
  transition:width .4s ease}

/* ---------- reviewing ----------
   A card was a heading, a line of text and four links in a row, which is the
   shape of a paragraph rather than the shape of a thing you answer. This is a
   card: one question at a time, a Show that is the only thing to press, then
   four grades that say what each one costs you. What the last grade did stays
   on screen while you answer the next one, because a review that never tells
   you what it did with your answer is a form, not practice. */
.review{background:var(--raise);border:2px solid var(--rule);border-radius:var(--r-xl);
  padding:var(--s-5) var(--s-6) var(--s-6);box-shadow:var(--shadow-sm);margin:0 0 var(--s-6)}
.review-top{display:flex;align-items:center;gap:var(--s-4);flex-wrap:wrap;margin:0 0 var(--s-5)}
.review-top h2{margin:0}
.review-top .bar{flex:1 1 120px;height:10px}
.review-count{font:800 var(--t-xs)/1 var(--sans);font-variant-numeric:tabular-nums;
  letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3);white-space:nowrap}

/* what the previous answer did, kept in view while the next one is asked */
.review-last{display:flex;align-items:center;gap:var(--s-3);flex-wrap:wrap;
  font:600 var(--t-xs)/1.5 var(--sans);color:var(--ink-3);
  background:var(--surface);border-radius:999px;padding:8px var(--s-4);margin:0 0 var(--s-4)}
.review-last b{color:var(--ink);font-weight:800}
.review-last .rl-grade{color:var(--primary-hi);font-weight:800}
.review-last .rl-grade.is-again{color:var(--accent)}

.review-card{background:var(--surface);border-radius:var(--r-lg);
  padding:var(--s-6) var(--s-5);margin:0 0 var(--s-5);min-height:210px;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:var(--s-4);text-align:center}
.review-kind{font:800 var(--t-2xs)/1 var(--sans);letter-spacing:.09em;text-transform:uppercase;
  color:var(--primary-hi);background:var(--primary-wash);border-radius:999px;padding:6px 12px}
.review-front{font:400 clamp(28px,4vw,40px)/1.32 var(--serif);color:var(--ink);margin:0;
  max-width:20ch;text-wrap:balance}
/* A saved sentence is the whole sentence, and a form card is a phrase. Neither
   is a headword, so neither is set like one. */
.review-front.is-long{font-size:clamp(19px,2.2vw,26px);line-height:1.65;max-width:36ch}
.review-back{width:100%;border-top:1px solid var(--rule-2);padding-top:var(--s-5);
  display:flex;flex-direction:column;align-items:center;gap:var(--s-2);
  animation:review-in .18s ease-out}
@keyframes review-in{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
.review-answer{font:700 var(--t-xl)/1.35 var(--sans);letter-spacing:-.012em;
  color:var(--primary-hi);margin:0;max-width:34ch}
.review-back .gl-facts{justify-content:center;margin:0}

.review-ask{font:700 var(--t-xs)/1.4 var(--sans);color:var(--ink-3);letter-spacing:.06em;
  text-transform:uppercase;margin:0 0 var(--s-3);text-align:center}
.grades{display:grid;gap:var(--s-2);grid-template-columns:repeat(4,minmax(0,1fr))}
.grade{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
  font:800 var(--t-sm)/1.2 var(--sans);color:var(--ink-2);background:var(--surface);
  border:2px solid transparent;border-radius:var(--r);padding:12px 8px;min-height:62px;
  cursor:pointer;transition:color .12s ease,background-color .12s ease,border-color .12s ease}
.grade span{font:700 var(--t-2xs)/1 var(--sans);color:var(--ink-3);letter-spacing:.04em}
.grade:hover{background:var(--surface-2);color:var(--ink)}
.grade-again:hover{border-color:var(--accent);color:var(--accent);background:var(--accent-wash)}
.grade-again:hover span{color:var(--accent)}
.grade-good:hover,.grade-easy:hover{border-color:var(--primary);color:var(--primary-hi);
  background:var(--primary-wash)}
.grade-good:hover span,.grade-easy:hover span{color:var(--primary-hi)}
.grade:disabled{opacity:.5;cursor:default}

/* the end of a session, said as what you did rather than as one full stop */
.review-done{text-align:center;padding:var(--s-4) 0 0}
.review-done .review-front{margin:0 auto var(--s-3)}
.review-tally{display:flex;gap:var(--s-2);justify-content:center;flex-wrap:wrap;
  margin:0 0 var(--s-5)}
.review-tally span{font:800 var(--t-xs)/1 var(--sans);letter-spacing:.04em;
  background:var(--surface);color:var(--ink-2);border-radius:999px;padding:9px 14px}
.review-tally span b{color:var(--ink);font-variant-numeric:tabular-nums}
.review-tally span.is-again{background:var(--accent-wash);color:var(--accent)}
.review-tally span.is-good{background:var(--primary-wash);color:var(--primary-hi)}

kbd{font:700 var(--t-2xs)/1 var(--sans);color:var(--ink-3);background:var(--surface-2);
  border-radius:5px;padding:4px 6px;letter-spacing:.03em}
.btn kbd{background:rgba(255,255,255,.22);color:var(--primary-ink)}
@media (max-width:560px){
  .grades{grid-template-columns:1fr 1fr}
  .review{padding:var(--s-4) var(--s-4) var(--s-5)}
  .review-card{padding:var(--s-5) var(--s-3);min-height:170px}
}

/* ---------- tables ---------- */
.scroll{overflow-x:auto;max-width:100%;margin:0 0 var(--s-6);
  border:2px solid var(--rule);border-radius:var(--r-lg)}
table{border-collapse:collapse;width:100%;font:400 var(--t-base) var(--sans);margin:0}
caption{text-align:left;font:800 var(--t-sm) var(--sans);padding:var(--s-4) var(--s-5) var(--s-3);
  color:var(--ink);letter-spacing:.01em;background:var(--surface);
  border-bottom:1px solid var(--rule)}
th,td{text-align:left;padding:11px var(--s-4);border-bottom:1px solid var(--rule);
  vertical-align:baseline}
tbody tr:last-child th,tbody tr:last-child td{border-bottom:0}
thead th{font:800 var(--t-2xs) var(--sans);color:var(--ink-3);text-transform:uppercase;
  letter-spacing:.07em;background:var(--surface)}
tbody th{font:600 var(--t-sm) var(--sans);color:var(--ink-3);text-transform:none;white-space:nowrap}
td{font-variant-numeric:tabular-nums;color:var(--ink)}
tbody tr:hover{background:var(--surface)}
.judge{white-space:nowrap}
.judge button{font:700 var(--t-xs) var(--sans);background:none;border:2px solid var(--rule-2);
  border-radius:999px;cursor:pointer;padding:6px 13px;margin-right:var(--s-2);color:var(--ink-3);
  min-height:34px;transition:color .12s ease,border-color .12s ease,background-color .12s ease}
.judge .tick:hover{color:var(--good);border-color:var(--good);background:var(--primary-wash)}
.judge .cross:hover{color:var(--accent);border-color:var(--accent);background:var(--accent-wash)}
.judge.said-right .tick{color:var(--good);border-color:var(--good);background:var(--primary-wash)}
.judge.said-wrong .cross{color:var(--accent);border-color:var(--accent);background:var(--accent-wash)}
.tallies{font:600 var(--t-xs) var(--sans);color:var(--ink-3)}
.judge.is-busy button{opacity:.5;pointer-events:none}
/* A form table's judge column is one line wide until it is asked for a note,
   and a note field squeezed into that column is not a field anybody writes in. */
.judge.is-noting{white-space:normal;min-width:270px}

/* Saying a rule does not belong on this sentence.
   The rules are the part a model gets wrong in a way a learner cannot see: a
   plausible rule name over a sentence that does not use it reads exactly like
   a correct one. Every other German fact here already had two controls and
   this, the claim hardest to check, had none.

   The note is a field on the card rather than a browser prompt. The prompt was
   what the form tables used, and it throws away what you typed if you brush
   the wrong key, in the one place the site says the writing is worth more than
   the count. */
.rc-judge{display:flex;gap:var(--s-2);align-items:center;flex-wrap:wrap;white-space:normal;
  margin:var(--s-4) 0 0;padding-top:var(--s-4);border-top:1px solid var(--rule)}
.rc-judge .label.inline{color:var(--ink-3);margin-right:var(--s-2)}
.rc-judge .tallies{margin-left:var(--s-2)}
.judge-note{flex:1 1 100%;margin:var(--s-3) 0 0}
.judge-note textarea{min-height:80px;font:400 var(--t-sm)/1.55 var(--sans);
  border-radius:var(--r);margin:0 0 var(--s-3)}
.judge-note .row{margin:0;gap:var(--s-3);align-items:center}
.judge-said{font:700 var(--t-xs)/1.5 var(--sans);color:var(--primary-hi);
  background:var(--primary-wash);border-radius:999px;padding:7px 13px;margin:0}
.judge-said.is-wrong{color:var(--accent);background:var(--accent-wash)}

/* ---------- quota, health, admin ---------- */
.health{margin:0;padding:0;display:grid;gap:var(--s-3);
  grid-template-columns:repeat(auto-fit,minmax(190px,1fr))}
.health-row{display:flex;flex-direction:column;gap:var(--s-2);padding:var(--s-4) var(--s-5);
  background:var(--surface);border-radius:var(--r-lg);margin:0}
.health dt{color:var(--ink-3);font:700 var(--t-xs) var(--sans);letter-spacing:.06em;
  text-transform:uppercase;margin:0}
.health dd{margin:0;font:800 var(--t-2xl)/1 var(--sans);font-variant-numeric:tabular-nums;
  letter-spacing:-.02em;color:var(--ink)}
.quota{font:400 var(--t-sm)/1.6 var(--sans);color:var(--ink-2);background:var(--surface);
  border-radius:var(--r-lg);padding:var(--s-4) var(--s-5);margin:var(--s-5) 0 0;max-width:68ch}
.quota.spent{background:var(--accent-wash);color:var(--ink)}
.admin-row{display:flex;gap:var(--s-5);align-items:baseline;flex-wrap:wrap;width:100%}
.admin-key{font:700 var(--t-base) var(--sans);min-width:200px;color:var(--ink)}
.admin-note{font:400 var(--t-base)/1.55 var(--sans);margin:var(--s-1) 0 var(--s-2)}
.admin-meta{font:600 var(--t-xs) var(--sans);color:var(--ink-3);display:flex;gap:var(--s-3);flex-wrap:wrap}
.admin-meta span+span::before{content:"";display:inline-block;width:3px;height:3px;
  border-radius:50%;background:var(--rule-2);vertical-align:middle;margin-right:var(--s-3)}
.pending{border-left:3px solid var(--accent);padding-left:var(--s-4)}

/* ---------- panels ---------- */
.panel-grid{display:grid;gap:var(--s-5);grid-template-columns:repeat(auto-fit,minmax(320px,1fr));
  align-items:start;max-width:900px}
.panel{background:var(--raise);border:2px solid var(--rule);border-radius:var(--r-xl);
  padding:var(--s-5);box-shadow:var(--shadow-sm)}
.panel h2{font-size:var(--t-md);margin-bottom:var(--s-3)}
.panel .row{margin-bottom:0}

/* ---------- how it works ---------- */
.steps{list-style:none;margin:0;padding:0;display:grid;gap:var(--s-4);
  grid-template-columns:repeat(auto-fit,minmax(205px,1fr))}
/* The number was an inline-flex badge, so it sat on a text baseline and the
   line box around it left a band of nothing between the badge and the title,
   different in each card. A flex column has no line boxes, so the only space
   between the two is the margin that asks for it.

   The titles are held to two lines for the same reason the cards are a grid:
   step one wraps and the other three do not, and without the hold the four
   paragraphs each started at a different height. On a phone the cards stack
   and there is nothing left to line up with, so the hold comes off. */
.step{display:flex;flex-direction:column;
  background:var(--raise);border:2px solid var(--rule);border-radius:var(--r-lg);
  padding:var(--s-5);margin:0}
.step-n{align-self:flex-start;display:flex;align-items:center;justify-content:center;
  width:34px;height:34px;flex:0 0 auto;
  border-radius:11px;background:var(--primary);color:var(--primary-ink);
  font:800 var(--t-sm)/1 var(--sans);margin:0 0 var(--s-4)}
.step h3{margin:0 0 var(--s-3);min-height:2.7em}
.step p{font:400 var(--t-sm)/1.6 var(--sans);color:var(--ink-2);margin:0}
@media (max-width:720px){.step h3{min-height:0}}
.shot{display:block;width:100%;border:2px solid var(--rule);border-radius:var(--r-lg);
  background:var(--raise);margin:0 0 var(--s-3);overflow:hidden}
/* The demo is the real reading in miniature: same token markup, same panel,
   same stylesheet, so it cannot drift from the thing it is showing. */
.demo{display:grid;gap:var(--s-5);grid-template-columns:minmax(0,1fr) minmax(230px,290px);
  align-items:start;border:2px solid var(--rule);border-radius:var(--r-lg);
  background:var(--raise);padding:var(--s-5);margin:0 0 var(--s-3)}
/* The demo sentence is what this page is about, so it is set at the size the
   real reading uses rather than a step under it. The key naming the colours is
   a legend and has to read as one: it sat hard against the last line, close
   enough that the underlines under the words and the key's own ran together. */
.demo .sentence{font:400 var(--t-xl)/1.9 var(--serif);margin:0 0 var(--s-6);max-width:none}
.demo .key{margin:0}
.demo-panel .reading{background:var(--surface);border:0;border-radius:var(--r-lg);
  padding:var(--s-4) var(--s-5);box-shadow:none}
.demo-panel .headword{font-size:var(--t-lg)}
.demo-panel .gloss{padding-bottom:var(--s-3);margin-bottom:var(--s-3)}
.demo-panel .feats{margin:0}
@media (max-width:820px){.demo{grid-template-columns:minmax(0,1fr)}}

/* The rule demo, for the same reason the reading demo is real markup: it was a
   hand-drawn SVG at width 100%, so every word in it scaled with the column and
   on a wide screen the card was half again the size of the real one it was
   showing. Real classes and real type sizes cannot do that, and they cannot
   drift from the rule cards on a reading either. Same box and same edges as
   the demo above it, so the two figures on this page line up. */
.demo-rule{border:2px solid var(--rule);border-radius:var(--r-lg);
  background:var(--raise);padding:var(--s-5);margin:0 0 var(--s-3)}
.demo-rule .rule-card{margin:0 0 var(--s-5);cursor:default}
.demo-rule .rule-card:hover{border-color:var(--rule);transform:none;box-shadow:none}
.demo-rule .ex-de{font-size:var(--t-lg);margin:0 0 var(--s-3)}
.demo-rule .ex-why{margin:0}
.shot-cap{font:600 var(--t-xs)/1.5 var(--sans);color:var(--ink-3);margin:0 0 var(--s-7);max-width:70ch}
.shot-lead{font:400 var(--t-base)/1.65 var(--sans);color:var(--ink-2);margin:0 0 var(--s-4);max-width:68ch}
.faq+*,.steps+*{margin-top:var(--s-6)}
/* Scoped to the prose sections, which is where it was always meant to apply.
   Unscoped it was `#view-about h3`, an id beating any class, so it also put 38
   pixels above the title inside each of the four step cards. That was the band
   of nothing between the number and the title: not the badge's doing, a
   section rule reaching into a card it was never about. */
#view-about .block h3{margin-top:var(--s-6)}
#view-about .block>h3:first-of-type{margin-top:0}
.faq{margin:0;padding:0}
.faq details{border:2px solid var(--rule);border-radius:var(--r-lg);background:var(--raise);
  margin:0 0 var(--s-3);overflow:hidden}
.faq summary{cursor:pointer;padding:var(--s-4) var(--s-5);font:800 var(--t-base) var(--sans);
  color:var(--ink);list-style:none;display:flex;justify-content:space-between;gap:var(--s-4);
  align-items:center;min-height:56px}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:"";width:18px;height:18px;flex:0 0 auto;background:currentColor;
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 8l5 5 5-5'/%3E%3C/svg%3E") center/contain no-repeat;
  mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 8l5 5 5-5'/%3E%3C/svg%3E") center/contain no-repeat;
  transition:transform .15s ease;color:var(--ink-3)}
.faq details[open] summary::after{transform:rotate(180deg)}
.faq summary:hover{background:var(--surface)}
.faq details[open] summary{border-bottom:1px solid var(--rule)}
.faq .prose{padding:var(--s-5);max-width:70ch}

/* ---------- toast ---------- */
.toast{position:fixed;left:50%;bottom:26px;transform:translateX(-50%) translateY(8px);
  z-index:80;background:var(--ink);color:var(--paper);border-radius:999px;
  padding:13px 24px;font:700 var(--t-sm) var(--sans);box-shadow:var(--shadow);
  max-width:min(92vw,460px);text-align:center;opacity:0;
  transition:opacity .18s ease,transform .18s ease;pointer-events:none}
.toast.is-up{opacity:1;transform:translateX(-50%) translateY(0)}
.toast.err{background:var(--accent);color:var(--accent-ink)}

/* ---------- footer ---------- */
.footer{border-top:1px solid var(--rule);padding:var(--s-6) 0 var(--s-7);margin-top:var(--s-9)}
.footer p{font:400 var(--t-xs)/1.7 var(--sans);color:var(--ink-3);margin:0;max-width:72ch}

@media (prefers-reduced-motion:reduce){*{transition:none !important;animation:none !important}}

/* ---------- narrower ---------- */
@media (max-width:1020px){
  .result{grid-template-columns:minmax(0,1fr);
    grid-template-areas:"sent" "rail" "body"}
  .rail{position:static;margin-top:var(--s-5)}
  .rail .reading{box-shadow:none}
  .result-body{padding-top:var(--s-6)}
  .hero{grid-template-columns:minmax(0,1fr);gap:var(--s-6)}
  .hero-copy h1{max-width:20ch}
}
@media (max-width:720px){
  :root{--t-3xl:34px;--t-2xl:28px;--t-xl:23px;--t-lg:20px}
  .col{padding-left:18px;padding-right:18px}
  main{padding-top:var(--s-5)}
  .masthead{position:static}
  .masthead-in{min-height:0;padding-top:var(--s-3);padding-bottom:var(--s-2);gap:var(--s-3)}
  .nav{flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;width:100%;
    margin:0 -4px;padding:0 4px 2px}
  .nav::-webkit-scrollbar{display:none}
  .standfirst{max-width:none}
  .composer{padding:var(--s-4);border-radius:var(--r-lg)}
  .composer .btn{width:100%}
  .composer-row{align-items:stretch}
  .composer-row .inline-field,.composer-row select{width:100%;max-width:none}
  .sentence{max-width:none}
  .gl-head{min-width:0;flex:1 1 100%}
  .word-card{gap:var(--s-3);padding:var(--s-4)}
  .toolbar{gap:var(--s-4);width:100%;padding:var(--s-4)}
  .toolbar .inline-field,.toolbar select{width:100%;max-width:none}
  .toolbar .btn{width:100%}
  .health{grid-template-columns:1fr 1fr}
  .grp-cards{padding-left:var(--s-4)}
  .card-prompt{min-width:0;flex:1 1 100%}
  .rule-hero{padding:var(--s-5) var(--s-4)}
  .toast{left:16px;right:16px;bottom:16px;transform:translateY(8px);max-width:none}
  .toast.is-up{transform:translateY(0)}
}

.verbatim{font:400 var(--t-md)/1.6 var(--serif);color:var(--ink-2);margin:0 0 var(--s-4);
  padding-left:var(--s-4);border-left:3px solid var(--rule-2);max-width:62ch}

/* ---------------------------------------------------------------
   Mobile.
   The reading is a two pane layout on a wide screen and cannot be one on a
   phone, so the word you pick arrives as a sheet from the bottom instead. The
   sentence stays where it was and in view, the detail is a thumb's reach away,
   and closing it puts you back exactly where you were.
   --------------------------------------------------------------- */
@media (max-width:720px){
  .nav{-webkit-mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent);
       mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent)}
  .nav:last-child{padding-right:20px}

  .chip{padding:12px 17px}
  .judge button{padding:8px 14px;margin-bottom:4px}
  .grp-toggle{padding:10px 15px}
  .navlink{padding:11px 13px}

  .sentence{line-height:2.1}
  .tok{padding:2px .06em 3px}

  .rule-card{flex-wrap:wrap}
  .rule-side{flex-direction:row;width:100%}

  .rail{margin-top:0}
  .rail-idle{display:none}

  #token-detail:not([hidden]){
    position:fixed;left:0;right:0;bottom:0;z-index:70;
    margin:0;border:2px solid var(--rule);border-bottom:0;
    border-radius:var(--r-xl) var(--r-xl) 0 0;
    background:var(--raise);
    box-shadow:0 -10px 34px -14px rgba(0,0,0,.5);
    max-height:62vh;overflow-y:auto;-webkit-overflow-scrolling:touch;
    padding:var(--s-5) var(--s-5) calc(var(--s-5) + env(safe-area-inset-bottom,0px));
    animation:sheet-up .2s ease-out}
  .sheet-close{display:block;position:absolute;top:12px;right:12px;
    font:700 var(--t-xs) var(--sans);color:var(--ink-2);background:var(--surface);
    border:0;border-radius:999px;padding:10px 16px;cursor:pointer;min-height:40px}
  .sheet-close:hover{background:var(--surface-2);color:var(--ink)}
  .toast{bottom:auto;top:16px;transform:translateY(-8px)}
  .toast.is-up{transform:translateY(0)}
}
@keyframes sheet-up{from{transform:translateY(16px);opacity:0}to{transform:translateY(0);opacity:1}}

.grp-actions{margin-left:auto;display:flex;gap:var(--s-2);align-items:center;flex-shrink:0}
.grp-head .grp-toggle{margin-left:0}
/* Reveal-on-hover is for pointers only. Anything without hover keeps the
   control visible, which is every touch screen rather than every narrow one:
   the old rule keyed on width, so a touch laptop had no way to remove a card. */
.card-drop{margin-left:auto}
@media (hover:hover) and (pointer:fine){
  .card-drop{opacity:0;transition:opacity .12s ease}
  .grp-cards li:hover .card-drop,.card-drop:focus-visible,.card-drop:focus{opacity:1}
}
@media (max-width:720px){
  .grp-actions{margin-left:0;width:100%}
}

/* ---------- signing in ---------- */
.segmented{display:flex;gap:3px;background:var(--surface);border-radius:var(--r-lg);
  padding:4px;margin:0 0 var(--s-4)}
.seg{flex:1 1 0;font:700 var(--t-sm)/1 var(--sans);color:var(--ink-3);background:none;
  border:0;border-radius:calc(var(--r-lg) - 4px);padding:12px;cursor:pointer;min-height:44px;
  transition:background-color .12s ease,color .12s ease}
.seg:hover{color:var(--ink)}
.seg.is-on{background:var(--raise);color:var(--primary-hi);box-shadow:var(--shadow-sm)}
.pw{position:relative;display:block}
.pw input{padding-right:80px}
.pw-eye{position:absolute;top:12px;right:9px;font:700 var(--t-xs) var(--sans);
  color:var(--ink-3);background:var(--surface);border:0;border-radius:var(--r-sm);
  padding:9px 13px;cursor:pointer;min-height:36px}
.pw-eye:hover{color:var(--ink);background:var(--surface-2)}
.btn-wide{width:100%}
#auth-blurb{margin-bottom:var(--s-4)}
#pw-hint{margin:calc(var(--s-4) * -1 + 4px) 0 var(--s-4)}

.pop-end{display:block !important;padding:var(--s-5) 0 0;text-align:center}
.pop-end .hint{margin:0 0 var(--s-3)}
.pop-end .btn{min-width:200px}

/* ---------- the analysis's verdict on the sentence itself ----------
   Two things a reader has to be told before anything else on the page makes
   sense: that what they posted is not German, and that the German they are
   reading has a mistake in it. Neither is a fault in the backend, so neither
   uses the operator's notice above; both are addressed to whoever is reading.

   Set wider and heavier than .thin because this one is the answer rather than
   a footnote to it. On a page that is not German it is the only thing there. */
.verdict{border-radius:var(--r-lg);padding:var(--s-5);margin:0 0 var(--s-5);max-width:64ch;
  border:2px solid transparent}
.verdict p{font:400 var(--t-sm)/1.6 var(--sans);color:var(--ink-2);margin:0 0 var(--s-3)}
.verdict p:last-child{margin:0}
.verdict-head{font:800 var(--t-lg)/1.3 var(--sans)!important;color:var(--ink)!important;
  margin:0 0 var(--s-3)!important}
.verdict-note{color:var(--ink-3)!important;font-size:var(--t-xs)!important}

/* Not German: nothing was read and nothing is coming, so this is stated in the
   accent rather than the warning colour. A warning implies something to fix
   here; there is nothing to fix, only somewhere else to go. */
.verdict.is-foreign{background:var(--accent-wash);
  border-color:color-mix(in srgb,var(--accent) 30%,transparent)}

/* Wrong grammar: the reading below is real and worth having, and the mistake
   is a detour rather than a dead end, so this is the warning colour. */
.verdict.is-wrong{background:var(--warn-wash);
  border-color:color-mix(in srgb,var(--warn) 32%,transparent)}
.verdict-fix{display:flex;flex-direction:column;gap:4px;
  background:var(--raise);border-radius:var(--r);padding:var(--s-3) var(--s-4)}
.verdict-fix-label{font:700 var(--t-2xs) var(--sans);letter-spacing:.07em;
  text-transform:uppercase;color:var(--ink-3)}
.verdict-fix b{font:400 var(--t-base)/1.5 var(--serif);color:var(--ink)}

/* ---------- what you know, rather than what you owe ----------
   The band over My words used to measure the review queue: how much of it was
   not due yet, as a percentage. That answers "how much work is waiting", which
   is a question about today. This answers "where am I with German", which is
   the question somebody actually opens the page for, and the numbers only ever
   move one way.

   One bar, split by state, worst to best left to right, with the figures
   written out underneath. The colours carry no meaning the words do not also
   carry, so a reader who cannot separate them loses nothing. */
.streak.is-know{flex-direction:column;align-items:stretch;gap:var(--s-4)}
.know-top{display:flex;gap:var(--s-5);align-items:center;flex-wrap:wrap}
.know-bar{display:flex;gap:2px;background:transparent;overflow:visible}
/* Each segment names its own colour, and each selector has to outrank the
   plain ".bar i" above, which paints every bar's fill the primary gradient.
   Matched on one class the segments lost that fight and the whole bar came
   out one colour, which is a bar saying nothing at all. */
.know-bar i{display:block;height:100%;border-radius:999px;transition:width .4s ease}
.know-bar i.k-known{background:linear-gradient(90deg,var(--primary),var(--primary-hi))}
.know-bar i.k-study{background:color-mix(in srgb,var(--primary) 55%,var(--surface-2))}
.know-bar i.k-barely{background:var(--warn)}
.know-bar i.k-not{background:var(--accent)}
.know-bar i.k-none{background:var(--surface-2)}
.know-stat i.k-known{background:var(--primary)}
.know-stat i.k-study{background:color-mix(in srgb,var(--primary) 55%,var(--surface-2))}
.know-stat i.k-barely{background:var(--warn)}
.know-stat i.k-not{background:var(--accent)}
.know-stat i.k-none{background:var(--surface-2)}
.know-legend{display:flex;gap:var(--s-4);flex-wrap:wrap}
.know-stat{display:flex;align-items:center;gap:6px;
  font:600 var(--t-xs)/1 var(--sans);color:var(--ink-3);white-space:nowrap}
.know-stat b{font:800 var(--t-sm)/1 var(--sans);font-variant-numeric:tabular-nums;color:var(--ink)}
.know-stat i{width:10px;height:10px;border-radius:3px;flex:none}

/* Going through the lexicon reuses the review card, so it needs no shape of
   its own. The one thing it adds is a way out of a session that has no end:
   a review runs out of cards and this does not. */
.review-top .linkish{margin-left:auto}

/* What the run is narrowed to, where it is narrowed. It reads as a fact about
   this session rather than as a control, because the control is the lexicon's
   own filter and this is only reporting it. */
.review-narrow{font:700 var(--t-2xs) var(--sans);letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-3);background:var(--surface-2);border-radius:999px;
  padding:3px var(--s-3);white-space:nowrap}
