/*
 * Shared by the English and Hebrew pages. Kept in one file deliberately: the
 * copy has to exist twice, but the design must not, or the two languages drift
 * into looking like different products.
 *
 * Direction is handled with logical properties rather than [dir="rtl"] overrides,
 * so the Hebrew page mirrors itself from <html dir="rtl"> alone.
 */

:root {
  --teal-900: #134e4a;
  --teal-700: #0f766e;
  --teal-600: #0d9488;
  --teal-500: #14b8a6;
  --teal-50:  #f0fdfa;
  --ink:      #0f172a;
  --muted:    #52616f;
  --line:     #cbd5e1;
  --bg:       #ffffff;
  --surface:  #f8fafc;
}

/*
 * Dark palette, three-state so a visitor's explicit choice can override the
 * system. Applied when the system asks for dark UNLESS the visitor forced light,
 * and whenever the visitor forced dark — so the toggle (theme.js writes
 * `data-theme` on <html>) wins in both directions. Light is the bare :root above.
 * The token values are the same in both selectors; kept as two blocks because
 * CSS has no way to share one.
 */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ink:      #e8eef2;
    --muted:    #9fb0bd;
    --line:     #23343c;
    --bg:       #0c1517;
    --surface:  #111e21;
    --teal-50:  #10262a;
    --teal-700: #2dd4bf;
    --teal-900: #99f6e4;
  }
}
:root[data-theme="dark"] {
  --ink:      #e8eef2;
  --muted:    #9fb0bd;
  --line:     #23343c;
  --bg:       #0c1517;
  --surface:  #111e21;
  --teal-50:  #10262a;
  --teal-700: #2dd4bf;
  --teal-900: #99f6e4;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 17px/1.65 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  /* Apple ships type with optical sizing and legibility tuning baked in; ask the
     system font for the same rather than leaving it flat at every size. */
  font-optical-sizing: auto;
  text-rendering: optimizeLegibility;
}

/* Hebrew reads better with slightly more air between lines. */
html[lang="he"] body { line-height: 1.75; }

.wrap { max-width: 68rem; margin: 0 auto; padding: 0 1.5rem; }
a { color: var(--teal-700); }

/* ---- header ----
   A floating translucent layer that content scrolls *under*, not an opaque strip
   that consumes a fixed band (Apple's material chrome, §12). The blur + saturate
   is what makes it read as glass catching the page behind it; the hairline is the
   material's edge, softened so it's an edge and not a hard divider. Reduced
   transparency and the no-backdrop-filter fallback both make it solid — see the
   media blocks at the end. */
header {
  position: sticky; top: 0; z-index: 40;
  background: color-mix(in srgb, var(--bg) 72%, transparent);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  backdrop-filter: blur(20px) saturate(180%);
  border-bottom: 1px solid color-mix(in srgb, var(--line) 55%, transparent);
}
/* No backdrop-filter (older browsers): fall back to a solid bar so the header
   never turns into unreadable see-through text over scrolling content. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  header { background: var(--bg); }
}
.bar { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 1.15rem 0; }
.logo { display: flex; align-items: center; gap: .6rem; font-weight: 700; letter-spacing: -.02em; font-size: 1.15rem; }
/* Logo: a teal speech bubble with a white check, an inline SVG baked into the
   background so it's one source of truth for every page and needs no asset. */
.mark {
  width: 1.9rem; height: 1.9rem; flex: none;
  background: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%3E%3Cpath%20fill%3D%27%230d9488%27%20d%3D%27M5%202h14a3%203%200%200%201%203%203v10a3%203%200%200%201-3%203H10l-5%204v-4a3%203%200%200%201-3-3V5a3%203%200%200%201%203-3z%27%2F%3E%3Cpath%20fill%3D%27none%27%20stroke%3D%27%23ffffff%27%20stroke-width%3D%272.4%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%20d%3D%27M8%2010l2.8%202.8L16.5%207%27%2F%3E%3C%2Fsvg%3E") center / contain no-repeat;
}
nav { display: flex; gap: 1.4rem; font-size: .95rem; align-items: center; }
nav a { color: var(--muted); text-decoration: none; }
nav a:hover { color: var(--teal-700); }

