  /* -webkit-tap-highlight-color reset here (not per-component) because it's
     a browser default, not a theme choice - without it, tapping any button
     or clickable word on Android flashes the OS's own blue-ish highlight
     regardless of which of the three themes is active. */
  * { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
  body {
    margin: 0;
    min-height: 100vh;
    display: flex;
    justify-content: center;
    align-items: flex-start;
    padding: 2rem 1rem;
    background: #FFFFFF;
    font-family: 'IBM Plex Mono', monospace;
    color: #3B2A1C;
  }

  /* ---- Shared card look for both views ---- */
  .card {
    width: 100%;
    max-width: 480px;
    background: rgba(237,224,196,0.4);
    border: 1px solid rgba(184,130,62,0.35);
    border-radius: 18px;
    padding: 1.75rem;
    position: relative;
  }
  .card.wide { max-width: 780px; }

  /* Reserve horizontal touch gestures for the swipe-to-navigate history nav,
     while still letting vertical scroll behave natively. */
  #mainView { touch-action: pan-y; }

  /* Subtle slide+fade when navigating between sets (swipe or the history-nav
     arrows) - .slide-from-* is applied with transitions disabled to set the
     "from" state, then removed a frame later so the browser animates back. */
  .set-content {
    transition: transform 0.25s ease, opacity 0.25s ease;
  }
  /* 12px, not the more visually generous 24px it used to be: at 24px, this
     translateX briefly pushes the table past the true edge of the page on
     Material specifically - its .md-body padding is only 1rem (16px),
     versus 1.75rem (28px) on the other two themes, so the animation's own
     movement was exceeding its container's safety margin by 8px partway
     through the slide. That transient real overflow was observed (via
     mobile viewport emulation) to make the browser briefly misreport
     window.innerWidth, which visibly nudged the fixed Material nav bar
     toward the bottom-right corner for a couple of frames. 12px fits
     safely inside the smallest padding any theme uses. */
  .set-content.slide-from-right { transition: none; transform: translateX(12px); opacity: 0; }
  .set-content.slide-from-left  { transition: none; transform: translateX(-12px); opacity: 0; }
  @media (prefers-reduced-motion: reduce) {
    .set-content { transition: none !important; }
  }

  .header-row {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 1rem;
  }

  .eyebrow {
    font-size: 0.7rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: #A3541F;
    margin: 0 0 0.3rem;
  }
  h1 {
    font-family: 'Space Grotesk', sans-serif;
    font-size: 1.3rem;
    margin: 0 0 1.25rem;
    color: #2E2013;
  }

  /* ---- Hamburger menu (top right, deliberately understated) ---- */
  .menu-wrapper { position: relative; flex-shrink: 0; }
  .hamburger {
    background: transparent;
    border: none;
    font-size: 1.2rem;
    line-height: 1;
    color: #8A7256;
    cursor: pointer;
    padding: 0.35rem 0.5rem;
    border-radius: 6px;
    transition: background 0.15s ease, color 0.15s ease;
  }
  .hamburger:hover { background: rgba(184,130,62,0.12); color: #2E2013; }

  .menu-dropdown {
    display: none;
    position: absolute;
    top: 2.2rem;
    right: 0;
    background: #FFFDF8;
    border: 1px solid rgba(184,130,62,0.35);
    border-radius: 8px;
    box-shadow: 0 8px 20px rgba(59,42,28,0.15);
    min-width: 210px;
    overflow: hidden;
    z-index: 10;
  }
  .menu-dropdown.open { display: block; }
  .menu-dropdown a {
    display: block;
    padding: 0.6rem 0.85rem;
    font-size: 0.85rem;
    color: #3B2A1C;
    text-decoration: none;
    white-space: nowrap;
  }
  .menu-dropdown a:hover { background: rgba(184,130,62,0.12); }
  .menu-dropdown a.danger { color: #B4402B; }
  .menu-dropdown a.danger:hover { background: rgba(180,64,43,0.1); }

  /* ---- Main (topic trainer) view ---- */
  table { width: 100%; border-collapse: collapse; table-layout: fixed; }
  th {
    text-align: left;
    font-size: 0.65rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: #8A7256;
    padding-bottom: 0.5rem;
    border-bottom: 1px solid rgba(59,42,28,0.15);
  }
  td {
    padding: 0.55rem 0.3rem;
    border-bottom: 1px solid rgba(59,42,28,0.1);
    vertical-align: middle;
    font-size: 0.78rem;
    overflow-wrap: break-word;
    /* hyphens:auto (with each cell's lang attribute - es on the Spanish
       word, the page's own de on the German one) finds real syllable
       breaks first; word-break:break-word only kicks in as a fallback for
       anything it can't hyphenate (e.g. missing browser dictionary
       support), instead of being the first thing that fires. */
    hyphens: auto;
    -webkit-hyphens: auto;
    word-break: break-word;
  }
  .word {
    font-weight: 700;
    color: #2E2013;
    font-size: 0.82rem;
    cursor: pointer;
    transition: color 0.15s ease;
  }
  .word:hover, .word:focus { color: #A3541F; outline: none; }
  .ipa { color: #8A7256; font-size: 0.7rem; hyphens: none; -webkit-hyphens: none; }

  .note {
    margin-top: 1rem;
    font-size: 0.75rem;
    color: #8A7256;
  }

  /* ---- Dictionary view ---- */
  .back-link {
    display: inline-block;
    margin-bottom: 1.25rem;
    font-size: 0.8rem;
    color: #A3541F;
    text-decoration: none;
    cursor: pointer;
  }
  .back-link:hover { text-decoration: underline; }

  /* ---- Dictionary search: live-filters entries as you type (matches the
     Spanish word or German translation, see renderDictionary()) ---- */
  /* Wraps the search box together with the direction-switch and word-type-
     filter controls added alongside it - .dict-search-wrap itself no longer
     carries the bottom margin (moved here, onto the row) now that it's one
     flex item among three instead of the sole child of .md-body. */
  .dict-toolbar {
    display: flex;
    align-items: stretch;
    gap: 0.5rem;
    margin-bottom: 1.1rem;
  }
  .dict-search-wrap {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    background: rgba(237,224,196,0.4);
    border: 1px solid rgba(184,130,62,0.35);
    border-radius: 12px;
    padding: 0.5rem 0.75rem;
  }
  .dict-search-icon { color: #A3541F; flex-shrink: 0; }
  .dict-search-input {
    flex: 1;
    min-width: 0;
    border: none;
    background: transparent;
    font-family: inherit;
    font-size: 0.85rem;
    color: #3B2A1C;
  }
  .dict-search-input:focus { outline: none; }
  .dict-search-input::placeholder { color: #8A7256; opacity: 0.7; }
  .dict-search-clear {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.4rem;
    height: 1.4rem;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: rgba(184,130,62,0.18);
    color: #8A7256;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
  }
  .dict-search-clear:hover { background: rgba(184,130,62,0.32); color: #3B2A1C; }

  /* ---- Verb conjugation icon (Wörterbuch): sits right next to .dict-word,
     same circular icon-button shape as .dict-search-clear above but always
     accent-tinted (a feature affordance to notice, not a "clear" action
     that should stay quiet until relevant). .dict-word-row just keeps the
     word+icon pair from splitting apart if dict-columns' 200px column width
     forces a wrap. ---- */
  .dict-word-row { display: inline-flex; align-items: center; gap: 0.3rem; }
  .dict-conjugate-btn {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.3rem;
    height: 1.3rem;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: rgba(163,84,31,0.12);
    color: #A3541F;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
  }
  .dict-conjugate-btn:hover, .dict-conjugate-btn.open { background: rgba(163,84,31,0.26); }

  /* Responsive 1-3 column layout: the browser picks the column count that
     fits, based on the ideal column width, capped at 3 by column-count. */
  .dict-columns {
    column-count: 3;
    column-width: 200px;
    column-gap: 2rem;
  }

  .dict-letter {
    break-inside: avoid;
    break-after: avoid-column;
    font-family: 'Space Grotesk', sans-serif;
    font-weight: 700;
    font-size: 1.05rem;
    color: #A3541F;
    border-bottom: 1px solid rgba(163,84,31,0.3);
    padding-bottom: 0.2rem;
    margin: 1.1rem 0 0.5rem;
  }
  .dict-columns > .dict-letter:first-child { margin-top: 0; }

  .dict-entry {
    break-inside: avoid;
    margin: 0 0 0.65rem;
    font-size: 0.85rem;
    line-height: 1.35;
  }
  .dict-word {
    font-weight: 700;
    color: #2E2013;
    cursor: pointer;
    border-radius: 4px;
    transition: color 0.15s ease;
  }
  .dict-word:hover, .dict-word:focus { color: #A3541F; outline: none; }
  /* DE→ES gloss line: the Spanish word is still functionally `.dict-word`
     (speakable, tappable) but visually needs to read as the gloss, not a
     second bold headword - same weight/color/style as `.dict-de` below. */
  .dict-word.dict-word-gloss { font-weight: 400; font-style: italic; color: #6B573F; }
  .dict-word.dict-word-gloss:hover, .dict-word.dict-word-gloss:focus { color: #A3541F; }
  .dict-ipa { color: #8A7256; font-size: 0.8rem; }
  .dict-de { color: #6B573F; font-style: italic; }
  /* DE→ES headword: same weight/color as .dict-word, but no cursor/hover -
     it's German, this app never speaks German, so it must not look
     tappable the way the (still-speakable) Spanish word does. */
  .dict-headword { font-weight: 700; color: #2E2013; }

  .dict-empty { color: #8A7256; font-size: 0.85rem; }

  /* ---- Direction switch (ES→DE / DE→ES): a single tappable pill that
     flips state on tap (Google-Translate-style swap) - text alone reads
     clearly enough at this size, no icon needed. ---- */
  .dict-direction-switch {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    padding: 0 0.6rem;
    border: 1px solid rgba(184,130,62,0.5);
    border-radius: 12px;
    background: rgba(163,84,31,0.12);
    color: #A3541F;
    font-family: inherit;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.01em;
    cursor: pointer;
    white-space: nowrap;
  }
  .dict-direction-switch:hover { background: rgba(163,84,31,0.22); }

  /* ---- Word-type filter: icon button + anchored popover, same circular-
     icon-button footprint as .dict-search-clear/.dict-conjugate-btn. ---- */
  .dict-filter-wrap { position: relative; flex-shrink: 0; }
  .dict-filter-btn {
    position: relative;
    width: 2.3rem;
    height: 2.3rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid rgba(184,130,62,0.35);
    border-radius: 12px;
    background: rgba(237,224,196,0.4);
    color: #8A7256;
    cursor: pointer;
  }
  .dict-filter-btn[aria-expanded="true"] {
    background: rgba(163,84,31,0.22);
    color: #A3541F;
    border-color: transparent;
  }
  .dict-filter-badge {
    position: absolute;
    top: -2px; right: -2px;
    width: 9px; height: 9px;
    border-radius: 50%;
    background: #A3541F;
    border: 2px solid #FFFFFF;
  }
  .dict-filter-popup {
    position: absolute;
    top: calc(100% + 0.4rem);
    right: 0;
    z-index: 20;
    width: 12.5rem;
    background: #FFFDF8;
    border: 1px solid rgba(184,130,62,0.35);
    border-radius: 14px;
    box-shadow: 0 10px 30px -8px rgba(59,42,28,0.3);
    padding: 0.75rem 0.85rem 0.6rem;
  }
  .dict-filter-title {
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: #8A7256;
    margin: 0 0 0.55rem;
  }
  .dict-filter-option {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.32rem 0;
    font-size: 0.85rem;
    color: #2E2013;
    cursor: pointer;
    user-select: none;
  }
  .dict-filter-option input { width: 17px; height: 17px; accent-color: #A3541F; flex-shrink: 0; }
  .dict-filter-learned-toggle {
    font-weight: 600;
    padding-bottom: 0.55rem;
    margin-bottom: 0.55rem;
    border-bottom: 1px solid rgba(184,130,62,0.3);
  }
  .dict-filter-count {
    margin-left: auto;
    color: #8A7256;
    font-size: 0.75rem;
    font-variant-numeric: tabular-nums;
  }
  .dict-filter-reset {
    width: 100%;
    margin-top: 0.5rem;
    padding-top: 0.55rem;
    border: none;
    border-top: 1px solid rgba(184,130,62,0.3);
    background: none;
    color: #A3541F;
    font-family: inherit;
    font-size: 0.8rem;
    font-weight: 600;
    text-align: left;
    cursor: pointer;
  }

  /* ---- Reference view: switches the same page between Zahlwörter and
     Ordinalzahlen (used to be two separate destinations - merged so the
     Material bottom-nav doesn't need a slot for each) ---- */
  .reference-toggle {
    display: flex;
    gap: 0.5rem;
    margin-bottom: 1.25rem;
  }
  .reference-toggle-btn {
    flex: 1;
    padding: 0.55rem;
    background: rgba(237,224,196,0.4);
    border: 1px solid rgba(184,130,62,0.35);
    border-radius: 8px;
    font-family: 'Space Grotesk', sans-serif;
    font-weight: 600;
    font-size: 0.8rem;
    color: #A3541F;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
  }
  .reference-toggle-btn:hover { background: rgba(184,130,62,0.12); }
  .reference-toggle-btn.active {
    background: #B8823E;
    color: #FFF8ED;
    border-color: transparent;
  }

  /* Responsive 1-2 column layout for the numbers reference page */
  .numbers-columns {
    column-count: 2;
    column-width: 220px;
    column-gap: 2rem;
  }
  .number-entry {
    break-inside: avoid;
    margin: 0 0 0.6rem;
    font-size: 0.85rem;
    line-height: 1.35;
  }
  .number-num {
    font-weight: 700;
    color: #A3541F;
    font-variant-numeric: tabular-nums;
    margin-right: 0.4rem;
  }

  /* ---- Reusable primary action button (quiz prompt, "Auswerten", etc.) ---- */
  .primary-button {
    margin-top: 1.25rem;
    width: 100%;
    padding: 0.7rem;
    background: #B8823E;
    color: #FFF8ED;
    border: none;
    border-radius: 8px;
    font-family: 'Space Grotesk', sans-serif;
    font-weight: 600;
    font-size: 0.9rem;
    cursor: pointer;
    transition: background 0.15s ease, transform 0.1s ease;
  }
  .primary-button:hover { background: #A6743A; }
  .primary-button:active { transform: scale(0.98); }

  /* ---- History nav: step back/forward through recently generated sets ---- */
  .history-nav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    margin-top: 1rem;
  }
  .nav-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 1px solid rgba(184,130,62,0.4);
    color: #A3541F;
    min-width: 2.4rem;
    padding: 0.4rem 0.6rem;
    border-radius: 8px;
    font-family: 'Space Grotesk', sans-serif;
    font-weight: 600;
    font-size: 1.05rem;
    line-height: 1;
    cursor: pointer;
    transition: background 0.15s ease;
  }
  /* Scoped to real-hover devices only - on touch, :hover fires on tap and
     has no mouseleave to clear it, leaving the arrow stuck in its hover
     tint (seen as a Chrome-for-Android-specific "stuck highlight" bug). */
  @media (hover: hover) {
    .nav-button:hover:not(:disabled) { background: rgba(184,130,62,0.12); }
  }
  .nav-button:disabled { opacity: 0.35; cursor: default; }
  /* SVG instead of a "←"/"→" text glyph: Space Grotesk doesn't cover those
     characters, so the browser falls back to a system font for just that
     glyph - on Chrome for Android that fallback's vertical metrics don't
     match, leaving the arrow visibly off-center no matter how the button's
     own box is aligned. An SVG path renders identically everywhere. */
  .nav-arrow-icon { display: block; flex-shrink: 0; }
  /* Modifier for the forward button when it's the "Neue Wörter" / "Quiz" primary action (live set only) */
  .nav-button-primary {
    background: #B8823E;
    color: #FFF8ED;
    border-color: transparent;
    padding: 0.5rem 1rem;
  }
  @media (hover: hover) {
    .nav-button-primary:hover:not(:disabled) { background: #A6743A; }
  }
  .history-status {
    font-size: 0.7rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: #8A7256;
  }

  /* ---- Quiz view ---- */
  .quiz-eyebrow-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
  .mode-badge {
    font-family: 'Space Grotesk', sans-serif;
    font-size: 0.6rem;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: #FFF8ED;
    background: #B8823E;
    border-radius: 999px;
    padding: 0.12rem 0.5rem;
  }
  /* Uniform top+bottom padding, applied to every item with NO exception
     (not even :first-child). The earlier bug here wasn't top padding
     itself - it was a top/bottom split relying on
     `:first-child { padding-top: 0 }` to zero it out: that looks fine in
     a single column, but breaks once #quizBody's multi-column layout (see
     the min-width:1240px block) splits the list, because the first item
     of the SECOND column isn't `:first-child` in the DOM, so it kept its
     top padding and sat ~14px lower than column 1's top item (a real
     reported misalignment). A per-item exception is what broke it -
     giving literally every item the same top padding, with no item ever
     special-cased, keeps whichever item happens to start a column flush
     with every other column's start, since they're all identical. That
     also restores breathing room below each separator line (a second
     real report - bottom-only spacing left rows looking cramped right
     after the line). */
  .quiz-item {
    padding: 0.55rem 0 0.85rem;
    border-bottom: 1px solid rgba(59,42,28,0.1);
  }
  .quiz-row {
    display: grid;
    grid-template-columns: 1.6rem 1fr 1.4rem 1fr;
    align-items: center;
    gap: 0.6rem;
  }
  .quiz-num { color: #8A7256; font-size: 0.78rem; }
  .quiz-de, .quiz-es { font-size: 0.85rem; }
  .quiz-word-given { font-weight: 700; color: #2E2013; }
  .quiz-arrow { text-align: center; color: #8A7256; font-size: 0.85rem; opacity: 0.7; }

  .dash-input {
    width: 100%;
    border: none;
    border-bottom: 2px dashed rgba(184,130,62,0.5);
    background: transparent;
    padding: 0.15rem 0.1rem;
    font-family: inherit;
    font-size: 0.85rem;
    color: #3B2A1C;
    border-radius: 0;
  }
  .dash-input:focus { outline: none; border-bottom-color: #A3541F; }
  .dash-input::placeholder { color: #8A7256; opacity: 0.6; font-family: 'Space Grotesk', sans-serif; font-size: 0.75rem; }

  /* ---- Word cloud answer picker (Einfacher Modus) ---- */
  .cloud-field-wrap { position: relative; width: 100%; }
  .cloud-trigger {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.3rem;
    border: none;
    border-bottom: 2px dashed rgba(184,130,62,0.5);
    background: transparent;
    padding: 0.15rem 0.1rem;
    font-family: inherit;
    font-size: 0.85rem;
    cursor: pointer;
    border-radius: 0;
    text-align: left;
  }
  .cloud-trigger:hover, .cloud-trigger.open { border-bottom-color: #A3541F; }
  .cloud-trigger-text { color: #8A7256; opacity: 0.6; font-family: 'Space Grotesk', sans-serif; font-size: 0.75rem; }
  .cloud-trigger.chosen .cloud-trigger-text { color: #3B2A1C; opacity: 1; font-family: inherit; font-size: 0.85rem; font-weight: 600; }
  .cloud-caret { color: #A3541F; font-size: 0.7rem; flex-shrink: 0; transition: transform 0.15s ease; }
  .cloud-trigger.open .cloud-caret { transform: rotate(180deg); }

  .word-cloud {
    position: fixed;
    display: none;
    max-width: 250px;
    padding: 0.7rem;
    background: #FFFDF8;
    border: 1px solid rgba(184,130,62,0.35);
    border-radius: 14px;
    box-shadow: 0 16px 40px rgba(59,42,28,0.22);
    z-index: 50;
  }
  .word-cloud-chips {
    display: flex;
    flex-wrap: wrap;
    align-content: flex-start;
    gap: 0.4rem;
    max-height: min(60vh, 320px);
    overflow-y: auto;
  }
  .cloud-arrow {
    position: absolute;
    width: 11px;
    height: 11px;
    background: #FFFDF8;
    border-left: 1px solid rgba(184,130,62,0.35);
    border-top: 1px solid rgba(184,130,62,0.35);
  }
  .word-cloud:not(.cloud-above) .cloud-arrow { top: -6px; transform: rotate(45deg); }
  .word-cloud.cloud-above .cloud-arrow { bottom: -6px; transform: rotate(225deg); }

  .cloud-chip {
    font-family: inherit;
    color: #3B2A1C;
    background: rgba(184,130,62,0.12);
    border: 1px solid rgba(184,130,62,0.35);
    border-radius: 999px;
    padding: 0.28rem 0.65rem;
    cursor: pointer;
    transition: background 0.12s ease, border-color 0.12s ease, transform 0.12s ease;
    line-height: 1.3;
  }
  .cloud-chip:hover { background: rgba(184,130,62,0.28); border-color: #A3541F; transform: translateY(-1px); }

  /* ---- Verb conjugation popup: same anchored-popover structure/positioning
     technique as .word-cloud above (position:fixed, diamond arrow, flips
     above/below via .conjugation-above - see toggleConjugationPopup() in
     index.html), just its own class family since the content (a small
     header + 6 pronoun/form rows) is shaped differently from a word-cloud's
     chip grid. ---- */
  .conjugation-popup {
    position: fixed;
    display: none;
    flex-direction: column;
    gap: 0.6rem;
    width: 260px;
    max-width: calc(100vw - 24px);
    padding: 0.9rem 1rem;
    background: #FFFDF8;
    border: 1px solid rgba(184,130,62,0.35);
    border-radius: 14px;
    box-shadow: 0 16px 40px rgba(59,42,28,0.22);
    z-index: 50;
  }
  .conjugation-arrow {
    position: absolute;
    width: 11px;
    height: 11px;
    background: #FFFDF8;
    border-left: 1px solid rgba(184,130,62,0.35);
    border-top: 1px solid rgba(184,130,62,0.35);
  }
  .conjugation-popup:not(.conjugation-above) .conjugation-arrow { top: -6px; transform: rotate(45deg); }
  .conjugation-popup.conjugation-above .conjugation-arrow { bottom: -6px; transform: rotate(225deg); }
  .conjugation-head {
    font-weight: 700;
    color: #2E2013;
    padding-bottom: 0.5rem;
    border-bottom: 1px solid rgba(184,130,62,0.25);
  }
  .conjugation-gloss { font-weight: 400; font-style: italic; color: #6B573F; font-size: 0.85rem; }
  /* Defective/impersonal weather verbs (llover, nevar, ...) only ever get
     one row (él/ella/usted, relabeled "unpersönlich") - this note explains
     why the other 5 are missing instead of it looking like a bug. */
  .conjugation-note { font-style: italic; color: #6B573F; font-size: 0.78rem; margin-top: 0.3rem; }
  .conjugation-rows { display: flex; flex-direction: column; gap: 0.4rem; }
  /* Grid, not flex: the "auto" column always gives .conjugation-form its
     full natural (unwrapped) width first, and whatever's left goes to
     .conjugation-pronoun - which is fine to wrap onto 2 lines (its longest
     entries, e.g. "ellos, ellas, ustedes", have real spaces to break at).
     A flex row with no wrap (the previous approach) instead let the pronoun
     keep its full width unconditionally and pushed the form straight out
     past the popup's edge - exactly backwards, since the short verb form is
     the part that actually needs to stay on one line. */
  .conjugation-row { display: grid; grid-template-columns: 1fr auto; align-items: baseline; gap: 0.6rem; font-size: 0.85rem; }
  .conjugation-pronoun { color: #8A7256; min-width: 0; }
  .conjugation-form { font-weight: 700; color: #2E2013; cursor: pointer; text-align: right; white-space: nowrap; }
  .conjugation-form:hover, .conjugation-form:focus { color: #A3541F; outline: none; }

  .result-cell { display: flex; align-items: baseline; gap: 0.4rem; }
  .result-mark { font-size: 0.9rem; flex-shrink: 0; }
  .result-mark.ok { color: #4C7A3D; }
  .result-mark.no { color: #B4402B; }
  .result-stack { display: flex; flex-direction: column; line-height: 1.35; }
  .result-correct-word { color: #4C7A3D; font-weight: 700; font-size: 0.82rem; }
  .result-wrong-word {
    color: #B4402B;
    text-decoration: line-through;
    text-decoration-thickness: 1.5px;
    font-size: 0.82rem;
    opacity: 0.85;
  }
  .result-plain { color: #4C7A3D; }

  .quiz-result-panel { text-align: center; margin-top: 1.4rem; }
  .quiz-motivation {
    margin: 0 0 0.5rem;
    font-family: 'Space Grotesk', sans-serif;
    font-weight: 700;
    font-size: 1rem;
    color: #A3541F;
  }
  #quizScore {
    margin-bottom: 1.1rem;
    font-family: 'Space Grotesk', sans-serif;
    font-weight: 700;
    font-size: 1.05rem;
    color: #2E2013;
    text-align: center;
  }
  .quiz-retry-prompt {
    margin: 0 0 0.9rem;
    font-size: 0.8rem;
    color: #8A7256;
  }
  .quiz-result-actions { display: flex; gap: 0.7rem; }
  .quiz-result-actions .primary-button,
  .quiz-result-actions .secondary-button {
    width: auto;
    flex: 1;
    margin-top: 0;
  }
  .secondary-button {
    padding: 0.7rem;
    background: transparent;
    border: 1px solid rgba(184,130,62,0.4);
    color: #A3541F;
    border-radius: 8px;
    font-family: 'Space Grotesk', sans-serif;
    font-weight: 600;
    font-size: 0.9rem;
    cursor: pointer;
    transition: background 0.15s ease;
  }
  .secondary-button:hover { background: rgba(184,130,62,0.1); }
  .result-article-note {
    color: #A3541F;
    font-size: 0.78rem;
    opacity: 0.9;
  }

  /* ---- Confirmation modal (styled like the rest of the app, replaces native confirm()) ---- */
  .modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(59,42,28,0.35);
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 1rem;
    z-index: 100;
  }
  .modal-box {
    width: 100%;
    max-width: 360px;
    background: #FFFDF8;
    border: 1px solid rgba(184,130,62,0.35);
    border-radius: 14px;
    padding: 1.5rem;
    box-shadow: 0 20px 50px rgba(59,42,28,0.25);
  }
  .modal-box h2 {
    font-family: 'Space Grotesk', sans-serif;
    font-size: 1.05rem;
    color: #2E2013;
    margin: 0 0 0.6rem;
  }
  .modal-box p {
    font-size: 0.85rem;
    color: #6B573F;
    line-height: 1.5;
    margin: 0;
  }
  .modal-actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.6rem;
    margin-top: 1.4rem;
  }
  .modal-actions button {
    padding: 0.5rem 0.9rem;
    border-radius: 8px;
    font-family: 'Space Grotesk', sans-serif;
    font-weight: 600;
    font-size: 0.82rem;
    cursor: pointer;
    border: none;
    transition: background 0.15s ease;
  }
  .modal-cancel {
    background: transparent;
    color: #6B573F;
    border: 1px solid rgba(184,130,62,0.35) !important;
  }
  .modal-cancel:hover { background: rgba(184,130,62,0.1); }
  .modal-confirm {
    background: #B4402B;
    color: #FFF8ED;
  }
  .modal-confirm-neutral {
    background: #B8823E;
    color: #FFF8ED;
  }
  .modal-confirm-neutral:hover { background: #A6743A; }
  .modal-confirm:hover { background: #97331F; }

  /* ---- Settings view: grouped, uniform-row layout (compact on mobile) ---- */
  .settings-section-label {
    font-family: 'Space Grotesk', sans-serif;
    font-size: 0.68rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: #A3541F;
    margin: 0 0 0.4rem 0.3rem;
  }
  .settings-section-label.danger { color: #B4402B; }
  .settings-hint { font-size: 0.72rem; color: #8A7256; margin: -0.15rem 0 0.6rem 0.3rem; }
  .app-version { text-align: center; font-size: 0.68rem; color: #8A7256; opacity: 0.75; margin: 1.6rem 0 0; }
  .settings-section {
    background: rgba(237,224,196,0.4);
    border: 1px solid rgba(184,130,62,0.35);
    border-radius: 14px;
    overflow: hidden;
    margin-bottom: 1rem;
  }
  .settings-section:last-child { margin-bottom: 0; }

  .settings-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    min-height: 2.75rem;
    padding: 0.6rem 0.9rem;
  }
  .settings-row + .settings-row {
    border-top: 1px solid rgba(59,42,28,0.12);
  }
  .settings-row-label {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 0;
  }
  .settings-row-title {
    font-family: -apple-system, 'Segoe UI', sans-serif;
    font-size: 0.88rem;
    font-weight: 500;
    color: #2E2013;
    display: flex;
    align-items: center;
    gap: 0.4rem;
  }
  .settings-row-caption {
    font-size: 0.68rem;
    color: #8A7256;
    line-height: 1.4;
  }

  /* action-row is a <button> made to look like a row: reset the button chrome */
  button.action-row {
    width: 100%;
    background: transparent;
    border: none;
    font: inherit;
    text-align: left;
    cursor: pointer;
    transition: background 0.15s ease;
  }
  button.action-row:hover { background: rgba(184,130,62,0.1); }
  .action-row.danger .settings-row-title { color: #B4402B; }
  .action-row.danger:hover { background: rgba(180,64,43,0.1); }
  .chevron {
    font-family: -apple-system, 'Segoe UI', sans-serif;
    color: #A3541F;
    font-size: 0.95rem;
    flex-shrink: 0;
  }
  .action-row.danger .chevron { color: #B4402B; }

  .toggle-switch {
    position: relative;
    width: 2.6rem;
    height: 1.5rem;
    flex-shrink: 0;
  }
  .toggle-switch input {
    opacity: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    position: absolute;
    cursor: pointer;
    z-index: 1;
  }
  .toggle-track {
    position: absolute;
    inset: 0;
    background: rgba(184,130,62,0.28);
    border-radius: 999px;
    transition: background 0.2s ease;
  }
  .toggle-track::before {
    content: '';
    position: absolute;
    top: 0.18rem;
    left: 0.18rem;
    width: 1.14rem;
    height: 1.14rem;
    background: #FFF8ED;
    border-radius: 50%;
    box-shadow: 0 1px 3px rgba(59,42,28,0.35);
    transition: transform 0.2s ease;
  }
  .toggle-switch input:checked + .toggle-track { background: #B8823E; }
  .toggle-switch input:checked + .toggle-track::before { transform: translateX(1.1rem); }

  /* =====================================================================
     Glas-Design (Liquid Glass theme): additive overrides only, scoped under
     body.theme-frosted-amber / body.theme-pastel-bloom. Nothing above this
     point is touched — the classic look is always what ships when a theme
     isn't active. Palette tokens are CSS custom properties (--glass-*),
     defined once per theme, then used by one shared block of component
     rules below so both themes stay in sync structurally.
     ===================================================================== */

  .glass-blob-field { display: none; }
  body.theme-frosted-amber .glass-blob-field,
  body.theme-pastel-bloom .glass-blob-field {
    display: block;
    position: fixed;
    inset: 0;
    z-index: -1;
    overflow: hidden;
  }
  .glass-blob { position: absolute; border-radius: 50%; filter: blur(80px); opacity: 0.55; }
  .glass-blob-1 { width: 42vmax; height: 42vmax; background: var(--glass-blob-a); top: -16vmax; left: -10vmax; }
  .glass-blob-2 { width: 38vmax; height: 38vmax; background: var(--glass-blob-b); bottom: -14vmax; right: -8vmax; }
  .glass-blob-3 { width: 30vmax; height: 30vmax; background: var(--glass-blob-c, transparent); top: 30%; right: -12vmax; }
  .glass-blob-4 { width: 26vmax; height: 26vmax; background: var(--glass-blob-d, transparent); bottom: 10%; left: -10vmax; }

  body.theme-frosted-amber {
    --glass-bg: #FBF3E4;
    --glass-blob-a: #F4E4C1; --glass-blob-b: #E8C896; --glass-blob-c: #D9A15C; --glass-blob-d: #FFF4DE;
    --glass-panel-bg: rgba(255,250,240,0.55);
    --glass-panel-bg-soft: rgba(255,255,255,0.35);
    --glass-panel-border: rgba(184,130,62,0.4);
    --glass-panel-shadow: rgba(120,80,30,0.18);
    --glass-text-primary: #2E2013;
    --glass-text-body: #3B2A1C;
    --glass-text-muted: #8A7256;
    --glass-accent: #A3541F;
    --glass-primary-bg: #B8823E;
    --glass-primary-text: #FFF8ED;
    --glass-primary-hover: #A6743A;
    --glass-danger: #B4402B;
    --glass-danger-hover: #97331F;
    --glass-success: #4C7A3D;
    --glass-sheen: rgba(255,255,255,0.8);
    --glass-dash: rgba(184,130,62,0.5);
    --glass-chip-bg: rgba(184,130,62,0.12);
    --glass-chip-hover: rgba(184,130,62,0.28);
    --glass-toggle-track-off: rgba(184,130,62,0.28);
    --glass-toggle-track-on: #B8823E;
    --glass-toggle-knob: #FFF8ED;
    --glass-modal-bg: rgba(255,253,248,0.75);
    --glass-overlay-dim: rgba(59,42,28,0.35);
    --glass-danger-tint: rgba(180,64,43,0.1);
  }
  body.theme-pastel-bloom {
    --glass-bg: #FAFAFA;
    --glass-blob-a: #A9C6FF; --glass-blob-b: #FFB8D2; --glass-blob-c: #FFD9A0; --glass-blob-d: #C9B8FF;
    --glass-panel-bg: rgba(255,255,255,0.58);
    --glass-panel-bg-soft: rgba(255,255,255,0.42);
    --glass-panel-border: rgba(40,50,90,0.12);
    --glass-panel-shadow: rgba(40,40,90,0.16);
    --glass-text-primary: #1C1C2E;
    --glass-text-body: #2A2A3D;
    --glass-text-muted: rgba(28,28,46,0.55);
    --glass-accent: #007AFF;
    --glass-primary-bg: #007AFF;
    --glass-primary-text: #FFFFFF;
    --glass-primary-hover: #339CFF;
    --glass-danger: #FF3B30;
    --glass-danger-hover: #E0281D;
    --glass-success: #34C759;
    --glass-sheen: rgba(255,255,255,0.95);
    --glass-dash: rgba(0,122,255,0.4);
    --glass-chip-bg: rgba(0,122,255,0.1);
    --glass-chip-hover: rgba(0,122,255,0.22);
    --glass-toggle-track-off: rgba(28,28,46,0.15);
    --glass-toggle-track-on: #007AFF;
    --glass-toggle-knob: #FFFFFF;
    --glass-modal-bg: rgba(255,255,255,0.75);
    --glass-overlay-dim: rgba(20,20,40,0.35);
    --glass-danger-tint: rgba(255,59,48,0.12);
  }

  /* ---- Shared component overrides (both themes, via the tokens above) ---- */
  body.theme-frosted-amber,
  body.theme-pastel-bloom {
    background: var(--glass-bg);
    color: var(--glass-text-body);
  }
  body.theme-frosted-amber h1,
  body.theme-pastel-bloom h1,
  body.theme-frosted-amber .modal-box h2,
  body.theme-pastel-bloom .modal-box h2,
  body.theme-frosted-amber .primary-button,
  body.theme-pastel-bloom .primary-button,
  body.theme-frosted-amber .secondary-button,
  body.theme-pastel-bloom .secondary-button,
  body.theme-frosted-amber .settings-row-title,
  body.theme-pastel-bloom .settings-row-title,
  body.theme-frosted-amber .nav-button-primary,
  body.theme-pastel-bloom .nav-button-primary,
  body.theme-frosted-amber .modal-actions button,
  body.theme-pastel-bloom .modal-actions button {
    font-family: -apple-system, 'Segoe UI', sans-serif;
  }
  /* The plain prev/next arrows (←/→, not the "+"/Quiz primary action) stay
     in the app's own monospace font — -apple-system's glyph metrics for
     those arrow characters sit noticeably lower, throwing off vertical
     alignment against the rest of the pill. */
  body.theme-frosted-amber .nav-button:not(.nav-button-primary),
  body.theme-pastel-bloom .nav-button:not(.nav-button-primary) {
    font-family: 'IBM Plex Mono', monospace;
  }

  /* Cards: the core "pane of glass" look */
  /* backdrop-filter on .card itself would make .card a containing block for
     any position:fixed descendant (the word-cloud popup) — it would then
     track the card's scroll position instead of the viewport, going
     offset/off-screen. Moving the blur onto a ::before decoration layer
     avoids that: .card stays filter-free, so position:fixed still means
     "relative to the viewport" for anything inside it. */
  body.theme-frosted-amber .card,
  body.theme-pastel-bloom .card {
    background: transparent;
    border: none;
    box-shadow: none;
    border-radius: 26px;
    isolation: isolate;
  }
  body.theme-frosted-amber .card::before,
  body.theme-pastel-bloom .card::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: var(--glass-panel-bg);
    backdrop-filter: blur(30px) saturate(170%);
    -webkit-backdrop-filter: blur(30px) saturate(170%);
    border: 1px solid var(--glass-panel-border);
    box-shadow: 0 20px 60px var(--glass-panel-shadow);
    pointer-events: none;
    z-index: -2;
  }
  body.theme-frosted-amber .card::after,
  body.theme-pastel-bloom .card::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: linear-gradient(135deg, var(--glass-sheen) 0%, transparent 32%, transparent 68%, var(--glass-sheen) 130%);
    opacity: 0.14;
    pointer-events: none;
    z-index: -1;
  }

  body.theme-frosted-amber .eyebrow, body.theme-pastel-bloom .eyebrow,
  body.theme-frosted-amber .back-link, body.theme-pastel-bloom .back-link,
  body.theme-frosted-amber .dict-letter, body.theme-pastel-bloom .dict-letter,
  body.theme-frosted-amber .number-num, body.theme-pastel-bloom .number-num,
  body.theme-frosted-amber .cloud-caret, body.theme-pastel-bloom .cloud-caret,
  body.theme-frosted-amber .chevron, body.theme-pastel-bloom .chevron,
  body.theme-frosted-amber .settings-section-label, body.theme-pastel-bloom .settings-section-label,
  body.theme-frosted-amber .quiz-motivation, body.theme-pastel-bloom .quiz-motivation,
  body.theme-frosted-amber .result-article-note, body.theme-pastel-bloom .result-article-note {
    color: var(--glass-accent);
  }
  body.theme-frosted-amber h1, body.theme-pastel-bloom h1,
  body.theme-frosted-amber .word, body.theme-pastel-bloom .word,
  body.theme-frosted-amber .dict-word, body.theme-pastel-bloom .dict-word,
  body.theme-frosted-amber .quiz-word-given, body.theme-pastel-bloom .quiz-word-given,
  body.theme-frosted-amber .settings-row-title, body.theme-pastel-bloom .settings-row-title,
  body.theme-frosted-amber .modal-box h2, body.theme-pastel-bloom .modal-box h2,
  body.theme-frosted-amber #quizScore, body.theme-pastel-bloom #quizScore,
  body.theme-frosted-amber .cloud-trigger.chosen .cloud-trigger-text,
  body.theme-pastel-bloom .cloud-trigger.chosen .cloud-trigger-text {
    color: var(--glass-text-primary);
  }
  body.theme-frosted-amber .word:hover, body.theme-frosted-amber .word:focus,
  body.theme-pastel-bloom .word:hover, body.theme-pastel-bloom .word:focus,
  body.theme-frosted-amber .dict-word:hover, body.theme-frosted-amber .dict-word:focus,
  body.theme-pastel-bloom .dict-word:hover, body.theme-pastel-bloom .dict-word:focus {
    color: var(--glass-accent);
  }
  body.theme-frosted-amber th, body.theme-pastel-bloom th,
  body.theme-frosted-amber .ipa, body.theme-pastel-bloom .ipa,
  body.theme-frosted-amber .note, body.theme-pastel-bloom .note,
  body.theme-frosted-amber .dict-ipa, body.theme-pastel-bloom .dict-ipa,
  body.theme-frosted-amber .dict-de, body.theme-pastel-bloom .dict-de,
  body.theme-frosted-amber .dict-empty, body.theme-pastel-bloom .dict-empty,
  body.theme-frosted-amber .quiz-num, body.theme-pastel-bloom .quiz-num,
  body.theme-frosted-amber .quiz-arrow, body.theme-pastel-bloom .quiz-arrow,
  body.theme-frosted-amber .quiz-retry-prompt, body.theme-pastel-bloom .quiz-retry-prompt,
  body.theme-frosted-amber .cloud-trigger-text, body.theme-pastel-bloom .cloud-trigger-text,
  body.theme-frosted-amber .settings-row-caption, body.theme-pastel-bloom .settings-row-caption,
  body.theme-frosted-amber .settings-hint, body.theme-pastel-bloom .settings-hint,
  body.theme-frosted-amber .app-version, body.theme-pastel-bloom .app-version,
  body.theme-frosted-amber .history-status, body.theme-pastel-bloom .history-status,
  body.theme-frosted-amber .modal-box p, body.theme-pastel-bloom .modal-box p,
  body.theme-frosted-amber .modal-cancel, body.theme-pastel-bloom .modal-cancel {
    color: var(--glass-text-muted);
  }
  body.theme-frosted-amber th, body.theme-pastel-bloom th,
  body.theme-frosted-amber td, body.theme-pastel-bloom td,
  body.theme-frosted-amber .quiz-item, body.theme-pastel-bloom .quiz-item,
  body.theme-frosted-amber .settings-row + .settings-row, body.theme-pastel-bloom .settings-row + .settings-row {
    border-color: var(--glass-panel-border);
  }

  /* Hamburger + dropdown */
  /* backdrop-filter combined directly with border-radius on the same element
     is a known Chromium/WebKit rendering bug: the blur doesn't respect the
     rounded clip, leaving a sharp square "leak" at each corner. Every
     blurred element below uses a ::before decoration layer instead (same
     fix already applied to .card) so the real element can stay border-
     radius-only and the ::before carries the filter. */
  /* Shadow lives on the ::before itself (same pattern as .card above), not
     as filter:drop-shadow() on this outer element - filter on an ancestor
     of a backdrop-filter descendant isolates that subtree's compositing
     layer, cutting the ::before's blur off from the real page content
     behind it and leaving a flat, barely-tinted panel instead of genuine
     frosted glass. An earlier "residual corner leak" fix added overflow:
     hidden + filter:drop-shadow here; that's what caused it. */
  body.theme-frosted-amber .hamburger, body.theme-pastel-bloom .hamburger {
    background: transparent;
    border: none;
    border-radius: 50%;
    width: 2.3rem; height: 2.3rem;
    color: var(--glass-text-primary);
    position: relative;
    isolation: isolate;
  }
  body.theme-frosted-amber .hamburger::before, body.theme-pastel-bloom .hamburger::before {
    content: '';
    position: absolute; inset: 0; border-radius: inherit;
    background: var(--glass-panel-bg);
    backdrop-filter: blur(16px) saturate(160%);
    -webkit-backdrop-filter: blur(16px) saturate(160%);
    border: 1px solid var(--glass-panel-border);
    box-shadow: 0 4px 14px var(--glass-panel-shadow), inset 0 1px 0 var(--glass-sheen);
    z-index: -1;
    pointer-events: none;
  }
  body.theme-frosted-amber .hamburger:hover::before, body.theme-pastel-bloom .hamburger:hover::before { background: var(--glass-chip-hover); }
  body.theme-frosted-amber .menu-dropdown, body.theme-pastel-bloom .menu-dropdown {
    background: transparent;
    border: none;
    border-radius: 14px;
    isolation: isolate;
  }
  body.theme-frosted-amber .menu-dropdown::before, body.theme-pastel-bloom .menu-dropdown::before {
    content: '';
    position: absolute; inset: 0; border-radius: inherit;
    background: var(--glass-modal-bg);
    backdrop-filter: blur(24px) saturate(170%);
    -webkit-backdrop-filter: blur(24px) saturate(170%);
    border: 1px solid var(--glass-panel-border);
    box-shadow: 0 16px 40px var(--glass-panel-shadow);
    z-index: -1;
    pointer-events: none;
  }
  body.theme-frosted-amber .menu-dropdown a, body.theme-pastel-bloom .menu-dropdown a { color: var(--glass-text-body); }
  body.theme-frosted-amber .menu-dropdown a:hover, body.theme-pastel-bloom .menu-dropdown a:hover { background: var(--glass-chip-bg); }
  body.theme-frosted-amber .menu-dropdown a.danger, body.theme-pastel-bloom .menu-dropdown a.danger { color: var(--glass-danger); }

  /* History nav pill */
  body.theme-frosted-amber .history-nav, body.theme-pastel-bloom .history-nav {
    background: transparent;
    border: none;
    border-radius: 999px;
    padding: 0.35rem 0.6rem;
    position: relative;
    isolation: isolate;
  }
  body.theme-frosted-amber .history-nav::before, body.theme-pastel-bloom .history-nav::before {
    content: '';
    position: absolute; inset: 0; border-radius: inherit;
    background: var(--glass-panel-bg);
    backdrop-filter: blur(20px) saturate(170%);
    -webkit-backdrop-filter: blur(20px) saturate(170%);
    border: 1px solid var(--glass-panel-border);
    box-shadow: 0 8px 22px var(--glass-panel-shadow), inset 0 1px 0 var(--glass-sheen);
    z-index: -1;
    pointer-events: none;
  }
  body.theme-frosted-amber .nav-button, body.theme-pastel-bloom .nav-button {
    background: transparent;
    border-color: transparent;
    color: var(--glass-accent);
  }
  @media (hover: hover) {
    body.theme-frosted-amber .nav-button:hover:not(:disabled), body.theme-pastel-bloom .nav-button:hover:not(:disabled) { background: var(--glass-chip-bg); }
  }
  body.theme-frosted-amber .nav-button-primary, body.theme-pastel-bloom .nav-button-primary {
    background: var(--glass-primary-bg);
    color: var(--glass-primary-text);
    border-radius: 999px;
    box-shadow: 0 6px 16px var(--glass-panel-shadow);
    position: relative;
    overflow: hidden;
    isolation: isolate;
  }
  body.theme-frosted-amber .nav-button-primary::before, body.theme-pastel-bloom .nav-button-primary::before {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(135deg, rgba(255,255,255,0.55) 0%, transparent 45%);
    z-index: -1;
  }
  @media (hover: hover) {
    body.theme-frosted-amber .nav-button-primary:hover:not(:disabled), body.theme-pastel-bloom .nav-button-primary:hover:not(:disabled) { background: var(--glass-primary-hover); }
  }

  /* Buttons */
  body.theme-frosted-amber .primary-button, body.theme-pastel-bloom .primary-button {
    background: var(--glass-primary-bg);
    color: var(--glass-primary-text);
  }
  body.theme-frosted-amber .primary-button:hover, body.theme-pastel-bloom .primary-button:hover { background: var(--glass-primary-hover); }
  body.theme-frosted-amber .secondary-button, body.theme-pastel-bloom .secondary-button {
    border-color: var(--glass-panel-border);
    color: var(--glass-accent);
  }
  body.theme-frosted-amber .secondary-button:hover, body.theme-pastel-bloom .secondary-button:hover { background: var(--glass-chip-bg); }

  /* Word cloud (Einfacher Modus) */
  body.theme-frosted-amber .cloud-trigger, body.theme-pastel-bloom .cloud-trigger { border-bottom-color: var(--glass-dash); }
  body.theme-frosted-amber .cloud-trigger:hover, body.theme-frosted-amber .cloud-trigger.open,
  body.theme-pastel-bloom .cloud-trigger:hover, body.theme-pastel-bloom .cloud-trigger.open { border-bottom-color: var(--glass-accent); }
  body.theme-frosted-amber .cloud-arrow, body.theme-pastel-bloom .cloud-arrow {
    background: var(--glass-modal-bg);
    border-color: var(--glass-panel-border);
  }
  body.theme-frosted-amber .word-cloud, body.theme-pastel-bloom .word-cloud {
    background: transparent;
    border: none;
    isolation: isolate;
  }
  body.theme-frosted-amber .word-cloud::before, body.theme-pastel-bloom .word-cloud::before {
    content: '';
    position: absolute; inset: 0; border-radius: inherit;
    background: var(--glass-modal-bg);
    backdrop-filter: blur(24px) saturate(170%);
    -webkit-backdrop-filter: blur(24px) saturate(170%);
    border: 1px solid var(--glass-panel-border);
    box-shadow: 0 16px 40px var(--glass-panel-shadow);
    z-index: -1;
    pointer-events: none;
  }
  body.theme-frosted-amber .cloud-chip, body.theme-pastel-bloom .cloud-chip {
    color: var(--glass-text-body);
    background: var(--glass-chip-bg);
    border-color: var(--glass-panel-border);
  }
  body.theme-frosted-amber .cloud-chip:hover, body.theme-pastel-bloom .cloud-chip:hover {
    background: var(--glass-chip-hover);
    border-color: var(--glass-accent);
  }

  /* Verb conjugation popup - same glass-panel technique as .word-cloud above */
  body.theme-frosted-amber .conjugation-arrow, body.theme-pastel-bloom .conjugation-arrow {
    background: var(--glass-modal-bg);
    border-color: var(--glass-panel-border);
  }
  body.theme-frosted-amber .conjugation-popup, body.theme-pastel-bloom .conjugation-popup {
    background: transparent;
    border: none;
    isolation: isolate;
  }
  body.theme-frosted-amber .conjugation-popup::before, body.theme-pastel-bloom .conjugation-popup::before {
    content: '';
    position: absolute; inset: 0; border-radius: inherit;
    background: var(--glass-modal-bg);
    backdrop-filter: blur(24px) saturate(170%);
    -webkit-backdrop-filter: blur(24px) saturate(170%);
    border: 1px solid var(--glass-panel-border);
    box-shadow: 0 16px 40px var(--glass-panel-shadow);
    z-index: -1;
    pointer-events: none;
  }
  body.theme-frosted-amber .conjugation-head, body.theme-pastel-bloom .conjugation-head {
    color: var(--glass-text-primary);
    border-bottom-color: var(--glass-panel-border);
  }
  body.theme-frosted-amber .conjugation-gloss, body.theme-pastel-bloom .conjugation-gloss,
  body.theme-frosted-amber .conjugation-note, body.theme-pastel-bloom .conjugation-note,
  body.theme-frosted-amber .conjugation-pronoun, body.theme-pastel-bloom .conjugation-pronoun {
    color: var(--glass-text-muted);
  }
  body.theme-frosted-amber .conjugation-form, body.theme-pastel-bloom .conjugation-form { color: var(--glass-text-primary); }
  body.theme-frosted-amber .conjugation-form:hover, body.theme-pastel-bloom .conjugation-form:hover { color: var(--glass-accent); }

  body.theme-frosted-amber .dash-input, body.theme-pastel-bloom .dash-input { border-bottom-color: var(--glass-dash); color: var(--glass-text-body); }
  body.theme-frosted-amber .dash-input:focus, body.theme-pastel-bloom .dash-input:focus { border-bottom-color: var(--glass-accent); }

  /* Dictionary search bar - same glass-panel technique as .word-cloud above */
  body.theme-frosted-amber .dict-search-wrap, body.theme-pastel-bloom .dict-search-wrap {
    position: relative;
    background: transparent;
    border: none;
    isolation: isolate;
  }
  body.theme-frosted-amber .dict-search-wrap::before, body.theme-pastel-bloom .dict-search-wrap::before {
    content: '';
    position: absolute; inset: 0; border-radius: inherit;
    background: var(--glass-panel-bg);
    backdrop-filter: blur(20px) saturate(170%);
    -webkit-backdrop-filter: blur(20px) saturate(170%);
    border: 1px solid var(--glass-panel-border);
    z-index: -1;
    pointer-events: none;
  }
  body.theme-frosted-amber .dict-search-icon, body.theme-pastel-bloom .dict-search-icon { color: var(--glass-accent); }
  body.theme-frosted-amber .dict-search-input, body.theme-pastel-bloom .dict-search-input { color: var(--glass-text-body); }
  body.theme-frosted-amber .dict-search-input::placeholder, body.theme-pastel-bloom .dict-search-input::placeholder { color: var(--glass-text-muted); }
  body.theme-frosted-amber .dict-search-clear, body.theme-pastel-bloom .dict-search-clear {
    background: var(--glass-chip-bg);
    color: var(--glass-text-muted);
  }
  body.theme-frosted-amber .dict-search-clear:hover, body.theme-pastel-bloom .dict-search-clear:hover {
    background: var(--glass-chip-hover);
    color: var(--glass-text-primary);
  }
  body.theme-frosted-amber .dict-conjugate-btn, body.theme-pastel-bloom .dict-conjugate-btn {
    background: var(--glass-chip-bg);
    color: var(--glass-accent);
  }
  body.theme-frosted-amber .dict-conjugate-btn:hover, body.theme-frosted-amber .dict-conjugate-btn.open,
  body.theme-pastel-bloom .dict-conjugate-btn:hover, body.theme-pastel-bloom .dict-conjugate-btn.open {
    background: var(--glass-chip-hover);
  }
  body.theme-frosted-amber .dict-headword, body.theme-pastel-bloom .dict-headword { color: var(--glass-text-primary); }
  body.theme-frosted-amber .dict-word.dict-word-gloss, body.theme-pastel-bloom .dict-word.dict-word-gloss { color: var(--glass-text-muted); }
  body.theme-frosted-amber .dict-word.dict-word-gloss:hover, body.theme-frosted-amber .dict-word.dict-word-gloss:focus,
  body.theme-pastel-bloom .dict-word.dict-word-gloss:hover, body.theme-pastel-bloom .dict-word.dict-word-gloss:focus {
    color: var(--glass-accent);
  }

  /* Direction switch + word-type filter: same glass-chip treatment as
     .dict-conjugate-btn/.dict-search-clear above. */
  body.theme-frosted-amber .dict-direction-switch, body.theme-pastel-bloom .dict-direction-switch {
    border: 1px solid var(--glass-panel-border);
    background: var(--glass-chip-bg);
    color: var(--glass-accent);
  }
  body.theme-frosted-amber .dict-direction-switch:hover, body.theme-pastel-bloom .dict-direction-switch:hover {
    background: var(--glass-chip-hover);
  }
  body.theme-frosted-amber .dict-filter-btn, body.theme-pastel-bloom .dict-filter-btn {
    border: 1px solid var(--glass-panel-border);
    background: var(--glass-chip-bg);
    color: var(--glass-text-muted);
  }
  body.theme-frosted-amber .dict-filter-btn[aria-expanded="true"], body.theme-pastel-bloom .dict-filter-btn[aria-expanded="true"] {
    background: var(--glass-chip-hover);
    color: var(--glass-accent);
    border-color: transparent;
  }
  body.theme-frosted-amber .dict-filter-badge, body.theme-pastel-bloom .dict-filter-badge {
    background: var(--glass-accent);
    border-color: var(--glass-bg);
  }
  body.theme-frosted-amber .dict-filter-popup, body.theme-pastel-bloom .dict-filter-popup {
    position: relative;
    background: transparent;
    border: none;
    box-shadow: none;
    isolation: isolate;
  }
  body.theme-frosted-amber .dict-filter-popup::before, body.theme-pastel-bloom .dict-filter-popup::before {
    content: '';
    position: absolute; inset: 0; border-radius: inherit;
    background: var(--glass-panel-bg);
    backdrop-filter: blur(20px) saturate(170%);
    -webkit-backdrop-filter: blur(20px) saturate(170%);
    border: 1px solid var(--glass-panel-border);
    box-shadow: 0 20px 40px var(--glass-panel-shadow);
    z-index: -1;
    pointer-events: none;
  }
  body.theme-frosted-amber .dict-filter-title, body.theme-pastel-bloom .dict-filter-title,
  body.theme-frosted-amber .dict-filter-count, body.theme-pastel-bloom .dict-filter-count {
    color: var(--glass-text-muted);
  }
  body.theme-frosted-amber .dict-filter-option, body.theme-pastel-bloom .dict-filter-option { color: var(--glass-text-primary); }
  body.theme-frosted-amber .dict-filter-option input, body.theme-pastel-bloom .dict-filter-option input { accent-color: var(--glass-accent); }
  body.theme-frosted-amber .dict-filter-reset, body.theme-pastel-bloom .dict-filter-reset {
    color: var(--glass-accent);
    border-top-color: var(--glass-panel-border);
  }
  body.theme-frosted-amber .dict-filter-learned-toggle, body.theme-pastel-bloom .dict-filter-learned-toggle {
    border-bottom-color: var(--glass-panel-border);
  }

  body.theme-frosted-amber .reference-toggle-btn, body.theme-pastel-bloom .reference-toggle-btn {
    background: var(--glass-chip-bg);
    border-color: var(--glass-panel-border);
    color: var(--glass-accent);
  }
  body.theme-frosted-amber .reference-toggle-btn:hover, body.theme-pastel-bloom .reference-toggle-btn:hover {
    background: var(--glass-chip-hover);
  }
  body.theme-frosted-amber .reference-toggle-btn.active, body.theme-pastel-bloom .reference-toggle-btn.active {
    background: var(--glass-primary-bg);
    color: var(--glass-primary-text);
    border-color: transparent;
  }

  /* Quiz results */
  body.theme-frosted-amber .result-mark.ok, body.theme-pastel-bloom .result-mark.ok,
  body.theme-frosted-amber .result-correct-word, body.theme-pastel-bloom .result-correct-word,
  body.theme-frosted-amber .result-plain, body.theme-pastel-bloom .result-plain {
    color: var(--glass-success);
  }
  body.theme-frosted-amber .result-mark.no, body.theme-pastel-bloom .result-mark.no,
  body.theme-frosted-amber .result-wrong-word, body.theme-pastel-bloom .result-wrong-word {
    color: var(--glass-danger);
  }
  body.theme-frosted-amber .mode-badge, body.theme-pastel-bloom .mode-badge {
    background: var(--glass-primary-bg);
    color: var(--glass-primary-text);
  }

  /* Settings page */
  body.theme-frosted-amber .settings-section-label.danger, body.theme-pastel-bloom .settings-section-label.danger,
  body.theme-frosted-amber .action-row.danger .settings-row-title, body.theme-pastel-bloom .action-row.danger .settings-row-title,
  body.theme-frosted-amber .action-row.danger .chevron, body.theme-pastel-bloom .action-row.danger .chevron {
    color: var(--glass-danger);
  }
  body.theme-frosted-amber .settings-section, body.theme-pastel-bloom .settings-section {
    background: var(--glass-panel-bg-soft);
    border-color: var(--glass-panel-border);
  }
  body.theme-frosted-amber button.action-row:hover, body.theme-pastel-bloom button.action-row:hover { background: var(--glass-chip-bg); }
  body.theme-frosted-amber .action-row.danger:hover, body.theme-pastel-bloom .action-row.danger:hover {
    background: var(--glass-danger-tint);
  }
  body.theme-frosted-amber .toggle-track, body.theme-pastel-bloom .toggle-track { background: var(--glass-toggle-track-off); }
  body.theme-frosted-amber .toggle-track::before, body.theme-pastel-bloom .toggle-track::before { background: var(--glass-toggle-knob); }
  body.theme-frosted-amber .toggle-switch input:checked + .toggle-track,
  body.theme-pastel-bloom .toggle-switch input:checked + .toggle-track { background: var(--glass-toggle-track-on); }

  /* Modals (shared by all 5 confirmation dialogs) */
  body.theme-frosted-amber .modal-overlay, body.theme-pastel-bloom .modal-overlay { background: var(--glass-overlay-dim); }
  body.theme-frosted-amber .modal-box, body.theme-pastel-bloom .modal-box {
    background: transparent;
    border: none;
    border-radius: 20px;
    position: relative;
    isolation: isolate;
  }
  body.theme-frosted-amber .modal-box::before, body.theme-pastel-bloom .modal-box::before {
    content: '';
    position: absolute; inset: 0; border-radius: inherit;
    background: var(--glass-modal-bg);
    backdrop-filter: blur(26px) saturate(170%);
    -webkit-backdrop-filter: blur(26px) saturate(170%);
    border: 1px solid var(--glass-panel-border);
    box-shadow: 0 20px 50px var(--glass-panel-shadow);
    z-index: -1;
    pointer-events: none;
  }
  body.theme-frosted-amber .modal-cancel, body.theme-pastel-bloom .modal-cancel { border-color: var(--glass-panel-border) !important; }
  body.theme-frosted-amber .modal-cancel:hover, body.theme-pastel-bloom .modal-cancel:hover { background: var(--glass-chip-bg); }
  body.theme-frosted-amber .modal-confirm, body.theme-pastel-bloom .modal-confirm { background: var(--glass-danger); color: var(--glass-primary-text); }
  body.theme-frosted-amber .modal-confirm:hover, body.theme-pastel-bloom .modal-confirm:hover { background: var(--glass-danger-hover); }
  body.theme-frosted-amber .modal-confirm-neutral, body.theme-pastel-bloom .modal-confirm-neutral { background: var(--glass-primary-bg); color: var(--glass-primary-text); }
  body.theme-frosted-amber .modal-confirm-neutral:hover, body.theme-pastel-bloom .modal-confirm-neutral:hover { background: var(--glass-primary-hover); }

  /* =====================================================================
     Material Design theme: additive overrides only, scoped under
     body.theme-material. Separate --md-* token namespace and its own rule
     blocks (not merged into the Glas-Design pairing above) - Material
     renders via flat tonal surfaces (a contrasting fill, no shadow) rather
     than translucent backdrop-filter blur, and its palette is computed at
     runtime from the OS accent color (see applyMaterialColorFromSystem()/
     applyMaterialPalette() in index.html) rather than a fixed hex, so the
     two families share no technique worth reusing.
     ===================================================================== */

  .md-nav { display: none; }
  /* Same reasoning as .md-nav above - both live at body level (see
     index.html) so they're present regardless of theme, and only
     body.theme-material's own rules (further down / the 1240px section at
     the end of this file) turn this back on. */
  .md-history-panel { display: none; }

  body.theme-material {
    /* Fallback tokens (amber hue 30) - overwritten inline by
       applyMaterialPalette() once the OS accent color has been read (or
       immediately, as the deliberate fallback, if the browser doesn't
       expose one). Only visible for the brief instant before that JS runs
       on first activation. */
    --md-primary: hsl(30, 46%, 36%);
    --md-primary-dark: hsl(30, 50%, 24%);
    --md-primary-container: hsl(30, 58%, 87%);
    --md-on-primary-container: hsl(30, 45%, 15%);
    --md-secondary-container: hsl(30, 24%, 87%);
    --md-on-secondary-container: hsl(30, 20%, 18%);
    --md-tertiary-container: hsl(90, 42%, 87%);
    --md-on-tertiary-container: hsl(90, 35%, 15%);
    --md-surface: hsl(30, 18%, 98%);
    --md-surface1: hsl(30, 16%, 95%);
    --md-surface2: hsl(30, 16%, 91%);
    --md-surface3: hsl(30, 16%, 87%);
    --md-on-surface: hsl(30, 12%, 14%);
    --md-on-surface-variant: hsl(30, 10%, 33%);
    --md-outline: hsl(30, 9%, 50%);
    --md-outline-variant: hsl(30, 15%, 83%);

    background: var(--md-surface1);
    color: var(--md-on-surface);
    font-family: -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
    padding: 0 0 4.5rem;
    /* scroll-padding-bottom for Conversations' autoscroll (so a scrolled-to
       bubble doesn't end up under the fixed nav bar) is NOT set here - the
       actual scrolling box on this page is <html> (document.scrollingElement),
       not <body>, so a rule scoped to body.theme-material has no effect on
       it (confirmed: computed scroll-padding-bottom stayed "auto" on <html>
       even with this declared here). Set via JS instead, on <html> itself,
       alongside the theme class - see applyDesignThemeClass() in index.html. */
    /* The base body rule's min-height:100vh is calculated against the
       viewport with the address bar hidden, not however much is actually
       visible right now - on mobile Chrome with the bar showing, that
       silently reserves more height than fits, and Material's larger
       bottom padding (4.5rem, for the nav bar, vs. 2rem for the other
       themes) is just enough to tip that into a real, visible phantom
       scroll on a card that doesn't otherwise need one. dvh tracks the
       actually-visible viewport instead; kept vh first as a fallback for
       browsers that don't support dvh (unsupported values are ignored,
       so they simply keep the first declaration). */
    min-height: 100vh;
    min-height: 100dvh;
    /* Defends the fixed nav bar (left:0;right:0) against two separate
       glitches, both ultimately about the viewport-width/height the
       browser hands to position:fixed drifting briefly out from under it:
       1) overflow-x:hidden - re-rendering the vocab table on "Neue Wörter"
          can, for one paint, make document.documentElement.scrollWidth
          exceed the true viewport width by a few px (observed, without any
          single element individually overflowing - most likely a momentary
          scrollbar-driven layout-width fluctuation) - during that window,
          .md-nav's right:0 was resolving against the wider scrollWidth
          instead of the viewport, visibly nudging it toward the bottom-right
          corner. With no horizontal overflow possible at all, this can't happen.
       2) overscroll-behavior-y:none - stops the mobile rubber-band bounce
          past the top/bottom of a page that's shorter than the viewport,
          which could drag the sticky hero out of view along with it even
          though the page has nothing there to legitimately scroll to. */
    overflow-x: hidden;
    overscroll-behavior-y: none;
  }
  @media (min-width: 900px) {
    body.theme-material { padding: 0 0 0 5.5rem; }
  }

  /* ---- Card shell: just sizes/centers the view now - zero padding of its
     own. Both .header-row (the hero) and .md-body (everything below it,
     see next block) are full-width direct children that supply their own
     insets, so they naturally sit flush with .card's true edges with no
     bleed math needed anywhere. max-width is desktop-only (see the rail
     breakpoint below) - below that, the card stretches edge to edge same
     as a narrow phone would, instead of getting stranded at a constrained
     width once the nav has already dropped to the mobile bottom-bar. */
  body.theme-material .card {
    /* Explicitly cancels the base (classic-theme) .card/.card.wide
       max-width (480px/780px) - those apply to every theme by default, so
       simply not re-declaring a Material-specific max-width here still
       left the base one in effect below 900px, constraining the card and
       leaving exactly the kind of side gap this rule exists to prevent. */
    max-width: none;
    background: none;
    border: none;
    box-shadow: none;
    border-radius: 0;
    padding: 0;
  }
  @media (min-width: 900px) {
    body.theme-material .card { max-width: 560px; }
    body.theme-material .card.wide { max-width: 640px; }
  }

  /* ---- Hero bar: restyles the existing .header-row, no new markup - a
     slim solid-color banner, not a big rounded panel ---- */
  body.theme-material .header-row {
    /* Stays put while the content below it scrolls, like a real app bar -
       sticky (not fixed) so it still respects .card's own horizontal
       bounds on desktop instead of needing to know the rail's width.
       overflow:hidden is deliberately NOT set here at the base/mobile
       width - see the >=900px block below for why it's only needed
       there (border-radius is 0 on mobile, nothing to clip) and why
       having it here broke the 3-dot menu on iOS Safari. */
    position: sticky;
    top: 0;
    z-index: 5;
    align-items: flex-end;
    height: 62px;
    margin: 0 0 1.1rem;
    padding: 0 1.1rem 0.5rem;
    border-radius: 0;
    background: linear-gradient(135deg, var(--md-primary) 0%, var(--md-primary-dark) 100%);
  }
  body.theme-material .header-row::before {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(0,0,0,0.08) 0%, rgba(0,0,0,0.22) 100%);
    pointer-events: none;
  }
  body.theme-material .header-row > div { position: relative; z-index: 1; min-width: 0; }
  body.theme-material .header-row .eyebrow { color: rgba(255,255,255,0.85); }
  body.theme-material .header-row h1 { color: #fff; font-weight: 500; font-size: 1.08rem; margin-bottom: 0; }
  @media (min-width: 900px) {
    body.theme-material .header-row {
      height: 52px;
      /* No bottom margin here (unlike the mobile 1.1rem gap): on desktop
         .header-row's border and .md-body's border below need to touch
         directly to read as one continuous frame - a gap between them
         would leave the two rounded halves visibly disconnected. .md-body
         supplies its own top padding instead, so the content inside still
         gets breathing room without breaking the frame's seam. */
      margin: 1.2rem 0 0;
      padding: 0 1.4rem 0.4rem;
      border: 1px solid var(--md-outline-variant);
      border-bottom: none;
      border-radius: 5px 5px 0 0;
      /* Only needed here (border-radius is 0, nothing to clip, on
         mobile) - clips .header-row::before's gradient overlay to these
         rounded corners. The 3-dot menu's .menu-dropdown (position:
         fixed) doesn't exist at this width (.menu-wrapper is hidden
         >=900px, see below), so there's nothing for this to break here. */
      overflow: hidden;
    }
    body.theme-material .header-row .eyebrow { font-size: 0.68rem; }
    body.theme-material .header-row h1 { font-size: 0.92rem; }
  }

  /* ---- .md-body wraps everything below the hero (see index.html) - a
     normal in-flow sibling of .header-row, so its top edge lands exactly
     where the hero ends purely through document flow, with no hardcoded
     offset to keep in sync if either one's height or spacing ever changes.
     Its own border/radius supplies the bottom half of the "continues from
     the hero" frame on desktop; .header-row supplies the top half. */
  body.theme-material .md-body {
    padding: 0 1rem 1.5rem;
  }
  @media (min-width: 900px) {
    body.theme-material .md-body {
      /* Restores the breathing room .header-row's margin-bottom would
         otherwise have provided (removed above so the frame seam is
         seamless) - as padding instead of margin so it's INSIDE the
         border rather than a gap before it. */
      padding-top: 1.1rem;
      border: 1px solid var(--md-outline-variant);
      border-radius: 0 0 5px 5px;
    }
  }


  /* ---- Classic navigation: the always-visible .md-nav replaces it for
     everything except Einstellungen, which the bottom-nav (mobile) has no
     spare slot for without crowding - reused here as a genuine overflow
     menu (3-dot button, dropdown reduced to just the one entry) rather
     than duplicating a second dropdown implementation. On the desktop
     rail there's room for a normal Einstellungen destination instead, so
     this whole thing goes back to being fully hidden there - see the
     900px block below. ---- */
  body.theme-material .back-link { display: none; }
  body.theme-material .menu-wrapper { position: relative; flex-shrink: 0; }
  body.theme-material .hamburger {
    font-size: 0; /* collapses the "☰" text node - replaced by the ::after below */
    width: 2.2rem;
    height: 2.2rem;
    border-radius: 999px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(255,255,255,0.16);
    color: #fff;
  }
  body.theme-material .hamburger::after { content: '⋮'; font-size: 1.35rem; line-height: 1; }
  body.theme-material .hamburger:hover { background: rgba(255,255,255,0.26); }
  body.theme-material .menu-dropdown {
    /* fixed, not absolute: this only actually renders <900px (see
       .menu-wrapper's visibility below), and .header-row deliberately
       has NO overflow:hidden at that width (moved into the >=900px
       block above) specifically so this fixed-position dropdown isn't a
       descendant of an overflow:hidden ancestor at all - iOS Safari has
       a real bug where a position:fixed element can still get clipped/
       mis-stacked by an overflow:hidden + stacking-context ancestor
       (here: .header-row's position:sticky + z-index) even though the
       CSS spec says it shouldn't be, since fixed positioning escapes the
       ancestor's containing block when nothing in the chain sets
       transform/filter/will-change (confirmed - Chrome always rendered
       this fine, only Safari/iOS showed the popup vanishing behind other
       content). Values below match the 3-dot button's actual mobile
       position; irrelevant above 900px since .menu-wrapper is hidden
       there. */
    position: fixed;
    top: 3.7rem;
    right: 1rem;
    background: var(--md-surface);
    border: none;
    border-radius: 14px;
    box-shadow: 0 8px 24px rgba(0,0,0,0.28);
    min-width: 190px;
  }
  body.theme-material .menu-dropdown a { color: var(--md-on-surface); }
  body.theme-material .menu-dropdown a:hover { background: rgba(0,0,0,0.055); }
  /* Every other link (Training, Wörterbuch, Zahlwörter, ...) already has
     its own slot in the bottom nav - repeating them here would be
     redundant, so only Einstellungen and Hilfe (destinations WITHOUT a
     bottom-nav slot) stay visible in this reduced menu. */
  body.theme-material .menu-dropdown a:not([href="#einstellungen"]):not([href="#hilfe"]) { display: none; }
  /* Frees the slot the 3-dot menu now covers for Einstellungen/Hilfe. */
  body.theme-material .md-nav-item[data-hash="#einstellungen"] { display: none; }
  body.theme-material .md-nav-item[data-hash="#hilfe"] { display: none; }

  /* ---- Bottom-nav (mobile) / rail (desktop, matches the >=900px breakpoint used elsewhere in the project) ---- */
  body.theme-material .md-nav {
    display: flex;
    position: fixed;
    z-index: 40;
    left: 0;
    right: 0;
    bottom: 0;
    background: var(--md-surface1);
    box-shadow: 0 -1px 3px rgba(0,0,0,0.12);
    justify-content: space-around;
    align-items: stretch;
    overflow-x: auto;
    padding: 0.4rem 0.5rem calc(0.4rem + env(safe-area-inset-bottom, 0px));
    gap: 0.25rem;
  }
  body.theme-material .md-nav-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.1rem;
    /* Equal-share flex (not a fixed min-width) so all 6 destinations always
       divide up whatever width is available and never need the .md-nav's
       overflow-x:auto fallback on narrow phones - they just get narrower
       together instead of forcing a scrollbar. */
    flex: 1 1 0;
    min-width: 0;
    padding: 0.3rem 0.15rem 0.25rem;
    background: transparent;
    border: none;
    border-radius: 16px;
    color: var(--md-on-surface-variant);
    font-family: inherit;
    cursor: pointer;
    position: relative;
    overflow: hidden;
    transition: background 0.15s ease, color 0.15s ease;
  }
  body.theme-material .md-nav-item:hover { background: rgba(0,0,0,0.05); }
  body.theme-material .md-nav-item.active { color: var(--md-on-surface); }
  body.theme-material .md-nav-icon {
    width: 2.2rem;
    height: 1.6rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    transition: background 0.15s ease;
  }
  body.theme-material .md-nav-item.active .md-nav-icon { background: var(--md-secondary-container); color: var(--md-on-secondary-container); }
  body.theme-material .md-nav-icon svg {
    width: 1.4rem;
    height: 1.4rem;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
  }
  body.theme-material .md-nav-label {
    font-size: 0.66rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  @media (min-width: 900px) {
    body.theme-material .md-nav {
      left: 0;
      right: auto;
      top: 0;
      bottom: 0;
      flex-direction: column;
      justify-content: flex-start;
      align-items: stretch;
      width: 5.5rem;
      padding: 1.5rem 0.5rem;
      gap: 0.6rem;
      overflow-x: visible;
      overflow-y: auto;
      box-shadow: none;
    }
    /* Rail has room for Einstellungen and Hilfe as normal destinations -
       the mobile-only 3-dot overflow menu goes back to being fully
       hidden, same as every other theme. */
    body.theme-material .md-nav-item[data-hash="#einstellungen"] { display: flex; }
    body.theme-material .md-nav-item[data-hash="#hilfe"] { display: flex; }
    body.theme-material .menu-wrapper { display: none; }
    body.theme-material .md-nav-item {
      /* Rail items stack by content height (column direction) - equal-share
         growth would otherwise stretch every item to 1/6th of the full
         sidebar height, which is only correct for the mobile bottom-nav. */
      flex: 0 0 auto;
      gap: 0.15rem;
      padding: 0.5rem 0.4rem;
    }
    body.theme-material .md-nav-icon { width: 2rem; height: 1.5rem; }
    body.theme-material .md-nav-icon svg { width: 1.35rem; height: 1.35rem; }
    body.theme-material .md-nav-label {
      /* The rail has room to wrap a long label ("Einstellungen") onto a
         second line instead of truncating it - only the cramped mobile
         bottom-nav needs the single-line ellipsis treatment. */
      font-size: 0.62rem;
      max-width: none;
      overflow: visible;
      text-overflow: clip;
      white-space: normal;
      text-align: center;
    }
  }
  /* Only meaningful once the rail widens into a full drawer (see the
     1240px "expanded" section at the end of this file) - a bare icon rail
     has no room for it and no need for one. */
  body.theme-material .md-nav-brand { display: none; }

  /* ---- Vocabulary table (Training view): a flat tonal surface (contrasting
     fill against the page, no shadow), like the mockup's .card/.md-table ---- */
  body.theme-material table {
    background: var(--md-surface2);
    border-radius: 20px;
    overflow: hidden;
    border-collapse: separate;
    border-spacing: 0;
  }
  body.theme-material th { color: var(--md-on-surface-variant); font-weight: 600; padding: 0.7rem 1.1rem 0.5rem; border-bottom: 1px solid var(--md-outline-variant); }
  body.theme-material td { padding: 0.65rem 1.1rem; border-bottom: 1px solid var(--md-outline-variant); font-size: 0.92rem; }
  body.theme-material tbody tr:last-child td { border-bottom: none; }
  /* Body copy reads noticeably smaller under Material than the other themes
     at the exact same rem sizes - the system sans-serif font stack here has
     a smaller apparent x-height than IBM Plex Mono/Space Grotesk, which the
     rest of the app is built around. Bumped back up per-element (rather
     than scaling the root font-size) so nav/button sizing tuned in rem
     units - like the mobile bottom-nav's exact 6-item fit - isn't affected.
     Matched exactly to the dictionary's equivalent roles (.dict-word/
     .dict-ipa/.dict-de) so the same word reads the same size in both
     places - td's own 0.92rem above already matches .dict-word/.dict-de
     (both inherit .dict-entry's 0.92rem), .ipa below matches .dict-ipa. */
  body.theme-material .word { color: var(--md-on-surface); }
  body.theme-material .word:hover, body.theme-material .word:focus { color: var(--md-primary); }
  body.theme-material .ipa { color: var(--md-on-surface-variant); font-size: 0.86rem; }
  body.theme-material .note { color: var(--md-on-surface-variant); font-size: 0.82rem; }

  /* ---- Dictionary / Zahlwörter / Ordinalzahlen reference views - same tonal-surface treatment as the table ---- */
  body.theme-material .dict-columns, body.theme-material .numbers-columns {
    background: var(--md-surface2);
    border-radius: 20px;
    padding: 1rem 1.25rem;
  }
  body.theme-material .dict-letter { color: var(--md-primary); border-bottom-color: var(--md-outline-variant); }
  body.theme-material .dict-entry { font-size: 0.92rem; }
  body.theme-material .dict-word { color: var(--md-on-surface); }
  body.theme-material .dict-word:hover, body.theme-material .dict-word:focus { color: var(--md-primary); }
  body.theme-material .dict-word.dict-word-gloss { color: var(--md-on-surface-variant); }
  body.theme-material .dict-word.dict-word-gloss:hover, body.theme-material .dict-word.dict-word-gloss:focus { color: var(--md-primary); }
  body.theme-material .dict-ipa { color: var(--md-on-surface-variant); font-size: 0.86rem; }
  body.theme-material .dict-de { color: var(--md-on-surface-variant); }
  body.theme-material .dict-empty { color: var(--md-on-surface-variant); font-size: 0.92rem; }
  body.theme-material .number-entry { font-size: 0.92rem; }
  body.theme-material .number-num { color: var(--md-primary); }

  /* Reference-view toggle: a Material "segmented buttons" style pill pair */
  body.theme-material .reference-toggle {
    background: var(--md-surface2);
    border-radius: 999px;
    padding: 0.3rem;
    gap: 0.3rem;
    margin-bottom: 1.1rem;
  }
  body.theme-material .reference-toggle-btn {
    background: none;
    border: none;
    border-radius: 999px;
    color: var(--md-on-surface-variant);
    font-family: inherit;
    font-weight: 600;
    font-size: 0.85rem;
    padding: 0.5rem;
  }
  body.theme-material .reference-toggle-btn.active {
    background: var(--md-secondary-container);
    color: var(--md-on-secondary-container);
  }

  /* Dictionary search bar - a pill-shaped tonal field, matching Material's own search-bar convention */
  body.theme-material .dict-search-wrap {
    background: var(--md-surface2);
    border: none;
    border-radius: 999px;
  }
  body.theme-material .dict-search-icon { color: var(--md-on-surface-variant); }
  body.theme-material .dict-search-input { color: var(--md-on-surface); font-size: 0.92rem; }
  body.theme-material .dict-search-input::placeholder { color: var(--md-on-surface-variant); }
  body.theme-material .dict-search-clear { background: var(--md-surface3); color: var(--md-on-surface-variant); }
  body.theme-material .dict-search-clear:hover { background: var(--md-secondary-container); color: var(--md-on-secondary-container); }
  body.theme-material .dict-conjugate-btn { background: var(--md-secondary-container); color: var(--md-on-secondary-container); }
  body.theme-material .dict-conjugate-btn:hover, body.theme-material .dict-conjugate-btn.open { background: var(--md-primary-container); color: var(--md-on-primary-container); }
  body.theme-material .dict-headword { color: var(--md-on-surface); }

  /* Direction switch + word-type filter: same tonal-pill convention as the
     search bar above (border-radius: 999px, not the 12px classic uses). */
  body.theme-material .dict-direction-switch {
    border: 1px solid var(--md-outline);
    border-radius: 999px;
    background: var(--md-secondary-container);
    color: var(--md-on-secondary-container);
  }
  body.theme-material .dict-direction-switch:hover { background: var(--md-primary-container); }
  body.theme-material .dict-filter-btn {
    border: 1px solid var(--md-outline);
    border-radius: 999px;
    background: var(--md-surface2);
    color: var(--md-on-surface-variant);
  }
  body.theme-material .dict-filter-btn[aria-expanded="true"] {
    background: var(--md-secondary-container);
    color: var(--md-on-secondary-container);
    border-color: transparent;
  }
  body.theme-material .dict-filter-badge { background: var(--md-primary); border-color: var(--md-surface1); }
  body.theme-material .dict-filter-popup {
    background: var(--md-surface1);
    border-color: var(--md-outline-variant);
  }
  body.theme-material .dict-filter-title { color: var(--md-on-surface-variant); }
  body.theme-material .dict-filter-option { color: var(--md-on-surface); }
  body.theme-material .dict-filter-option input { accent-color: var(--md-primary); }
  body.theme-material .dict-filter-count { color: var(--md-on-surface-variant); }
  body.theme-material .dict-filter-reset { color: var(--md-primary); border-top-color: var(--md-outline-variant); }
  body.theme-material .dict-filter-learned-toggle { border-bottom-color: var(--md-outline-variant); }

  /* ---- History nav: tonal icon buttons + a status chip, like the mockup's .icon-btn-tonal/.chip ---- */
  body.theme-material .nav-button {
    border: none;
    background: var(--md-secondary-container);
    color: var(--md-on-secondary-container);
    border-radius: 12px;
    width: 2.5rem;
    min-width: 2.5rem;
    height: 2.5rem;
    padding: 0;
  }
  @media (hover: hover) {
    body.theme-material .nav-button:hover:not(:disabled) { background: var(--md-primary-container); color: var(--md-on-primary-container); }
  }
  body.theme-material .nav-button-primary {
    background: var(--md-primary-container);
    color: var(--md-on-primary-container);
    border-color: transparent;
  }
  body.theme-material .history-status {
    flex: 1;
    background: var(--md-surface1);
    border-radius: 999px;
    padding: 0.5rem 1rem;
    text-align: center;
    color: var(--md-on-surface-variant);
  }

  /* ---- Quiz view ---- */
  body.theme-material .mode-badge { background: var(--md-tertiary-container); color: var(--md-on-tertiary-container); }
  body.theme-material #quizBody {
    background: var(--md-surface2);
    border-radius: 20px;
    padding: 0.2rem 1.1rem;
    margin-bottom: 1.1rem;
  }
  body.theme-material .quiz-item { border-bottom-color: var(--md-outline-variant); }
  body.theme-material .quiz-item:last-child { border-bottom: none; }
  body.theme-material .quiz-de, body.theme-material .quiz-es { font-size: 0.92rem; }
  body.theme-material .quiz-num { color: var(--md-on-surface-variant); font-size: 0.85rem; }
  body.theme-material .quiz-word-given { color: var(--md-on-surface); }
  body.theme-material .quiz-arrow { color: var(--md-on-surface-variant); font-size: 0.92rem; }
  body.theme-material .dash-input { border-bottom-color: var(--md-outline); color: var(--md-on-surface); font-size: 0.92rem; }
  body.theme-material .dash-input:focus { border-bottom-color: var(--md-primary); }
  body.theme-material .dash-input::placeholder { color: var(--md-on-surface-variant); }

  body.theme-material .cloud-trigger { border-bottom-color: var(--md-outline); font-size: 0.92rem; }
  body.theme-material .cloud-trigger:hover, body.theme-material .cloud-trigger.open { border-bottom-color: var(--md-primary); }
  body.theme-material .cloud-trigger-text { color: var(--md-on-surface-variant); }
  body.theme-material .cloud-trigger.chosen .cloud-trigger-text { color: var(--md-on-surface); }
  body.theme-material .cloud-caret { color: var(--md-primary); }
  body.theme-material .word-cloud {
    background: var(--md-surface2);
    border: none;
    box-shadow: 0 8px 24px rgba(0,0,0,0.28);
    border-radius: 16px;
  }
  body.theme-material .cloud-arrow { background: var(--md-surface2); border-color: transparent; }
  body.theme-material .cloud-chip {
    color: var(--md-on-secondary-container);
    background: var(--md-secondary-container);
    border: none;
  }

  /* Verb conjugation popup - same flat tonal-surface treatment as .word-cloud above */
  body.theme-material .conjugation-popup {
    background: var(--md-surface2);
    border: none;
    box-shadow: 0 8px 24px rgba(0,0,0,0.28);
    border-radius: 16px;
  }
  body.theme-material .conjugation-arrow { background: var(--md-surface2); border-color: transparent; }
  body.theme-material .conjugation-head { color: var(--md-on-surface); border-bottom-color: var(--md-outline-variant); }
  body.theme-material .conjugation-gloss, body.theme-material .conjugation-note, body.theme-material .conjugation-pronoun { color: var(--md-on-surface-variant); }
  body.theme-material .conjugation-form { color: var(--md-on-surface); }
  body.theme-material .conjugation-form:hover, body.theme-material .conjugation-form:focus { color: var(--md-primary); }
  body.theme-material .cloud-chip:hover { background: var(--md-primary-container); color: var(--md-on-primary-container); transform: translateY(-1px); }

  body.theme-material .result-mark.ok { color: var(--md-primary); }
  body.theme-material .result-mark.no { color: #B3261E; }
  body.theme-material .result-correct-word { color: var(--md-primary); font-size: 0.88rem; }
  body.theme-material .result-wrong-word { color: #B3261E; font-size: 0.88rem; }
  body.theme-material .result-plain { color: var(--md-primary); }
  body.theme-material .result-article-note { color: var(--md-on-surface-variant); }
  body.theme-material .quiz-motivation { color: var(--md-primary); }
  body.theme-material #quizScore { color: var(--md-on-surface); }
  body.theme-material .quiz-retry-prompt { color: var(--md-on-surface-variant); font-size: 0.85rem; }

  /* ---- Primary / secondary buttons ---- */
  body.theme-material .primary-button {
    background: var(--md-primary);
    color: var(--md-surface);
    border-radius: 999px;
  }
  body.theme-material .primary-button:hover { background: var(--md-primary-dark); }
  body.theme-material .secondary-button {
    background: transparent;
    border: 1px solid var(--md-outline);
    color: var(--md-primary);
    border-radius: 999px;
  }
  body.theme-material .secondary-button:hover { background: var(--md-secondary-container); }

  /* ---- Settings view: grouped into tonal-surface boxes, same pattern as
     the table/dictionary/quiz surfaces elsewhere in the app - not the flat
     ungrouped rows the mockup used, for overall consistency with the rest
     of the app. ---- */
  body.theme-material .settings-section-label {
    font-size: 1.05rem;
    font-weight: 500;
    letter-spacing: normal;
    text-transform: none;
    color: var(--md-on-surface);
    margin: 0 0 0.5rem;
  }
  body.theme-material .settings-section-label.danger { color: #B3261E; }
  body.theme-material .settings-hint { color: var(--md-on-surface-variant); margin: -0.1rem 0 0.6rem; font-size: 0.78rem; }
  body.theme-material .app-version { color: var(--md-on-surface-variant); opacity: 0.75; }
  body.theme-material .settings-section {
    background: var(--md-surface2);
    border: none;
    box-shadow: none;
    border-radius: 20px;
    overflow: hidden;
    margin-bottom: 1.5rem;
  }
  body.theme-material .settings-row + .settings-row { border-top-color: var(--md-outline-variant); }
  body.theme-material button.action-row:hover, body.theme-material .settings-row:hover { background: rgba(0,0,0,0.045); }
  body.theme-material .settings-row-title { color: var(--md-on-surface); font-weight: 400; font-size: 0.94rem; }
  body.theme-material .settings-row-caption { color: var(--md-on-surface-variant); font-size: 0.74rem; }
  body.theme-material .chevron { color: var(--md-on-surface-variant); }
  body.theme-material .action-row.danger .settings-row-title { color: #B3261E; }
  body.theme-material .action-row.danger:hover { background: rgba(179,38,30,0.08); }
  body.theme-material .action-row.danger .chevron { color: #B3261E; }

  /* Theme-selection rows get a Material radio dot instead of the plain "✓"/"›" glyph - :not(:empty) reads the JS-driven selection state (✓ = selected, blank = not) without caring which character it is. */
  body.theme-material .theme-option-row .chevron {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    border: 2px solid var(--md-outline);
    font-size: 0;
    display: inline-flex;
    flex-shrink: 0;
    position: relative;
  }
  body.theme-material .theme-option-row .chevron:not(:empty) { border-color: var(--md-primary); }
  body.theme-material .theme-option-row .chevron:not(:empty)::after {
    content: '';
    position: absolute;
    inset: 3px;
    border-radius: 50%;
    background: var(--md-primary);
  }

  /* Export/Import/Reset become small tonal pill buttons instead of full-width rows, like the mockup's .btn-tonal/.btn-text */
  body.theme-material .settings-action-buttons {
    display: flex;
    gap: 0.6rem;
    flex-wrap: wrap;
    padding: 0.9rem 1.1rem 1.1rem;
  }
  body.theme-material .settings-action-buttons .action-row {
    width: auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.55rem 1.1rem;
    border-radius: 999px;
    background: var(--md-primary-container);
    color: var(--md-on-primary-container);
  }
  body.theme-material .settings-action-buttons .action-row:hover { background: var(--md-secondary-container); }
  body.theme-material .settings-action-buttons .action-row .settings-row-title { color: inherit; font-size: 0.82rem; font-weight: 600; }
  body.theme-material .settings-action-buttons .action-row.danger { background: transparent; color: #B3261E; }
  body.theme-material .settings-action-buttons .action-row.danger:hover { background: rgba(179,38,30,0.08); }
  body.theme-material .settings-action-buttons .chevron { display: none; }

  body.theme-material .toggle-track { background: var(--md-outline-variant); }
  body.theme-material .toggle-switch input:checked + .toggle-track { background: var(--md-primary); }

  /* ---- Accent color picker (Settings, Material only): real OS-color
     detection isn't possible on Android, so this is a genuine user choice
     instead of a fake "from your wallpaper" pretense ---- */
  body.theme-material .md-accent-picker {
    display: flex;
    flex-wrap: wrap;
    gap: 0.85rem;
    padding: 1rem;
  }
  body.theme-material .md-accent-swatch {
    width: 2.6rem;
    height: 2.6rem;
    border-radius: 50%;
    border: 2px solid transparent;
    background: var(--swatch-color);
    padding: 0;
    cursor: pointer;
    position: relative;
    overflow: hidden;
    transition: transform 0.15s ease, border-color 0.15s ease;
  }
  body.theme-material .md-accent-swatch:hover { transform: scale(1.08); }
  body.theme-material .md-accent-swatch.active {
    border-color: var(--md-on-surface);
    box-shadow: 0 0 0 3px var(--md-surface2), 0 0 0 4px var(--md-outline-variant);
  }
  body.theme-material .md-accent-swatch.active::after {
    content: '✓';
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: 1.1rem;
    font-weight: 700;
    text-shadow: 0 1px 2px rgba(0,0,0,0.5);
  }

  /* ---- Modals (covers all 5 overlays sharing this markup) ---- */
  body.theme-material .modal-overlay { background: rgba(0,0,0,0.32); }
  body.theme-material .modal-box {
    background: var(--md-surface2);
    border: none;
    border-radius: 28px;
    box-shadow: 0 8px 24px rgba(0,0,0,0.35);
  }
  body.theme-material .modal-box h2 { color: var(--md-on-surface); font-weight: 500; }
  body.theme-material .modal-box p { color: var(--md-on-surface-variant); }
  body.theme-material .modal-actions button { border-radius: 999px; }
  body.theme-material .modal-cancel { background: transparent; color: var(--md-primary); border: none !important; }
  body.theme-material .modal-cancel:hover { background: rgba(0,0,0,0.06); }
  body.theme-material .modal-confirm { background: transparent; color: #B3261E; }
  body.theme-material .modal-confirm:hover { background: rgba(179,38,30,0.08); }
  body.theme-material .modal-confirm-neutral { background: var(--md-primary-container); color: var(--md-on-primary-container); }
  body.theme-material .modal-confirm-neutral:hover { background: var(--md-secondary-container); }

  /* ---- Ripple click feedback (see the delegated pointerdown listener in
     index.html) - this list must cover every element the JS ripple
     selector can match, or a ripple still gets created (JS matched it) but
     lands in the wrong place: position:absolute with no positioned host
     falls back to the nearest positioned ANCESTOR instead (e.g. the hero
     bar), rendering the ripple pinned near that ancestor's corner instead
     of at the tap point. .word/.dict-word (the speak-aloud words in the
     table and dictionary) match the JS selector via role="button" (see
     makeSpeakableWord()) but were missing here - exactly that bug. ---- */
  body.theme-material .primary-button,
  body.theme-material .secondary-button,
  body.theme-material .nav-button,
  body.theme-material .settings-row.action-row,
  body.theme-material .md-nav-item,
  body.theme-material .cloud-trigger,
  body.theme-material .cloud-chip,
  body.theme-material .modal-cancel,
  body.theme-material .modal-confirm,
  body.theme-material .modal-confirm-neutral,
  body.theme-material .dict-search-clear,
  body.theme-material .word,
  body.theme-material .dict-word,
  body.theme-material .reference-toggle-btn,
  body.theme-material .dict-conjugate-btn,
  body.theme-material .conjugation-form {
    position: relative;
    overflow: hidden;
  }
  /* Deliberately NOT scoped under body.theme-material, unlike everything
     else in this file: a ripple can outlive the click that spawned it (its
     own 0.5s animation, or a theme switch fired by that very same click),
     and if position:absolute stopped applying the moment the theme class
     changed, an orphaned ripple would fall back to static flow and its
     explicit pixel width/height (computed from the button's own size) would
     inflate its parent's layout. Harmless to leave unscoped - the JS ripple
     listener already only ever creates one while theme-material is active. */
  .md-ripple {
    position: absolute;
    border-radius: 50%;
    background: currentColor;
    opacity: 0.25;
    transform: scale(0);
    animation: md-ripple-expand 0.5s ease-out;
    pointer-events: none;
  }
  @keyframes md-ripple-expand {
    to { transform: scale(1); opacity: 0; }
  }
  @media (prefers-reduced-motion: reduce) {
    .md-ripple { animation: none; display: none; }
  }

  /* ============================================================
     "Expanded" Material window size class (tablet landscape / desktop,
     >=1240px) - a second tier on top of the 900px "medium" rail above, not
     a replacement for it. Widens the rail into a full labeled drawer and
     lets each view reflow into the extra width instead of just capping at
     the same 640px card forever. Mocked up and confirmed with the user
     before building (see chat) - deliberately mirrors that mockup's
     structure/values 1:1.
     ============================================================ */
  @media (min-width: 1240px) {
    body.theme-material { padding: 0 0 0 15rem; }

    /* ---- Rail -> drawer ---- */
    body.theme-material .md-nav {
      width: 15rem;
      padding: 1.6rem 0.9rem;
      gap: 0.2rem;
      border-right: 1px solid var(--md-outline-variant);
    }
    body.theme-material .md-nav-brand {
      display: block;
      font-family: 'Space Grotesk', sans-serif;
      font-weight: 700;
      font-size: 0.98rem;
      color: var(--md-on-surface);
      padding: 0.4rem 1rem 1.3rem;
    }
    body.theme-material .md-nav-item {
      flex-direction: row;
      gap: 0.9rem;
      padding: 0.65rem 1rem;
      border-radius: 999px;
      justify-content: flex-start;
    }
    body.theme-material .md-nav-item.active { background: var(--md-secondary-container); }
    /* The rail's active state tints just the icon's own pill; the drawer's
       wider row tints the whole row instead (set above), so the icon's own
       background needs to step back out of the way here. */
    body.theme-material .md-nav-item.active .md-nav-icon { background: transparent; }
    body.theme-material .md-nav-icon { width: 1.5rem; height: 1.5rem; }
    body.theme-material .md-nav-icon svg { width: 1.35rem; height: 1.35rem; }
    body.theme-material .md-nav-label {
      font-size: 0.86rem;
      text-align: left;
    }

    /* ---- Card widths: a wider baseline for every "wide" view, plus a
       couple of views that need more than that for their own reflow below ---- */
    body.theme-material .card.wide { max-width: 820px; }
    body.theme-material #settingsView.card.wide { max-width: 900px; }
    body.theme-material #quizView.card.wide { max-width: 880px; }

    /* ---- Main (Training) view: set + history-nav stay their normal width,
       with the full set history alongside as a clickable side panel -
       fixed height (matched to the table) with its own scroll, so a
       history of any length never changes the layout's height. ---- */
    body.theme-material #mainView .md-body {
      display: flex;
      align-items: flex-start;
      gap: 1.5rem;
    }
    body.theme-material .main-trainer-col { flex: 1 1 auto; min-width: 0; }
    body.theme-material .md-history-panel {
      display: flex;
      flex-direction: column;
      flex: 0 0 260px;
      max-height: 330px;
      background: var(--md-surface2);
      border-radius: 20px;
      overflow: hidden;
    }
    body.theme-material .md-history-panel-head {
      display: flex;
      align-items: baseline;
      justify-content: space-between;
      flex: 0 0 auto;
      padding: 0.9rem 1rem 0.5rem;
    }
    body.theme-material .md-history-panel-head h2 {
      margin: 0;
      font-size: 0.76rem;
      font-weight: 600;
      text-transform: uppercase;
      letter-spacing: 0.05em;
      color: var(--md-on-surface-variant);
    }
    body.theme-material .md-history-panel-head .count { font-size: 0.68rem; color: var(--md-on-surface-variant); opacity: 0.75; }
    body.theme-material .md-history-panel-list { overflow-y: auto; padding: 0 0.6rem 0.7rem; }
    body.theme-material .md-history-item {
      display: flex;
      align-items: center;
      gap: 0.3rem;
      width: 100%;
      border: none;
      background: transparent;
      font-family: inherit;
      cursor: pointer;
      text-align: left;
      padding: 0.55rem 0.6rem;
      margin-bottom: 0.15rem;
      border-radius: 12px;
      font-size: 0.82rem;
      color: var(--md-on-surface);
    }
    body.theme-material .md-history-item:hover { background: rgba(0,0,0,0.045); }
    body.theme-material .md-history-item .day { font-weight: 600; flex-shrink: 0; }
    body.theme-material .md-history-item .topic {
      flex: 1 1 auto;
      min-width: 0;
      color: var(--md-on-surface-variant);
      font-size: 0.76rem;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    body.theme-material .md-history-item.current {
      background: var(--md-primary-container);
      color: var(--md-on-primary-container);
      font-weight: 600;
    }
    body.theme-material .md-history-item.current .topic { color: inherit; opacity: 0.75; }

    /* ---- Settings: the two column groups (see index.html) become an
       actual 2-column grid instead of just stacking. ---- */
    body.theme-material #settingsView .md-body {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 0 1.8rem;
      align-items: start;
    }
    /* .app-version is a 3rd grid item (after the two settings-col-* divs) -
       without this it auto-places into column 1 only instead of spanning
       under both columns. */
    body.theme-material #settingsView .md-body > .app-version {
      grid-column: 1 / -1;
    }

    /* ---- Quiz (both the regular 25-word and the 10-word Zufalls-Quiz
       share #quizBody): reflow into 2 CSS columns, same technique already
       used for the dictionary/numbers views. break-inside:avoid keeps each
       item from being split across the column break. ---- */
    body.theme-material #quizBody {
      column-width: 380px;
      column-gap: 1.6rem;
    }
    body.theme-material .quiz-item { break-inside: avoid; }

    /* ---- Zahlen (Zahlwörter/Ordinalzahlen): the column-count:2 cap (see
       the shared, all-themes .numbers-columns rule) never grows no matter
       how wide the screen gets - raise it by one now that there's room. ---- */
    body.theme-material .numbers-columns { column-count: 3; }

    /* ---- Conversations picker: two columns once there's room. ---- */
    body.theme-material .conv-picker-list { grid-template-columns: 1fr 1fr; }
  }

  /* ============ CONVERSATIONS (Material theme only - this feature has no
     look under the other three themes, see showConversations() in
     index.html). Uses the same "correct = primary accent, wrong = fixed
     Material error red" convention already established by the quiz result
     view (.result-correct-word/.result-wrong-word) rather than inventing a
     separate success color. ============ */

  body.theme-material .conv-picker-list {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.8rem;
  }
  body.theme-material .conv-card {
    display: flex;
    align-items: center;
    gap: 0.8rem;
    text-align: left;
    background: var(--md-surface2);
    border: none;
    border-radius: 16px;
    padding: 0.7rem;
    font-family: inherit;
    cursor: pointer;
    transition: background 0.15s ease;
  }
  body.theme-material .conv-card:hover:not(:disabled) { background: var(--md-surface3); }
  body.theme-material .conv-card:disabled { cursor: default; opacity: 0.75; }
  body.theme-material .conv-card-img-wrap {
    position: relative;
    overflow: hidden;
    flex: 0 0 auto;
    width: 64px;
    height: 64px;
    border-radius: 12px;
    background: var(--md-surface3);
  }
  body.theme-material .conv-card-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
  }
  /* Same masked-tint approach as .conv-hero-tint, scaled down - the mask
     PNG is reused as-is, mask-size:cover scales it to fit this 64px box. */
  body.theme-material .conv-card-img-tint {
    position: absolute;
    inset: 0;
    background: var(--md-primary);
    mix-blend-mode: hue;
    pointer-events: none;
    mask-repeat: no-repeat;
    mask-size: cover;
    mask-position: 50% 55%;
    -webkit-mask-repeat: no-repeat;
    -webkit-mask-size: cover;
    -webkit-mask-position: 50% 55%;
  }
  body.theme-material .conv-card-lock {
    flex: 0 0 auto;
    width: 64px;
    height: 64px;
    border-radius: 12px;
    background: var(--md-surface3);
    color: var(--md-on-surface-variant);
    display: flex;
    align-items: center;
    justify-content: center;
  }
  body.theme-material .conv-card-body { min-width: 0; }
  body.theme-material .conv-card-title { font-weight: 600; color: var(--md-on-surface); font-size: 0.94rem; }
  body.theme-material .conv-card-meta { color: var(--md-on-surface-variant); font-size: 0.8rem; margin-top: 0.15rem; }

  /* ---- Playback ---- */
  body.theme-material .conv-back-btn {
    border: none;
    background: var(--md-surface2);
    color: var(--md-on-surface);
    width: 36px;
    height: 36px;
    border-radius: 999px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    margin-bottom: 0.7rem;
  }
  body.theme-material .conv-hero {
    position: relative;
    overflow: hidden;
    height: 150px;
    border-radius: 16px;
    background-size: cover;
    background-position: 50% 55%;
    background-color: var(--md-primary-dark);
    margin-bottom: 0.9rem;
    box-shadow: inset 0 -60px 50px -20px rgba(15,25,40,0.55);
  }
  /* Live-tints the hero to the current accent hue, masked to the image's
     blue background only (see convHeroTint wiring in showConversation()) -
     mix-blend-mode:hue recolors whatever it's painted over, so without the
     mask it would wash out the illustrations' warm accents too. */
  body.theme-material .conv-hero-tint {
    position: absolute;
    inset: 0;
    background: var(--md-primary);
    mix-blend-mode: hue;
    pointer-events: none;
    mask-repeat: no-repeat;
    mask-size: cover;
    mask-position: 50% 55%;
    -webkit-mask-repeat: no-repeat;
    -webkit-mask-size: cover;
    -webkit-mask-position: 50% 55%;
  }
  body.theme-material .conv-progress-row {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    margin-bottom: 0.9rem;
  }
  body.theme-material .conv-play-btn {
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    border-radius: 999px;
    border: none;
    background: var(--md-primary);
    color: var(--md-surface);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
  }
  body.theme-material .conv-progress-dots { flex: 1 1 auto; display: flex; gap: 0.28rem; align-items: center; flex-wrap: wrap; }
  body.theme-material .conv-dot { width: 8px; height: 8px; border-radius: 50%; border: 1.5px solid var(--md-outline-variant); }
  body.theme-material .conv-dot.done { background: var(--md-primary); border-color: var(--md-primary); }
  body.theme-material .conv-dot.current { width: 10px; height: 10px; background: var(--md-primary); border-color: var(--md-primary); box-shadow: 0 0 0 3px var(--md-primary-container); }
  body.theme-material .conv-progress-count { flex: 0 0 auto; font-size: 0.74rem; color: var(--md-on-surface-variant); font-variant-numeric: tabular-nums; }

  body.theme-material .conv-transcript, body.theme-material .conv-test-transcript { display: flex; flex-direction: column; gap: 0.7rem; margin-bottom: 0.9rem; }
  body.theme-material .conv-bubble-row { display: flex; align-items: flex-end; gap: 0.5rem; }
  body.theme-material .conv-bubble-row.right { flex-direction: row-reverse; }
  body.theme-material .conv-avatar { flex: 0 0 auto; width: 34px; height: 34px; border-radius: 50%; object-fit: cover; background: var(--md-surface3); }
  body.theme-material .conv-avatar.mirrored { transform: scaleX(-1); }
  body.theme-material .conv-bubble { max-width: 82%; background: var(--md-surface2); border-radius: 16px 16px 16px 4px; padding: 0.55rem 0.8rem; }
  body.theme-material .conv-bubble.right { border-radius: 16px 16px 4px 16px; text-align: right; }
  body.theme-material .conv-bubble.current { background: var(--md-primary-container); box-shadow: 0 0 0 2px var(--md-primary); }
  body.theme-material .conv-bubble-head { display: flex; align-items: center; gap: 0.5rem; }
  body.theme-material .conv-bubble.right .conv-bubble-head { flex-direction: row-reverse; }
  body.theme-material .conv-bubble-es { margin: 0; font-size: 0.94rem; font-weight: 600; line-height: 1.6; color: var(--md-on-surface); }
  body.theme-material .conv-bubble.current .conv-bubble-es { color: var(--md-on-primary-container); }
  body.theme-material .conv-bubble-de { margin: 0.3rem 0 0; font-size: 0.78rem; line-height: 1.35; color: var(--md-on-surface-variant); }
  body.theme-material .conv-bubble.current .conv-bubble-de { color: var(--md-on-primary-container); opacity: 0.75; }
  body.theme-material .conv-replay-btn { flex: 0 0 auto; border: none; background: transparent; color: var(--md-on-surface-variant); cursor: pointer; display: flex; }
  body.theme-material .conv-test-start-btn { margin-top: 0.3rem; }
  body.theme-material .conv-skip-btn {
    display: block;
    margin: 0 0 0.7rem auto;
    background: none;
    border: none;
    color: var(--md-primary);
    font-family: inherit;
    font-size: 0.8rem;
    font-weight: 600;
    cursor: pointer;
    padding: 0.2rem 0.3rem;
  }
  body.theme-material .conv-skip-btn:hover { text-decoration: underline; }

  /* ---- Tap-to-dissect words ---- */
  body.theme-material .tap-word {
    text-decoration: underline;
    text-decoration-style: dotted;
    text-decoration-color: currentColor;
    text-underline-offset: 3px;
    text-decoration-thickness: 1.5px;
    cursor: pointer;
  }
  body.theme-material .tap-word-fixed-phrase { text-decoration-style: solid; }
  /* Words/verbs/adjectives/phrases NOT yet in the learner's own training
     history (esVocab_history) - subtle (color+thickness on the same
     dotted underline, no background fill) so it stays legible across a
     full paragraph and doesn't visually compete with .open below, which
     still wins once a word is actually tapped. */
  body.theme-material .tap-word-unknown { text-decoration-color: var(--md-primary); text-decoration-thickness: 2px; }
  body.theme-material .tap-word.open { background: var(--md-primary); color: var(--md-surface); border-radius: 5px; padding: 0 0.15rem; text-decoration: none; }

  /* ---- Dissection popup (fixed-phrase / function-word / content-word -
     verbs reuse #conjugationPopup instead, see openDissectPopup()). Same
     flat tonal-surface treatment as #conjugationPopup/.word-cloud. ---- */
  .dissect-popup {
    position: fixed;
    display: none;
    width: 280px;
    max-width: calc(100vw - 24px);
    z-index: 50;
    border-radius: 16px;
    overflow: hidden;
    box-shadow: 0 8px 24px rgba(0,0,0,0.28);
  }
  body.theme-material .dissect-popup { background: var(--md-surface); }
  body.theme-material .dissect-popup-function-word .dissect-head { background: var(--md-tertiary-container); }
  body.theme-material .dissect-popup-fixed-phrase .dissect-head,
  body.theme-material .dissect-popup-word .dissect-head,
  body.theme-material .dissect-popup-adjective .dissect-head { background: var(--md-secondary-container); }
  body.theme-material .dissect-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.6rem;
    padding: 0.8rem 0.9rem 0.6rem;
  }
  body.theme-material .dissect-popup-function-word .dissect-head { color: var(--md-on-tertiary-container); }
  body.theme-material .dissect-popup-fixed-phrase .dissect-head,
  body.theme-material .dissect-popup-word .dissect-head,
  body.theme-material .dissect-popup-adjective .dissect-head { color: var(--md-on-secondary-container); }
  body.theme-material .dissect-main { font-weight: 700; font-size: 1rem; }
  body.theme-material .dissect-sub { font-size: 0.8rem; opacity: 0.85; margin-left: 0.35rem; }
  body.theme-material .dissect-tag { font-size: 0.7rem; opacity: 0.8; white-space: nowrap; }
  body.theme-material .dissect-note {
    margin: 0;
    padding: 0.6rem 0.9rem 0.8rem;
    font-size: 0.8rem;
    line-height: 1.5;
    color: var(--md-on-surface-variant);
  }
  /* Verb dissection's "In diesem Satz: ..." subject-reference callout,
     inside the REUSED #conjugationPopup - see toggleConjugationPopup(). */
  .conjugation-context {
    margin: 0.6rem 0.9rem 0;
    padding: 0.45rem 0.6rem;
    border-radius: 8px;
    font-size: 0.78rem;
    line-height: 1.4;
  }
  body.theme-material .conjugation-context { background: var(--md-primary-container); color: var(--md-on-primary-container); }
  body.theme-material .conjugation-row.current { background: var(--md-primary-container); border-radius: 8px; }

  /* ---- Test, Stufe A: fill in the blanks ---- */
  body.theme-material .conv-quiz-sentence-card {
    background: var(--md-surface);
    border: 2px solid var(--md-primary);
    border-radius: 16px;
    padding: 0.8rem 1rem;
    margin-bottom: 0.9rem;
  }
  body.theme-material .conv-quiz-sentence { margin: 0; font-size: 1rem; font-weight: 600; line-height: 1.9; color: var(--md-on-surface); }
  body.theme-material .blank { display: inline-block; border-radius: 6px; padding: 0 0.4rem; }
  body.theme-material .blank-empty { border: 2px dashed var(--md-outline-variant); background: var(--md-surface2); min-width: 5.6rem; height: 1.4rem; vertical-align: middle; }
  body.theme-material .blank-active { border: 2px dashed var(--md-primary); background: var(--md-surface); min-width: 5.6rem; height: 1.4rem; vertical-align: middle; box-shadow: 0 0 0 3px var(--md-primary-container); }
  body.theme-material .blank-correct { background: var(--md-primary-container); color: var(--md-on-primary-container); border: 1.5px solid var(--md-primary); font-weight: 700; }
  body.theme-material .blank-wrong { border-color: #B3261E !important; background: rgba(179,38,30,0.12) !important; box-shadow: 0 0 0 3px rgba(179,38,30,0.12) !important; animation: conv-shake 0.4s ease; }

  body.theme-material .conv-quiz-bank-card { background: var(--md-surface2); border-radius: 14px; padding: 0.9rem 1rem 1rem; margin-bottom: 0.7rem; }
  body.theme-material .conv-quiz-bank-label { margin: 0 0 0.6rem; font-size: 0.7rem; letter-spacing: 0.03em; text-transform: uppercase; color: var(--md-on-surface-variant); }
  body.theme-material .conv-quiz-bank { display: flex; flex-wrap: wrap; gap: 0.5rem; min-height: 2.2rem; }
  body.theme-material .chip { display: inline-flex; align-items: center; padding: 0.42rem 0.8rem; border-radius: 999px; background: var(--md-surface); border: 1.5px solid var(--md-outline-variant); font-size: 0.86rem; font-weight: 600; color: var(--md-on-surface); cursor: pointer; }
  body.theme-material .chip:hover { border-color: var(--md-primary); }
  body.theme-material .chip.used { display: none; }
  body.theme-material .chip.wrong { background: rgba(179,38,30,0.12); border-color: #B3261E; color: #B3261E; animation: conv-shake 0.4s ease; }

  body.theme-material .conv-quiz-feedback { min-height: 1.1rem; font-size: 0.8rem; font-weight: 600; opacity: 0; transition: opacity 0.2s ease; margin: 0 0 0.6rem; }
  body.theme-material .conv-quiz-feedback.show.ok { opacity: 1; color: var(--md-primary); }
  body.theme-material .conv-quiz-feedback.show.bad { opacity: 1; color: #B3261E; }
  body.theme-material .conv-quiz-next-btn:disabled { background: var(--md-outline-variant); color: var(--md-on-surface-variant); opacity: 0.7; cursor: not-allowed; }

  @keyframes conv-shake {
    10%, 90% { transform: translateX(-2px); }
    20%, 80% { transform: translateX(3px); }
    30%, 50%, 70% { transform: translateX(-5px); }
    40%, 60% { transform: translateX(5px); }
  }

  /* ---- Test, Stufe B: sort the conversation into order ---- */
  body.theme-material .conv-divider { display: flex; align-items: center; gap: 0.6rem; margin: 0.2rem 0 0.9rem; }
  body.theme-material .conv-divider-line { flex: 1 1 auto; height: 1px; background: var(--md-outline-variant); }
  body.theme-material .conv-divider span { font-size: 0.72rem; color: var(--md-on-surface-variant); white-space: nowrap; }
  body.theme-material .conv-test-pool { display: flex; flex-direction: column; gap: 0.55rem; }
  body.theme-material .conv-test-pool-card {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    background: var(--md-surface);
    border: 1.5px dashed var(--md-outline-variant);
    border-radius: 12px;
    padding: 0.6rem 0.8rem;
    cursor: pointer;
    transition: transform 0.12s ease, opacity 0.18s ease;
  }
  body.theme-material .conv-test-pool-card:hover { border-color: var(--md-primary); }
  body.theme-material .conv-test-pool-card.leaving { transform: scale(0.92); opacity: 0; }
  body.theme-material .conv-test-pool-card.wrong { background: rgba(179,38,30,0.12); border: 1.5px solid #B3261E; animation: conv-shake 0.4s ease; }
  body.theme-material .conv-test-pool-card img { flex: 0 0 auto; width: 30px; height: 30px; border-radius: 50%; object-fit: cover; }
  body.theme-material .conv-test-pool-card img.mirrored { transform: scaleX(-1); }
  body.theme-material .conv-test-pool-name { margin: 0 0 0.15rem; font-size: 0.68rem; font-weight: 700; color: var(--md-on-surface-variant); }
  body.theme-material .conv-test-pool-es { margin: 0; font-size: 0.86rem; font-weight: 600; color: var(--md-on-surface); line-height: 1.35; }
  body.theme-material .conv-test-done { padding: 0.9rem; text-align: center; background: var(--md-primary-container); color: var(--md-on-primary-container); border-radius: 12px; font-weight: 700; margin-bottom: 0.8rem; }

  /* ---- Test completion summary: "Neu gelernte Wörter" ---- */
  body.theme-material .conv-summary-lede { font-size: 0.88rem; color: var(--md-on-surface-variant); line-height: 1.5; margin: 0 0 1rem; }
  body.theme-material .conv-summary-list { background: var(--md-surface); border-radius: 14px; padding: 0.7rem 1rem; margin-bottom: 1.1rem; }
  body.theme-material .conv-summary-list .dict-entry:last-child { margin-bottom: 0; }
