/* ==========================================================================
   DeutschTools design system

   Visual idea: ink-dark indigo with a violet-to-coral glow, glass only where it earns
   its GPU cost (the two bars that float over scrolling content), solid surfaces
   everywhere else. Everything is CSS - no images, no icon font, no framework - so the
   whole look costs a few kilobytes and works offline from the first paint.

   Themes: light is the default. Dark applies from the system preference when the learner
   has not chosen (data-theme=""), or from an explicit data-theme="dark". The token block
   is written twice because a media query cannot join a selector list; keep the two in step.

   Direction: layout uses logical properties (inline/block, start/end) throughout, so
   setting dir="rtl" on <html> mirrors the entire app with no per-component overrides.
   ========================================================================== */

/* ------------------------------------------------------------------- fonts */
/* One family name, two files split by unicode-range. The browser downloads Vazirmatn
   only once Persian text is actually on screen, and mixed German/Persian lines pick the
   right glyphs per character without any markup. Both are variable fonts, so every
   weight comes from one file each. */

@font-face {
  font-family: "App Sans";
  src: url("../fonts/inter-latin-wght.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  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: "App Sans";
  src: url("../fonts/vazirmatn-arabic-wght.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, U+0897-08E1,
                 U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74,
                 U+FE76-FEFC, U+102E0-102FB, U+10E60-10E7E, U+10EC2-10EC4, U+10EFC-10EFF,
                 U+1EE00-1EEFF;
}

/* ------------------------------------------------------------------ tokens */

:root {
  color-scheme: light;

  --bg: #f5f4fb;
  --bg-glow-1: rgb(108 92 255 / 16%);
  --bg-glow-2: rgb(255 107 129 / 11%);
  --bg-glow-3: rgb(56 189 248 / 9%);

  --surface: #ffffff;
  --surface-2: #f1f0f8;
  --surface-3: #e7e5f2;
  --glass: rgb(255 255 255 / 72%);
  --line: rgb(20 19 43 / 8%);
  --line-strong: rgb(20 19 43 / 15%);

  --text: #15142b;
  --text-2: #56557a;
  --text-3: #8e8dab;

  --accent: #5b4bff;
  --accent-2: #9b5cff;
  --accent-3: #ff6b81;
  --accent-soft: rgb(91 75 255 / 10%);
  --accent-text: #ffffff;
  --grad: linear-gradient(135deg, #5b4bff 0%, #9b5cff 55%, #ff6b81 120%);
  --grad-soft: linear-gradient(135deg, rgb(91 75 255 / 12%), rgb(255 107 129 / 10%));

  --good: #0f9f6e;
  --good-soft: rgb(16 185 129 / 12%);
  --warn: #c07a06;
  --warn-soft: rgb(245 158 11 / 14%);
  --bad: #e0335a;
  --bad-soft: rgb(244 63 94 / 11%);
  --flame: #ff8a1f;

  --a1: #10b981;
  --a2: #0ea5e9;
  --b1: #f59e0b;
  --b2: #f43f5e;

  --radius-lg: 24px;
  --radius: 18px;
  --radius-sm: 12px;
  --radius-xs: 8px;

  --shadow-sm: 0 1px 2px rgb(21 20 43 / 5%);
  --shadow: 0 1px 2px rgb(21 20 43 / 4%), 0 8px 24px -6px rgb(21 20 43 / 10%);
  --shadow-lift: 0 2px 6px rgb(21 20 43 / 6%), 0 22px 48px -12px rgb(21 20 43 / 22%);
  --shadow-glow: 0 10px 30px -8px rgb(91 75 255 / 55%);

  --font: "App Sans", system-ui, -apple-system, "Segoe UI", Roboto, Tahoma, sans-serif;
  --font-de: var(--font);
  --font-fa: var(--font);
  --font-mono: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, monospace;

  --nav-h: 64px;
  --header-h: 56px;
  --gutter: 16px;

  --ease: cubic-bezier(.2, .8, .2, 1);
  --spring: cubic-bezier(.34, 1.56, .64, 1);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;

    --bg: #0b0a17;
    --bg-glow-1: rgb(108 92 255 / 26%);
    --bg-glow-2: rgb(255 107 129 / 14%);
    --bg-glow-3: rgb(56 189 248 / 10%);

    --surface: #151429;
    --surface-2: #1c1b34;
    --surface-3: #26253f;
    --glass: rgb(21 20 41 / 72%);
    --line: rgb(255 255 255 / 7%);
    --line-strong: rgb(255 255 255 / 13%);

    --text: #eeedf9;
    --text-2: #a9a8c6;
    --text-3: #72718f;

    --accent: #8b7dff;
    --accent-2: #b48bff;
    --accent-3: #ff8599;
    --accent-soft: rgb(139 125 255 / 15%);
    --accent-text: #ffffff;
    --grad: linear-gradient(135deg, #6a5cff 0%, #a26bff 55%, #ff7a8f 120%);
    --grad-soft: linear-gradient(135deg, rgb(139 125 255 / 18%), rgb(255 133 153 / 12%));

    --good: #34d399;
    --good-soft: rgb(52 211 153 / 14%);
    --warn: #fbbf24;
    --warn-soft: rgb(251 191 36 / 14%);
    --bad: #fb7185;
    --bad-soft: rgb(251 113 133 / 14%);

    --shadow-sm: 0 1px 2px rgb(0 0 0 / 30%);
    --shadow: 0 1px 2px rgb(0 0 0 / 30%), 0 10px 28px -8px rgb(0 0 0 / 55%);
    --shadow-lift: 0 2px 8px rgb(0 0 0 / 40%), 0 26px 56px -14px rgb(0 0 0 / 70%);
    --shadow-glow: 0 12px 34px -8px rgb(122 108 255 / 60%);
  }
}

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

  --bg: #0b0a17;
  --bg-glow-1: rgb(108 92 255 / 26%);
  --bg-glow-2: rgb(255 107 129 / 14%);
  --bg-glow-3: rgb(56 189 248 / 10%);

  --surface: #151429;
  --surface-2: #1c1b34;
  --surface-3: #26253f;
  --glass: rgb(21 20 41 / 72%);
  --line: rgb(255 255 255 / 7%);
  --line-strong: rgb(255 255 255 / 13%);

  --text: #eeedf9;
  --text-2: #a9a8c6;
  --text-3: #72718f;

  --accent: #8b7dff;
  --accent-2: #b48bff;
  --accent-3: #ff8599;
  --accent-soft: rgb(139 125 255 / 15%);
  --accent-text: #ffffff;
  --grad: linear-gradient(135deg, #6a5cff 0%, #a26bff 55%, #ff7a8f 120%);
  --grad-soft: linear-gradient(135deg, rgb(139 125 255 / 18%), rgb(255 133 153 / 12%));

  --good: #34d399;
  --good-soft: rgb(52 211 153 / 14%);
  --warn: #fbbf24;
  --warn-soft: rgb(251 191 36 / 14%);
  --bad: #fb7185;
  --bad-soft: rgb(251 113 133 / 14%);

  --shadow-sm: 0 1px 2px rgb(0 0 0 / 30%);
  --shadow: 0 1px 2px rgb(0 0 0 / 30%), 0 10px 28px -8px rgb(0 0 0 / 55%);
  --shadow-lift: 0 2px 8px rgb(0 0 0 / 40%), 0 26px 56px -14px rgb(0 0 0 / 70%);
  --shadow-glow: 0 12px 34px -8px rgb(122 108 255 / 60%);
}

/* -------------------------------------------------------------------- base */

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

/* The document itself never scrolls: on iOS an installed app otherwise rubber-bands the
   whole screen - header, nav and all - in every direction, and overscroll-behavior on the
   root does not stop it there. Scrolling lives in .scroller instead. */
html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  overflow: hidden;
  overscroll-behavior: none;
  /* Panning only: no pinch zoom, no double-tap zoom, and no 300ms wait for one on every
     tap. Ancestors' touch-action intersects, so this holds for every element below. */
  touch-action: pan-x pan-y;
}

body { position: fixed; inset: 0; }

body {
  background-color: var(--bg);
  /* The glow is fixed so it does not repaint on scroll - three radial gradients, no
     image, no blur filter, so it is cheap even on an old phone. */
  background-image:
    radial-gradient(60rem 40rem at 0% -10%, var(--bg-glow-1), transparent 60%),
    radial-gradient(50rem 36rem at 110% 0%, var(--bg-glow-2), transparent 55%),
    radial-gradient(40rem 30rem at 50% 115%, var(--bg-glow-3), transparent 60%);
  background-attachment: fixed;
  color: var(--text);
  font-family: var(--font);
  font-size: 15.5px;
  line-height: 1.55;
  font-feature-settings: "cv11", "ss01";
  -webkit-font-smoothing: antialiased;
  -webkit-text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
  transition: background-color .35s var(--ease), color .35s var(--ease);
}

/* Persian and Arabic read better with more leading; the font itself is shared. */
:root[lang="fa"] body, :root[lang="ar"] body { line-height: 1.8; font-feature-settings: normal; }

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

/* iOS zooms the page into any field whose text is under 16px when it takes focus, and
   leaves it zoomed after - the body's 15.5px is just under. */
input, select, textarea { font-size: max(16px, 1em); }

/* Content is not selectable or copyable, and long-press opens no callout (Safari's
   preview/save/copy sheet). Form fields stay editable - a search box you cannot select
   in is broken. The copy/cut/context-menu events are blocked in index.html as well. */
body { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
input, textarea, [contenteditable] { -webkit-user-select: text; user-select: text; -webkit-touch-callout: default; }

/* An icon with no sizing rule of its own would otherwise fill its container. */
svg:not([width]) { width: 1.25em; height: 1.25em; flex: 0 0 auto; }
button { cursor: pointer; background: none; border: 0; padding: 0; }
a { color: var(--accent); text-decoration: none; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: var(--radius-xs);
}

::selection { background: var(--accent-soft); }

h1[tabindex="-1"]:focus { outline: none; }

/* Native controls pick up the brand colour instead of the browser default blue. */
input[type="range"], input[type="checkbox"] { accent-color: var(--accent); }
input[type="range"] { width: 100%; }

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

/* Script helpers. German stays left-to-right inside a right-to-left page - a German
   sentence mirrored is unreadable - and Persian keeps its own direction inside an
   English page. `unicode-bidi: isolate` stops punctuation from jumping to the wrong end. */
.de { direction: ltr; unicode-bidi: isolate; }
.fa, .ar { direction: rtl; unicode-bidi: isolate; line-height: 1.85; }
.ltr { direction: ltr; unicode-bidi: isolate; }

/* Directional glyphs (arrows) point the other way in a right-to-left layout. */
.flip-x { transform: scaleX(-1); }
.mono { font-family: var(--font-mono); direction: ltr; unicode-bidi: isolate; }

/* ------------------------------------------------------------------ layout */

/* Pinned to the viewport rather than sized with height: 100%. A percentage height needs
   every ancestor (#app, and whatever Blazor renders around the layout) to have one too;
   miss one and .scroller grows to fit its content, never overflows, and nothing scrolls. */
.app {
  position: fixed;
  inset: 0;
}

/* The one scrolling surface. The header floats over its top edge so content still slides
   under the glass, but being outside it, the header stays put when the list bounces. */
.scroller {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding-block-start: calc(var(--header-h) + env(safe-area-inset-top));
  padding-block-end: calc(var(--nav-h) + env(safe-area-inset-bottom) + 20px);
}

.topbar {
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  gap: 8px;
  height: calc(var(--header-h) + env(safe-area-inset-top));
  padding: env(safe-area-inset-top) var(--gutter) 0;
  background: var(--glass);
  backdrop-filter: saturate(180%) blur(18px);
  -webkit-backdrop-filter: saturate(180%) blur(18px);
  border-block-end: 1px solid var(--line);
}

.topbar h1 {
  flex: 1;
  margin: 0;
  font-size: 19px;
  font-weight: 750;
  letter-spacing: -0.02em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.topbar .brand-dot {
  width: 26px;
  height: 26px;
  flex: 0 0 auto;
  border-radius: 9px;
  background: var(--grad);
  box-shadow: var(--shadow-glow);
  display: grid;
  place-items: center;
  color: #fff;
  font-size: 13px;
  font-weight: 800;
}

.icon-btn {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 12px;
  color: var(--text-2);
  transition: background .2s var(--ease), color .2s var(--ease), transform .15s var(--ease);
}
.icon-btn:hover { background: var(--surface-2); color: var(--text); }
.icon-btn:active { transform: scale(.92); }
.icon-btn svg { width: 21px; height: 21px; }

/* Grows to fill a short page but never shrinks below its content - that overflow is
   what the scroller scrolls. */
main {
  flex: 1 0 auto;
  width: 100%;
  max-width: 1080px;
  margin: 0 auto;
  padding: 18px var(--gutter);
}

/* Floating pill nav. Detached from the screen edge so it reads as a control rather than
   as page chrome, which is what makes the whole app feel native. */
.navbar {
  position: fixed;
  z-index: 30;
  inset-inline: 12px;
  inset-block-end: calc(10px + env(safe-area-inset-bottom));
  max-width: 520px;
  margin-inline: auto;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  height: var(--nav-h);
  padding: 6px;
  border-radius: 22px;
  background: var(--glass);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  border: 1px solid var(--line-strong);
  box-shadow: var(--shadow-lift);
}

.navbar a {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  border-radius: 16px;
  font-size: 10.5px;
  font-weight: 600;
  color: var(--text-3);
  text-decoration: none;
  transition: color .25s var(--ease), background .25s var(--ease);
}

.navbar a svg { width: 22px; height: 22px; transition: transform .3s var(--spring); }
.navbar a:active svg { transform: scale(.86); }

.navbar a.active {
  color: var(--accent);
  background: var(--accent-soft);
}
.navbar a.active svg { transform: translateY(-1px); }

.navbar .badge {
  position: absolute;
  inset-block-start: -7px;
  inset-inline-end: -10px;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 9px;
  background: var(--accent-3);
  color: #fff;
  font-size: 10px;
  font-weight: 800;
  line-height: 18px;
  text-align: center;
  box-shadow: 0 0 0 2px var(--surface);
}

/* ---------------------------------------------------------------- entrance */
/* Pages rise in, children staggered. Cheap: opacity and transform only. */

@keyframes rise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

.rise > * { animation: rise .5s var(--ease) both; }
.rise > *:nth-child(2) { animation-delay: .05s; }
.rise > *:nth-child(3) { animation-delay: .1s; }
.rise > *:nth-child(4) { animation-delay: .15s; }
.rise > *:nth-child(5) { animation-delay: .2s; }
.rise > *:nth-child(n+6) { animation-delay: .25s; }

/* ----------------------------------------------------------------- pieces */

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px;
  box-shadow: var(--shadow);
}

.card.interactive { transition: transform .25s var(--ease), box-shadow .25s var(--ease); }
.card.interactive:hover { transform: translateY(-2px); box-shadow: var(--shadow-lift); }

.section-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin: 8px 2px 0;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .02em;
  color: var(--text-2);
}

.grid { display: grid; gap: 12px; grid-template-columns: 1fr; }
@media (min-width: 700px)  { .grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1040px) { .grid { grid-template-columns: repeat(3, 1fr); } }

.row { display: flex; align-items: center; gap: 10px; }
.row-between { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.stack { display: flex; flex-direction: column; gap: 12px; }
.muted { color: var(--text-2); }
.dim { color: var(--text-3); }
.tiny { font-size: 12.5px; }

.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 18px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--text);
  font-weight: 650;
  white-space: nowrap;
  transition: transform .15s var(--ease), background .2s var(--ease), box-shadow .25s var(--ease), opacity .2s;
}

.btn:active { transform: scale(.97); }
.btn svg { width: 18px; height: 18px; }

.btn-primary {
  border-color: transparent;
  background: var(--grad);
  color: var(--accent-text);
  box-shadow: var(--shadow-glow);
}
.btn-primary:hover { box-shadow: 0 14px 38px -8px rgb(91 75 255 / 65%); }

.btn-ghost { border-color: transparent; background: transparent; box-shadow: none; }
.btn-ghost:hover { background: var(--surface-2); }
.btn-block { width: 100%; }
.btn-lg { min-height: 54px; font-size: 16.5px; border-radius: var(--radius); }
.btn:disabled { opacity: .45; cursor: default; box-shadow: none; transform: none; }

.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 13px;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--text-2);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  transition: all .2s var(--ease);
}