/* "About" dropdown — a native <details> so it needs no script and taps on
   mobile. Logical properties keep it correct in the RTL (Hebrew) layout. */
.dropdown { position: relative; }
.dropdown > summary {
  list-style: none; cursor: pointer; color: var(--muted); user-select: none;
}
.dropdown > summary::-webkit-details-marker { display: none; }
.dropdown > summary::after { content: "▾"; font-size: .75em; margin-inline-start: .3em; }
.dropdown > summary:hover, .dropdown[open] > summary { color: var(--teal-700); }
.dropdown-menu {
  position: absolute; top: calc(100% + .5rem); inset-inline-start: 0;
  display: flex; flex-direction: column; gap: .2rem;
  background: var(--bg); border: 1px solid var(--line); border-radius: .6rem;
  padding: .45rem .3rem; min-width: 11rem; z-index: 20;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .1);
}
.dropdown-menu a { padding: .4rem .8rem; border-radius: .4rem; white-space: nowrap; }
.dropdown-menu a:hover { background: var(--surface); }

/* Three languages, so the switcher shows all of them with the current one marked
   rather than toggling between two. */
.langs { display: flex; gap: .35rem; }
.lang {
  border: 1px solid var(--line); border-radius: 999px;
  padding: .25rem .7rem; color: var(--teal-700) !important; font-weight: 600;
  font-size: .88rem; white-space: nowrap;
}
.lang:hover { border-color: var(--teal-500); }
.lang[aria-current="page"] {
  background: var(--teal-600); border-color: var(--teal-600); color: #fff !important;
  cursor: default;
}

/* Light/dark toggle — a native <button>; theme.js sets the emoji and flips it. */
.theme-toggle {
  border: 1px solid var(--line); border-radius: 999px; background: transparent;
  cursor: pointer; font-size: 1rem; line-height: 1; padding: .3rem .55rem;
  color: inherit;
}
.theme-toggle:hover { border-color: var(--teal-500); }

/* ---- hero ---- */
.hero { display: grid; grid-template-columns: 1.05fr .95fr; gap: 3.5rem; align-items: center; padding: 4.5rem 0 3.5rem; }
h1 { font-size: clamp(2.1rem, 5vw, 3.1rem); line-height: 1.12; letter-spacing: -.03em; margin: 0 0 1.1rem; }
h1 .accent { color: var(--teal-700); }
.lede { font-size: 1.15rem; color: var(--muted); margin: 0 0 1.8rem; max-width: 34rem; }

.pill {
  display: inline-flex; align-items: center; gap: .5rem;
  background: var(--teal-50); color: var(--teal-900);
  border: 1px solid color-mix(in srgb, var(--teal-500) 30%, transparent);
  border-radius: 999px; padding: .35rem .85rem; font-size: .85rem; font-weight: 600;
  margin-bottom: 1.4rem;
}
.dot { width: .45rem; height: .45rem; border-radius: 50%; background: var(--teal-600); flex: none; }

/* ---- chat ---- */
.chat {
  background: var(--surface); border: 1px solid var(--line); border-radius: 1.1rem;
  padding: 1.4rem; display: flex; flex-direction: column; gap: .55rem;
}
.msg { max-width: 84%; padding: .6rem .85rem; border-radius: 1rem; font-size: .95rem; line-height: 1.5; }
/* Logical radii, so the "tail" corner follows the reading direction. */
.from-me { align-self: flex-end; background: var(--teal-600); color: #fff; border-end-end-radius: .3rem; }
.from-bot { align-self: flex-start; background: var(--bg); border: 1px solid var(--line); border-end-start-radius: .3rem; }

/* A bubble in the other language keeps its own direction. */
.rtl { direction: rtl; text-align: right; }
.ltr { direction: ltr; text-align: left; }

.voice { display: flex; align-items: center; gap: .55rem; }
.wave { display: flex; align-items: center; gap: 2px; }
.wave i { display: block; width: 2px; border-radius: 2px; background: currentColor; opacity: .75; }
.dur { font-size: .8rem; opacity: .85; }

/* ---- sections ---- */
section { padding: 3.5rem 0; border-top: 1px solid var(--line); }
h2 { font-size: 1.6rem; letter-spacing: -.02em; margin: 0 0 .6rem; }
.sub { color: var(--muted); margin: 0 0 2rem; max-width: 42rem; }

.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); gap: 1.5rem; }
.card { border: 1px solid var(--line); border-radius: .9rem; padding: 1.3rem; background: var(--surface); }
.card h3 { margin: 0 0 .4rem; font-size: 1.03rem; }
.card p { margin: 0; color: var(--muted); font-size: .95rem; }
.icon {
  width: 2.1rem; height: 2.1rem; border-radius: .55rem; background: var(--teal-50);
  color: var(--teal-700); display: grid; place-items: center; margin-bottom: .8rem; font-size: 1.05rem;
}