.chip:active { transform: scale(.95); }

.chip[aria-pressed="true"] {
  border-color: transparent;
  background: var(--grad);
  color: #fff;
  box-shadow: 0 6px 16px -6px rgb(91 75 255 / 55%);
}

.chiprow {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding-block: 2px 4px;
  margin-inline: calc(var(--gutter) * -1);
  padding-inline: var(--gutter);
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
}
.chiprow::-webkit-scrollbar { display: none; }

.divider-v { width: 1px; flex: 0 0 1px; margin: 4px 2px; background: var(--line-strong); }

.tag {
  display: inline-flex;
  align-items: center;
  padding: 3px 8px;
  border-radius: 7px;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .03em;
  color: #fff;
  direction: ltr;
}
.tag.A1 { background: linear-gradient(135deg, #10b981, #34d399); }
.tag.A2 { background: linear-gradient(135deg, #0284c7, #38bdf8); }
.tag.B1 { background: linear-gradient(135deg, #d97706, #fbbf24); }
.tag.B2 { background: linear-gradient(135deg, #e11d48, #fb7185); }

.pill {
  display: inline-flex;
  align-items: center;
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--text-2);
  font-size: 12px;
  font-weight: 550;
}
.pill.accent { background: var(--accent-soft); color: var(--accent); }

.search {
  position: relative;
  display: flex;
  align-items: center;
}

.search svg {
  position: absolute;
  inset-inline-start: 14px;
  width: 18px;
  height: 18px;
  color: var(--text-3);
  pointer-events: none;
}

.search input {
  width: 100%;
  min-height: 48px;
  padding-block: 0;
  padding-inline: 44px 14px;
  border-radius: var(--radius);
  border: 1px solid var(--line-strong);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  outline: none;
  transition: border-color .2s var(--ease), box-shadow .2s var(--ease);
}
.search input:focus { border-color: var(--accent); box-shadow: 0 0 0 4px var(--accent-soft); }

/* --------------------------------------------------------------- home hero */

.hero {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  padding: 22px;
  border-radius: var(--radius-lg);
  background: var(--grad);
  color: #fff;
  box-shadow: var(--shadow-glow), var(--shadow-lift);
}

/* Soft light blobs drifting behind the hero content. Transform-only animation. */
.hero::before, .hero::after {
  content: "";
  position: absolute;
  z-index: -1;
  border-radius: 50%;
  background: rgb(255 255 255 / 18%);
  filter: blur(2px);
}
.hero::before { width: 220px; height: 220px; inset-block-start: -90px; inset-inline-end: -60px; animation: drift 9s ease-in-out infinite alternate; }
.hero::after  { width: 140px; height: 140px; inset-block-end: -60px; inset-inline-start: -30px; background: rgb(255 255 255 / 10%); animation: drift 12s ease-in-out infinite alternate-reverse; }

@keyframes drift {
  from { transform: translate(0, 0) scale(1); }
  to   { transform: translate(-18px, 14px) scale(1.08); }
}

.hero-top { display: flex; align-items: center; justify-content: space-between; gap: 14px; }
.hero-greet { font-size: 14px; font-weight: 600; opacity: .88; }
.hero-title { margin: 2px 0 0; font-size: 24px; font-weight: 800; letter-spacing: -.02em; line-height: 1.2; }

.ring { position: relative; width: 96px; height: 96px; flex: 0 0 auto; }
.ring svg { width: 100%; height: 100%; transform: rotate(-90deg); }
:root[dir="rtl"] .ring svg { transform: rotate(-90deg) scaleY(-1); }
.ring .track { stroke: rgb(255 255 255 / 22%); }
.ring .value { stroke: #fff; stroke-linecap: round; transition: stroke-dashoffset 1s var(--ease); }
.ring .label { position: absolute; inset: 0; display: grid; place-content: center; text-align: center; line-height: 1.05; }
.ring .label b { font-size: 26px; font-weight: 800; letter-spacing: -.02em; }
.ring .label span { font-size: 10.5px; font-weight: 600; opacity: .85; }

.hero .btn-hero {
  margin-block-start: 18px;
  width: 100%;
  min-height: 52px;
  border: 0;
  border-radius: var(--radius);
  background: #fff;
  color: #3b2fd6;
  font-size: 16px;
  font-weight: 750;
  box-shadow: 0 10px 24px -10px rgb(0 0 0 / 35%);
}
.hero .btn-hero:disabled { background: rgb(255 255 255 / 30%); color: #fff; opacity: 1; }
.hero .btn-hero svg { transition: transform .25s var(--ease); }
.hero .btn-hero:not(:disabled):hover svg { transform: translateX(3px); }
:root[dir="rtl"] .hero .btn-hero svg { transform: scaleX(-1); }
:root[dir="rtl"] .hero .btn-hero:not(:disabled):hover svg { transform: scaleX(-1) translateX(3px); }

.hero-meta { display: flex; align-items: center; gap: 6px; margin-block-start: 12px; font-size: 13px; font-weight: 600; opacity: .92; }
.hero-meta svg { width: 16px; height: 16px; color: #ffd27a; }

/* Stat tiles */

.stats { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }
@media (min-width: 760px) { .stats { grid-template-columns: repeat(4, 1fr); } }

.stat {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px;
  border-radius: var(--radius);
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--shadow);
}

.stat .bubble {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 11px;
}
.stat .bubble svg { width: 19px; height: 19px; }

.stat .value { font-size: 26px; font-weight: 800; line-height: 1; letter-spacing: -.02em; }
.stat .label { font-size: 13px; font-weight: 650; }
.stat .hint { font-size: 11.5px; color: var(--text-3); }

.stat.due .bubble      { background: var(--accent-soft); color: var(--accent); }
.stat.new .bubble      { background: rgb(14 165 233 / 13%); color: #0ea5e9; }
.stat.learning .bubble { background: var(--warn-soft); color: var(--warn); }
.stat.known .bubble    { background: var(--good-soft); color: var(--good); }

/* Level progress */

.levels { display: flex; flex-direction: column; gap: 14px; }

.level-row { display: grid; grid-template-columns: 38px 1fr auto; align-items: center; gap: 12px; }
.level-row .count { font-size: 12px; font-weight: 650; color: var(--text-3); font-variant-numeric: tabular-nums; direction: ltr; }

.meter { height: 8px; border-radius: 99px; background: var(--surface-3); overflow: hidden; }
.meter i { display: block; height: 100%; border-radius: inherit; transition: width 1s var(--ease); }
.meter.A1 i { background: linear-gradient(90deg, #10b981, #34d399); }
.meter.A2 i { background: linear-gradient(90deg, #0284c7, #38bdf8); }
.meter.B1 i { background: linear-gradient(90deg, #d97706, #fbbf24); }
.meter.B2 i { background: linear-gradient(90deg, #e11d48, #fb7185); }
/* Meters fill from the reading start. */
:root[dir="rtl"] .meter i { margin-inline-start: auto; }

/* Quick links */

.quick { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }

.quick a {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 16px;
  border-radius: var(--radius);
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--shadow);
  color: var(--text);
  transition: transform .25s var(--ease), box-shadow .25s var(--ease);
}
.quick a:hover { transform: translateY(-3px); box-shadow: var(--shadow-lift); }
.quick a:active { transform: scale(.98); }
.quick .ic { display: grid; place-items: center; width: 42px; height: 42px; border-radius: 13px; background: var(--grad-soft); color: var(--accent); }
.quick .ic svg { width: 22px; height: 22px; }
.quick strong { font-size: 15px; }
.quick span { font-size: 12.5px; color: var(--text-3); }

/* ------------------------------------------------------------ sign-in prompt */

.sync-prompt { display: flex; flex-direction: column; gap: 12px; border-color: var(--accent-soft); }
.sync-prompt-ic { flex: none; display: grid; place-items: center; width: 42px; height: 42px; border-radius: 13px; background: var(--grad-soft); color: var(--accent); }
.sync-prompt-ic svg { width: 22px; height: 22px; }

.consent { display: flex; align-items: flex-start; gap: 10px; cursor: pointer; }
.consent input { flex: none; width: 20px; height: 20px; margin: 1px 0 0; accent-color: var(--accent); }
.consent a { font-weight: 650; }

/* ------------------------------------------------------------ privacy page */

.privacy .card { display: flex; flex-direction: column; gap: 8px; }
.privacy h3 { margin: 0; font-size: 16px; }
.privacy p { margin: 0; line-height: 1.6; }

.legal-links { display: flex; justify-content: center; gap: 10px; padding: 4px 0 8px; font-size: 13px; color: var(--text-3); }
.legal-links a { color: var(--text-2); font-weight: 600; }

/* ------------------------------------------------------------ status strip */
/* Replaces the "you are offline" interstitial: a one-line, non-blocking note. */

.netstrip {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 7px var(--gutter);
  font-size: 13px;
  font-weight: 600;
}
.netstrip.offline { background: var(--warn-soft); color: var(--warn); }
.netstrip.syncing { background: var(--accent-soft); color: var(--accent); }
.netstrip svg { width: 16px; height: 16px; }

.spinner {
  width: 14px;
  height: 14px;
  flex: 0 0 auto;
  border: 2px solid currentColor;
  border-inline-end-color: transparent;
  border-radius: 50%;
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* --------------------------------------------------------- install banner */

.installbar {
  position: fixed;
  z-index: 40;
  inset-inline: 12px;
  inset-block-end: calc(var(--nav-h) + env(safe-area-inset-bottom) + 22px);
  max-width: 520px;
  margin-inline: auto;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border-radius: var(--radius);
  border: 1px solid var(--line-strong);
  background: var(--surface);
  box-shadow: var(--shadow-lift);
  animation: rise .45s var(--ease) both;
}
.installbar .icon { font-size: 22px; flex: 0 0 auto; }
.installbar .body { flex: 1; min-width: 0; }
.installbar .body strong { display: block; font-size: 14px; }
.installbar .body span { font-size: 12.5px; color: var(--text-2); }

/* The update bar borrows the install bar's shape but sits above it, on the rare
   occasion both have something to say, and carries the accent edge so it reads as
   news rather than as another prompt to install. */
.updatebar {
  position: fixed;
  z-index: 41;
  inset-inline: 12px;
  inset-block-end: calc(var(--nav-h) + env(safe-area-inset-bottom) + 22px);
  max-width: 520px;
  margin-inline: auto;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border-radius: var(--radius);
  border: 1px solid transparent;
  background:
    linear-gradient(var(--surface), var(--surface)) padding-box,
    var(--grad) border-box;
  box-shadow: var(--shadow-lift);
  animation: rise .45s var(--ease) both;
}
.updatebar .icon { font-size: 22px; flex: 0 0 auto; }
.updatebar .body { flex: 1; min-width: 0; }
.updatebar .body strong { display: block; font-size: 14px; }
.updatebar .body span { font-size: 12.5px; color: var(--text-2); }

/* Stacked above the install bar on the rare launch where both have something to say. */
.updatebar.stacked { inset-block-end: calc(var(--nav-h) + env(safe-area-inset-bottom) + 96px); }

/* ------------------------------------------------------------------ review */

.review { display: flex; flex-direction: column; gap: 16px; min-height: calc(100dvh - var(--header-h) - var(--nav-h) - 80px); }

.review-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; font-size: 13px; font-weight: 650; color: var(--text-2); }

.review-progress {
  height: 6px;
  border-radius: 99px;
  background: var(--surface-3);
  overflow: hidden;
}
.review-progress i { display: block; height: 100%; border-radius: inherit; background: var(--grad); transition: width .45s var(--ease); }
:root[dir="rtl"] .review-progress i { margin-inline-start: auto; }

/* The card itself. A real 3D flip - front shows the prompt, back the answer - so the
   reveal has weight instead of just more text appearing. */
.flip {
  flex: 1;
  display: grid;
  min-height: 340px;
  perspective: 1400px;
}

.flip-inner {
  position: relative;
  display: grid;
  transform-style: preserve-3d;
  transition: transform .6s var(--ease);
}
.flip.revealed .flip-inner { transform: rotateY(180deg); }

.face {
  grid-area: 1 / 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 28px 22px;
  text-align: center;
  border-radius: var(--radius-lg);
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-lift);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}
.face.back { transform: rotateY(180deg); }

/* A thin gradient edge across the top of each face. */
.face::before {
  content: "";
  position: absolute;
  inset-inline: 22px;
  inset-block-start: 0;
  height: 3px;
  border-radius: 0 0 3px 3px;
  background: var(--grad);
  opacity: .9;
}

.face .kind { font-size: 11.5px; font-weight: 750; letter-spacing: .08em; text-transform: uppercase; color: var(--text-3); }
.q .prompt, .face .prompt { margin: 0; font-size: clamp(26px, 7vw, 40px); font-weight: 780; line-height: 1.2; letter-spacing: -.02em; }
.q .hint, .face .hint { font-size: 13px; color: var(--text-3); font-family: var(--font-mono); }
.q .answer, .face .answer {
  margin: 0;
  font-size: clamp(22px, 5.6vw, 32px);
  font-weight: 750;
  line-height: 1.3;
  background: var(--grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.face .gloss-2 { font-size: 14px; color: var(--text-3); }
.face .headword { font-size: 17px; font-weight: 650; color: var(--text-2); }

.example {
  width: 100%;
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  text-align: start;
  font-size: 15px;
  color: var(--text-2);
}

.speak {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 650;
  font-size: 14px;
  transition: transform .15s var(--ease);
}
.speak:active { transform: scale(.94); }
.speak svg { width: 18px; height: 18px; }

.gradebar { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.gradebar .btn {
  flex-direction: column;
  gap: 1px;
  min-height: 64px;
  border-width: 1.5px;
  font-size: 15px;
  font-weight: 750;
}
.gradebar .btn small { font-size: 11.5px; font-weight: 600; opacity: .75; direction: ltr; }
.gradebar .again { border-color: color-mix(in srgb, var(--bad) 45%, transparent); color: var(--bad); background: var(--bad-soft); }
.gradebar .hard  { border-color: color-mix(in srgb, var(--warn) 45%, transparent); color: var(--warn); background: var(--warn-soft); }
.gradebar .good  { border-color: color-mix(in srgb, var(--good) 45%, transparent); color: var(--good); background: var(--good-soft); }

.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 56px 24px;
  text-align: center;
  color: var(--text-2);
}
.empty .big {
  display: grid;
  place-items: center;
  width: 84px;
  height: 84px;
  margin-block-end: 10px;
  border-radius: 28px;
  background: var(--grad-soft);
  font-size: 40px;
  animation: float 3.5s ease-in-out infinite;
}
.empty p { margin: 0; }
@keyframes float { 50% { transform: translateY(-6px); } }

/* ------------------------------------------------------------ list entries */

.entry { display: flex; flex-direction: column; gap: 10px; }
.entry .head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.entry .word { font-size: 19px; font-weight: 750; letter-spacing: -.01em; line-height: 1.3; }
.entry .gloss { font-size: 14.5px; color: var(--text); }
.entry .gloss-2 { font-size: 13px; color: var(--text-3); }
.entry .meta { display: flex; flex-wrap: wrap; gap: 6px; }
.entry .actions { display: flex; align-items: center; gap: 6px; margin-block-start: 2px; }
.entry .actions .btn { min-height: 34px; padding: 0 12px; font-size: 13px; }

/* Add / remove from the Leitner box, straight from a list card. */
.entry .btn.deck { gap: 6px; }
.entry .btn.deck svg { width: 16px; height: 16px; }
.btn.deck.in {
  border-color: transparent;
  background: var(--grad);
  color: #fff;
}

/* "I know this" - takes a card off the list; in the Learned view it puts it back. */
.entry .learn-row { display: flex; padding-block-start: 8px; border-block-start: 1px solid var(--line); }
.entry .learn-row .btn { flex: 1; min-height: 38px; padding: 0 12px; font-size: 13.5px; }
.entry .btn.learn { gap: 6px; color: var(--good); }
.entry .btn.learn svg { width: 16px; height: 16px; }
.entry .btn.learn:hover { background: var(--good-soft); }
.entry .btn.learn.undo { color: var(--text-2); }
.entry .btn.learn.undo:hover { background: var(--surface-2); }

/* To learn / Learned switch above the lists. */
.seg .count {
  min-width: 22px;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--surface-3);
  color: var(--text-2);
  font-size: 11.5px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.seg button[aria-pressed="true"] .count { background: var(--accent-soft); color: var(--accent); }

/* "Moved to Learned - Undo", above the nav bar. */
.toast {
  position: fixed;
  z-index: 42;
  inset-inline: 12px;
  inset-block-end: calc(var(--nav-h) + env(safe-area-inset-bottom) + 22px);
  max-width: 520px;
  margin-inline: auto;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px;
  padding-inline: 14px 10px;
  border-radius: var(--radius);
  background: var(--text);
  color: var(--bg);
  box-shadow: var(--shadow-lift);
  font-size: 14px;
  animation: rise .35s var(--ease) both;
}
.toast > svg { width: 18px; height: 18px; flex: 0 0 auto; color: var(--good); }
.toast .msg { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.toast-btn {
  flex: 0 0 auto;
  min-height: 34px;
  padding: 0 12px;
  border-radius: var(--radius-xs);
  font-weight: 700;
  color: var(--bg);
  background: color-mix(in srgb, var(--bg) 14%, transparent);
}
.toast-btn:hover { background: color-mix(in srgb, var(--bg) 24%, transparent); }

/* "When a German speaker says this" - the note that makes a phrase usable. */
.usage {
  display: flex;
  gap: 10px;
  padding: 11px 13px;
  border-radius: var(--radius-sm);
  background: var(--grad-soft);
  font-size: 13.5px;
  line-height: 1.7;
}
.usage svg { width: 18px; height: 18px; flex: 0 0 auto; margin-block-start: 3px; color: var(--accent); }
.usage b { display: block; font-size: 11.5px; font-weight: 750; letter-spacing: .04em; color: var(--accent); }

/* -------------------------------------------------------------- utilities */

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.loading-shell {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  min-height: 100dvh; gap: 14px; color: var(--text-2);
}

/* ------------------------------------------------------------ conjugation */

.conj {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-block-start: 4px;
  padding-block-start: 12px;
  border-block-start: 1px solid var(--line);
  direction: ltr;           /* a conjugation table is German through and through */
  text-align: left;
}

.conj h4 {
  margin: 0 0 6px;
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--accent);
}

.conj h4 em { font-style: normal; text-transform: none; letter-spacing: .02em; color: var(--text-3); }

.conj .rows { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0 16px; }
@media (max-width: 420px) { .conj .rows { grid-template-columns: 1fr; } }

.conj .rw {
  display: flex;
  gap: 8px;
  padding: 3px 0;
  font-size: 14px;
  border-block-end: 1px dashed var(--line);
}

.conj .rw i { flex: 0 0 46px; font-size: 12px; font-style: normal; color: var(--text-3); }
.conj .one { font-size: 14px; }

/* The highlighted part is what actually changes: prefix, participle, infinitive. */
.conj u { text-decoration: none; color: var(--accent); font-weight: 700; }
.conj em { font-style: normal; color: var(--text-3); }

/* The word-order note on a Redemittel card. */
.syntax {
  padding: 6px 10px;
  border-inline-start: 3px solid var(--accent);
  border-radius: var(--radius-xs);
  background: var(--accent-soft);
  font-size: 12px;
  line-height: 1.6;
  color: var(--text);
}

/* ------------------------------------------------------------------ intro */

.intro {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background-color: var(--bg);
  background-image:
    radial-gradient(40rem 30rem at 15% 10%, var(--bg-glow-1), transparent 60%),
    radial-gradient(36rem 28rem at 90% 30%, var(--bg-glow-2), transparent 60%);
  padding: calc(env(safe-area-inset-top) + 12px) var(--gutter) calc(env(safe-area-inset-bottom) + 20px);
}

.intro-top { display: flex; justify-content: flex-end; min-height: 44px; }

.intro-track {
  flex: 1;
  display: flex;
  transition: transform .55s var(--ease);
}

.slide {
  flex: 0 0 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 18px;
  padding: 12px;
  text-align: center;
}

.slide h2 {
  margin: 0;
  max-width: 440px;
  font-size: clamp(26px, 7vw, 34px);
  font-weight: 800;
  letter-spacing: -.02em;
  line-height: 1.2;
}

.slide p { margin: 0; max-width: 420px; font-size: 16px; line-height: 1.7; color: var(--text-2); }

/* Illustrations are drawn in CSS so the intro adds no images to the offline payload. */
.art {
  position: relative;
  width: 220px;
  height: 220px;
  margin-block-end: 8px;
  display: grid;
  place-items: center;
}

.art .orb {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--grad);
  opacity: .16;
  animation: pulse 4s ease-in-out infinite;
}
.art .orb.two { inset: 30px; opacity: .22; animation-delay: -1.3s; }
@keyframes pulse { 50% { transform: scale(1.06); } }

.art .tile {
  position: relative;
  display: grid;
  place-items: center;
  width: 120px;
  height: 120px;
  border-radius: 36px;
  background: var(--grad);
  color: #fff;
  box-shadow: var(--shadow-glow), var(--shadow-lift);
  animation: float 4s ease-in-out infinite;
}
.art .tile svg { width: 58px; height: 58px; }
.art .tile .glyph { font-size: 52px; font-weight: 800; letter-spacing: -.04em; line-height: 1; }

/* Leitner boxes illustration: seven bars growing like a schedule stretching out. */
.art .boxes { position: relative; display: flex; align-items: flex-end; gap: 7px; height: 120px; direction: ltr; }
.art .boxes i {
  width: 18px;
  border-radius: 6px;
  background: var(--grad);
  box-shadow: var(--shadow-glow);
  transform-origin: bottom;
  animation: grow 1.2s var(--spring) both;
}
.art .boxes i:nth-child(1) { height: 22%; animation-delay: .05s; }
.art .boxes i:nth-child(2) { height: 34%; animation-delay: .12s; }
.art .boxes i:nth-child(3) { height: 46%; animation-delay: .19s; }
.art .boxes i:nth-child(4) { height: 58%; animation-delay: .26s; }
.art .boxes i:nth-child(5) { height: 72%; animation-delay: .33s; }
.art .boxes i:nth-child(6) { height: 86%; animation-delay: .40s; }
.art .boxes i:nth-child(7) { height: 100%; animation-delay: .47s; }
@keyframes grow { from { transform: scaleY(0); } }

/* Language picker cards on the first slide. */
.lang-grid { display: grid; gap: 10px; width: 100%; max-width: 360px; }

.lang-option {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  border-radius: var(--radius);
  border: 1.5px solid var(--line-strong);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  text-align: start;
  transition: all .2s var(--ease);
}
.lang-option:active { transform: scale(.98); }
.lang-option .code {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 12px;
  background: var(--surface-2);
  font-size: 13px;
  font-weight: 800;
  text-transform: uppercase;
  color: var(--text-2);
}
.lang-option .names { flex: 1; display: flex; flex-direction: column; line-height: 1.3; }
.lang-option .names strong { font-size: 16px; }
.lang-option .names span { font-size: 12.5px; color: var(--text-3); }
.lang-option .check { width: 22px; height: 22px; color: var(--accent); opacity: 0; transform: scale(.5); transition: all .25s var(--spring); }

.lang-option[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); }
.lang-option[aria-pressed="true"] .code { background: var(--grad); color: #fff; }
.lang-option[aria-pressed="true"] .check { opacity: 1; transform: none; }

.intro-foot { display: flex; flex-direction: column; align-items: center; gap: 18px; max-width: 440px; width: 100%; margin-inline: auto; }

.dots { display: flex; gap: 7px; direction: ltr; }
.dots i { width: 7px; height: 7px; border-radius: 99px; background: var(--line-strong); transition: all .35s var(--ease); }
.dots i.on { width: 26px; background: var(--grad); }

.intro-nav { display: flex; gap: 10px; width: 100%; }
.intro-nav .btn { flex: 1; }
.intro-nav .btn-ghost { flex: 0 0 auto; }

/* ------------------------------------------------------------- settings */

.seg {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 4px;
  padding: 4px;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
}

.seg button {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 38px;
  padding: 0 10px;
  border-radius: 9px;
  font-size: 13.5px;
  font-weight: 650;
  color: var(--text-2);
  transition: all .2s var(--ease);
}
.seg button svg { width: 16px; height: 16px; }
.seg button[aria-pressed="true"] { background: var(--surface); color: var(--text); box-shadow: var(--shadow); }

.setting { display: flex; flex-direction: column; gap: 8px; }
.setting + .setting { margin-block-start: 16px; padding-block-start: 16px; border-block-start: 1px solid var(--line); }
.setting .label { font-size: 14.5px; font-weight: 700; }
.setting .hint { font-size: 12.5px; color: var(--text-3); margin-block-start: -4px; }

.switch {
  position: relative;
  flex: 0 0 auto;
  width: 48px;
  height: 28px;
  border-radius: 99px;
  background: var(--surface-3);
  transition: background .25s var(--ease);
}
.switch::after {
  content: "";
  position: absolute;
  inset-block-start: 3px;
  inset-inline-start: 3px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 2px 6px rgb(0 0 0 / 22%);
  transition: inset-inline-start .25s var(--spring);
}
.switch[aria-checked="true"] { background: var(--grad); }
.switch[aria-checked="true"]::after { inset-inline-start: 23px; }