.note {
  background: var(--teal-50); border: 1px solid color-mix(in srgb, var(--teal-500) 25%, transparent);
  border-radius: .9rem; padding: 1.3rem 1.5rem;
}
.note h3 { margin: 0 0 .5rem; font-size: 1.05rem; color: var(--teal-900); }
.note p { margin: 0 0 .7rem; color: var(--muted); font-size: .96rem; }
.note p:last-child { margin-bottom: 0; }

/* ---- legal pages (privacy, terms) ---- */
/* Shared by both, and by their Hebrew/Russian versions when those exist: the
   copy differs, the presentation must not. Narrower than the marketing pages —
   legal prose is read line by line, and a long measure makes that harder. */
.legal { max-width: 44rem; margin: 0 auto; padding: 3rem 0 1rem; }
.legal h1 { font-size: clamp(1.9rem, 4vw, 2.5rem); letter-spacing: -.03em; line-height: 1.15; margin: 0 0 1.2rem; }
.legal .meta { color: var(--muted); font-size: .95rem; margin: 0 0 1.6rem; }
.legal .meta div { margin: .2rem 0; }
.legal h2 { font-size: 1.3rem; letter-spacing: -.02em; margin: 2.6rem 0 .7rem; }
.legal h3 { font-size: 1.05rem; margin: 1.7rem 0 .5rem; }
.legal p { margin: 0 0 1rem; }
.legal ul { margin: 0 0 1rem; padding-inline-start: 1.4rem; }
.legal li { margin: .35rem 0; }
.legal strong { color: var(--ink); }
.legal hr { border: 0; border-top: 1px solid var(--line); margin: 2.2rem 0; }

/* Wide tables scroll inside their own box rather than pushing the page sideways. */
.table-scroll { overflow-x: auto; margin: 0 0 1.2rem; }
.legal table { width: 100%; border-collapse: collapse; font-size: .94rem; }
.legal th, .legal td { text-align: start; vertical-align: top; padding: .6rem .8rem; border: 1px solid var(--line); }
.legal th { background: var(--surface); font-weight: 600; }

/* A draft gap the operator still has to fill. Loud on purpose — a half-written
   policy must never read as finished. Filling one is find-and-replace on this. */
.tofill {
  background: #fde68a; color: #7c2d12;
  padding: .05rem .35rem; border-radius: .35rem;
  font-size: .85em; font-weight: 600;
}
@media (prefers-color-scheme: dark) { .tofill { background: #78350f; color: #fde68a; } }

/* ---- footer ---- */
footer { border-top: 1px solid var(--line); padding: 2.2rem 0 3rem; color: var(--muted); font-size: .92rem; }
.foot { display: flex; flex-wrap: wrap; gap: 1rem 1.6rem; justify-content: space-between; align-items: center; }
.foot nav { gap: 1.4rem; }

@media (max-width: 46rem) {
  .hero { grid-template-columns: 1fr; gap: 2.5rem; padding: 3rem 0 2.5rem; }
  nav .hide-sm { display: none; }
}

/* ---- storage notice ----
   A notice, not a consent gate: everything it describes is strictly necessary,
   so there is no reject button to style. See cookie-notice.js and privacy §10.
   Fixed to the bottom rather than covering the page — nothing here is a
   decision, so it must not behave like one and block reading. */
.cookie-notice {
  position: fixed; inset-inline: 0; bottom: 0; z-index: 50;
  display: flex; flex-wrap: wrap; gap: .8rem 1.4rem; align-items: center;
  justify-content: center;
  padding: .9rem 1.2rem calc(.9rem + env(safe-area-inset-bottom));
  background: var(--surface); border-top: 1px solid var(--line);
  color: var(--muted); font-size: .9rem; line-height: 1.5;
}
.cookie-notice p { margin: 0; max-width: 62ch; }
.cookie-notice a { color: var(--teal-700); }
.cookie-dismiss {
  flex: none; cursor: pointer;
  padding: .45rem 1.1rem; border-radius: 999px;
  border: 1px solid var(--line); background: var(--bg); color: var(--ink);
  font: inherit; font-weight: 600;
}
.cookie-dismiss:hover { border-color: var(--teal-600); color: var(--teal-700); }

/* ============================================================================
 * Fluid-interface layer
 *
 * The rest of this file is static presentation; this block is how the site
 * *responds*. The through-line (Apple, "Designing Fluid Interfaces", WWDC 2018):
 * an interface feels alive when it reacts the instant you touch it, moves
 * continuously, and settles like a real object rather than snapping.
 *
 * Everything here is additive and fails safe: content is fully visible with no
 * CSS at all, motion runs ONLY under `prefers-reduced-motion: no-preference`, and
 * the glass falls back to solid where `backdrop-filter` is unsupported or the
 * visitor asked for less transparency. Nothing below is load-bearing for reading
 * the page — it is the difference between "fine" and "fluid".
 * ========================================================================== */

/* Two curves used throughout. `--ease-out` decelerates into rest (no overshoot) —
   Apple's critically-damped default, right for almost everything. `--ease-spring`
   overshoots a hair, reserved for motion that follows a deliberate action (a
   press releasing, a panel arriving), never for something that merely appeared. */
:root {
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1);
  /* Surface depth: a bigger surface should read as thicker (§12). Soft, low, and
     theme-neutral so it reads as lift rather than a drawn shadow. */
  --lift-1: 0 1px 2px rgba(15, 23, 42, .04), 0 2px 8px rgba(15, 23, 42, .05);
  --lift-2: 0 4px 12px rgba(15, 23, 42, .07), 0 12px 28px rgba(15, 23, 42, .08);
}
:root[data-theme="dark"], :root:not([data-theme="light"]) {
  --lift-1: 0 1px 2px rgba(0, 0, 0, .3), 0 2px 10px rgba(0, 0, 0, .35);
  --lift-2: 0 6px 20px rgba(0, 0, 0, .45), 0 16px 40px rgba(0, 0, 0, .5);
}

/* ---- Craft: a real focus ring ----
   Keyboard users need to see where they are; pointer users never see this. The
   old default was the browser's, which the reset and custom controls half-erased. */
a:focus-visible, button:focus-visible, summary:focus-visible,
input:focus-visible, select:focus-visible, textarea:focus-visible,
.lang:focus-visible, .btn:focus-visible {
  outline: 2px solid var(--teal-500);
  outline-offset: 2px;
  border-radius: .4rem;
}

/* ---- §1 Response: feedback on the press, not the release ----
   The single most important rule. Every tappable thing dips instantly when
   pressed (snappy, ~90ms) and settles back with the decelerating curve on
   release, so the control feels physically depressed rather than merely clicked.
   Transitions are on transform/color/shadow only — the compositor-cheap ones. */
nav a, .lang, .theme-toggle, .dropdown > summary, .dropdown-menu a,
.btn, .cookie-dismiss, .logo, .card {
  transition:
    transform 220ms var(--ease-out),
    box-shadow 220ms var(--ease-out),
    color 160ms ease-out,
    border-color 160ms ease-out,
    background-color 160ms ease-out;
}
.lang:active, .theme-toggle:active, .btn:active, .cookie-dismiss:active,
.dropdown-menu a:active {
  transform: scale(.96);
  transition-duration: 90ms;
}
/* A text link has nothing to scale; dim it on press instead so the tap still
   registers as felt. */
nav a:active, .dropdown > summary:active { opacity: .6; transition-duration: 90ms; }

/* ---- §12 Materials & depth: surfaces that float ----
   Cards and notes lift toward the pointer on hover and press in when tapped —
   "grow up and out toward your finger" (§8). The shadow does the depth; the tiny
   translate does the intent. */
.card { box-shadow: var(--lift-1); }
.card:hover { transform: translateY(-3px); box-shadow: var(--lift-2); }
.card:active { transform: translateY(-1px) scale(.995); transition-duration: 90ms; }
.icon { transition: transform 240ms var(--ease-spring); }
.card:hover .icon { transform: scale(1.06) rotate(-2deg); }
.note { box-shadow: var(--lift-1); }

/* Buttons (marketing .lang-as-button + dashboard .btn) get a hover lift too, so
   the primary actions feel like the most physical things on the page. */
.btn:hover, .lang:not([aria-current="page"]):hover { transform: translateY(-1px); }
.btn { box-shadow: var(--lift-1); }
.btn:hover { box-shadow: var(--lift-2); }

/* The dropdown menu should arrive from its trigger, not blink into being (§7
   anchored origin, §12 materialize). Scoped to no-preference below. */
.dropdown-menu { box-shadow: var(--lift-2); transform-origin: top center; }
html[dir="rtl"] .dropdown-menu { transform-origin: top right; }

/* Dashboard surfaces: give the cards the same floating depth as the marketing
   cards, and make form fields respond to focus with a soft teal ring rather than
   only a border swap (§1 continuous feedback, §12 draw attention to the active
   control). These class names live in the dashboard's own <style>; adding motion
   here keeps all three language copies identical for free. */
.card-box { box-shadow: var(--lift-1); }
.field input:focus, .field textarea:focus, .field select:focus {
  outline: none;
  border-color: var(--teal-500);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--teal-500) 22%, transparent);
  transition: box-shadow 160ms ease-out, border-color 160ms ease-out;
}
.status { transition: color 200ms ease-out, opacity 200ms ease-out; }

/* Auto-save is a *felt* state, not a swapped word (§1 continuous feedback, §13
   causality — the mark changes on the actual save event). A spinner while the
   write is in flight, a check when it lands; the sentence beside it stays in the
   page's language, set by the dashboard's own SAVE_T map. Driven by a
   `data-state` the three dashboards set identically. */
#save-status { display: inline-flex; align-items: center; gap: .5rem; }
#save-status::before { content: ""; flex: none; display: none; }
#save-status[data-state="saving"]::before {
  display: inline-block; width: .85em; height: .85em; border-radius: 50%;
  border: 2px solid color-mix(in srgb, var(--muted) 35%, transparent);
  border-top-color: var(--teal-600);
  animation: spin .7s linear infinite;
}
#save-status[data-state="saved"]::before { display: inline-block; content: "✓"; color: var(--teal-700); font-weight: 700; }
#save-status[data-state="error"]::before { display: inline-block; content: "⚠"; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ---- §12 Chat bubbles: read as a real thread ---- */
.chat { box-shadow: var(--lift-1); }
.msg { box-shadow: 0 1px 2px rgba(15, 23, 42, .05); }

/* ---- The storage notice is floating chrome too: make it glass ---- */
.cookie-notice {
  background: color-mix(in srgb, var(--surface) 78%, transparent);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  backdrop-filter: blur(20px) saturate(180%);
  border-top: 1px solid color-mix(in srgb, var(--line) 55%, transparent);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .cookie-notice { background: var(--surface); }
}

/* ============================================================================
 * Motion — ONLY when the visitor hasn't asked for less of it.
 * Base state above is fully visible and still; nothing here is required to read
 * the page, so reduced-motion simply gets none of it.
 * ========================================================================== */
@media (prefers-reduced-motion: no-preference) {

  /* The page arrives. Header settles down, hero content and the chat rise into
     place with a short stagger — a load entrance, not a scroll trick, because
     this is all above the fold. `both` fill holds the from-state before the delay
     so there's no flash of the final position first. */
  header { animation: settle-down 520ms var(--ease-out) both; }
  /* First column only — `> div:first-child` is the text; the chat is the sibling.
     Reaching `.hero > div > *` would also grab the chat bubbles (grandchildren via
     the chat div) and rise them in with no stagger and no intent. */
  .hero > div:first-child > * { animation: rise-in 620ms var(--ease-out) both; }
  .hero .pill   { animation-delay: 60ms; }
  .hero h1      { animation-delay: 120ms; }
  .hero .lede   { animation-delay: 200ms; }
  .hero > .chat { animation: rise-in 700ms var(--ease-out) both; animation-delay: 280ms; }

  /* Below the fold: cards and notes fade in as they enter the viewport, driven by
     the scroll position itself (momentum, §6) rather than a fixed timer. Pure
     progressive enhancement — only opacity, so it never fights the hover-lift
     transform, and only where the browser supports scroll-driven animation; every
     other browser just shows them, already visible. */
  @supports (animation-timeline: view()) {
    .grid > .card, section > .note {
      animation: fade-in-scroll linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 55%;
    }
  }

  /* The dropdown materialises from its trigger instead of appearing. */
  .dropdown[open] > .dropdown-menu { animation: menu-in 200ms var(--ease-out); }

  /* Delight (§13 utility — small and meaningful): the "live" dot breathes, and
     the sample voice note's bars move like sound. Decorative only, aria-hidden. */
  .pill .dot { animation: breathe 2.4s ease-in-out infinite; }
  .wave i { transform-origin: center; animation: equalise 1s ease-in-out infinite; }
  .wave i:nth-child(1) { animation-delay: 0s;    }
  .wave i:nth-child(2) { animation-delay: .12s;  }
  .wave i:nth-child(3) { animation-delay: .24s;  }
  .wave i:nth-child(4) { animation-delay: .36s;  }
  .wave i:nth-child(5) { animation-delay: .48s;  }
  .wave i:nth-child(6) { animation-delay: .60s;  }
  .wave i:nth-child(7) { animation-delay: .18s;  }
  .wave i:nth-child(8) { animation-delay: .30s;  }
  .wave i:nth-child(9) { animation-delay: .42s;  }
  .wave i:nth-child(10){ animation-delay: .54s;  }
}

@keyframes rise-in       { from { opacity: 0; transform: translateY(1.4rem); } to { opacity: 1; transform: none; } }
@keyframes settle-down   { from { opacity: 0; transform: translateY(-.5rem); } to { opacity: 1; transform: none; } }
@keyframes fade-in-scroll{ from { opacity: 0; } to { opacity: 1; } }
@keyframes menu-in       { from { opacity: 0; transform: translateY(-.35rem) scale(.97); } to { opacity: 1; transform: none; } }
@keyframes breathe       { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .55; transform: scale(.82); } }
@keyframes equalise      { 0%, 100% { transform: scaleY(.5); } 50% { transform: scaleY(1); } }

/* ============================================================================
 * §14 Accessibility: honour what the visitor's OS already says they want.
 * ========================================================================== */

/* Reduced motion: strip transforms and animation, keep instant colour feedback
   (a gentler, non-vestibular equivalent — not "no feedback"). Smooth scrolling
   is vestibular too, so it goes. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .card:hover, .btn:hover, .lang:hover, .card:active,
  .card:hover .icon { transform: none !important; }
}

/* Reduced transparency: the glass becomes a solid surface. Translucency is a
   nicety here, never the only thing making text legible. */
@media (prefers-reduced-transparency: reduce) {
  header { background: var(--bg); -webkit-backdrop-filter: none; backdrop-filter: none; }
  .cookie-notice { background: var(--surface); -webkit-backdrop-filter: none; backdrop-filter: none; }
}

/* More contrast: near-solid chrome and a defined edge on every floating surface. */
@media (prefers-contrast: more) {
  header { background: var(--bg); -webkit-backdrop-filter: none; backdrop-filter: none;
           border-bottom-color: var(--line); }
  .card, .card-box, .note, .dropdown-menu, .chat { border-color: var(--muted); box-shadow: none; }
  a { text-decoration: underline; }
}
