/* Copied verbatim from Mnemes-Cards/mnemes_cards_frontend,
 * app/src/styles/tokens.css at e4e01c1. Do not edit here: change it in Cards,
 * then copy it again. Everything below this header is that file unchanged.
 * Board's tokens.css is the same file plus Board-only tokens. */
/* Every literal colour in the app lives here, and nowhere else.
 *
 * `index.css` maps these into Tailwind's `--color-*` namespace with `@theme inline`,
 * which emits utilities that reference `var(--name)` rather than inlining the value.
 * That indirection is the whole point: a future `[data-theme="dark"]` block in this
 * file re-points every utility in the app without touching a `.tsx` file. */
:root {
  color-scheme: light;

  /* The brand is a slate-teal at hue ~236. The anchor #123a52 is DARK (L 0.333), so it
     sits at 800 rather than mid-ramp — `bg-primary-500` is not the brand colour here.
     Stops 100-900 are literal values from the design mock; 50/500/950 are interpolated. */
  --primary-50: oklch(0.977 0.007 236);
  --primary-100: oklch(0.954 0.011 232);
  --primary-200: oklch(0.905 0.02 232);
  --primary-300: oklch(0.867 0.028 230);
  --primary-400: oklch(0.731 0.05 233);
  --primary-500: oklch(0.606 0.053 237);
  --primary-600: oklch(0.481 0.055 241);
  --primary-700: oklch(0.407 0.071 237);
  --primary-800: oklch(0.333 0.061 239);
  --primary-900: oklch(0.276 0.049 239);
  --primary-950: oklch(0.212 0.038 239);

  /* Unchanged: this is the confidence scale, not brand colour. `confidence.ts` and the
     detail panel's correct-answer tick are its only consumers. */
  --accent-50: oklch(0.971 0.013 160);
  --accent-100: oklch(0.942 0.039 160);
  --accent-200: oklch(0.885 0.082 160);
  --accent-300: oklch(0.799 0.129 160);
  --accent-400: oklch(0.696 0.155 160);
  --accent-500: oklch(0.627 0.155 160);
  --accent-600: oklch(0.522 0.134 160);
  --accent-700: oklch(0.428 0.109 160);
  --accent-800: oklch(0.355 0.088 160);
  --accent-900: oklch(0.305 0.071 160);
  --accent-950: oklch(0.235 0.048 160);

  /* Neutrals are Tailwind's `zinc` (hue 286), not `gray` (hue 264) — the mock's greys
     match zinc stop for stop. The mock uses five hairline greys spanning 3% lightness;
     they are collapsed to three here on purpose. */
  --canvas: oklch(0.985 0 0);
  --sidebar: oklch(0.988 0 0);
  /* `--surface` is the panel/card/button fill the app spelled `bg-white` in 43 places.
     A token rather than the literal so one line moves every panel in dark mode. Note it
     is LIGHTER than --canvas here: the design floats white panels on a faintly grey
     page, and that relationship inverts in dark mode. */
  --surface: oklch(1 0 0);
  --surface-hover: oklch(96.7% 0.001 286.375); /* zinc-100 */
  --surface-active: oklch(92% 0.004 286.32); /* zinc-200 */
  --hairline: oklch(0.947 0.003 286);
  --hairline-soft: oklch(0.963 0.002 286);
  --hairline-strong: oklch(0.92 0.004 286);
  --divider: oklch(0.896 0.005 286);
  --icon: oklch(0.653 0.013 286);
  --surface-sunken: oklch(0.967 0.001 286);
  /* The wash behind a modal and behind the command palette. Both hardcoded the same
     `oklch(0.24 0.083 275 / 0.35)`, and `CommandPalette` carried a comment saying "the
     same wash `Modal` uses, so the two overlays cannot drift apart" — a comment doing a
     token's job. Named `--scrim` rather than `--color-scrim` for `--elevation-overlay`'s
     reason: the `@theme inline` mapping must not be self-referential. */
  --scrim: oklch(0.24 0.083 275 / 0.35);

  /* Ink. Five levels, which is what the app actually uses. The `gray-*` half of each
     pair the app had been mixing is folded into the `zinc-*` one: the two ramps sit
     within 0.4% lightness of each other and differ only in hue (264 vs 286), and
     `zinc` is what the mock matches stop for stop. */
  --fg: oklch(21% 0.006 285.885); /* zinc-900 — headings, card faces */
  --fg-body: oklch(37% 0.013 285.805); /* zinc-700 — body text, secondary buttons */
  --fg-muted: oklch(44.2% 0.017 285.786); /* zinc-600 — menu items */
  /* The two light steps are set by contrast, not by a palette stop, which is why these
     two alone carry no `zinc-*` name. They were zinc-500 and zinc-400, and axe flagged
     both on every screen in the app the first time `e2e/tests/a11y` ran: zinc-400 on
     white is 2.63:1 against WCAG AA's 4.5:1, and zinc-500 on `--surface-sunken` is
     4.39:1 — close enough to look fine and still short.

     L 0.54 is the lightest ink that clears 4.5:1 on all four grounds the app paints
     text on: `--surface` (#fff), `--canvas` (#fafafa), `--surface-sunken` (#f4f4f5) and
     the selected sidebar row (#f3f8fc). So `--fg-subtle` sits just inside it, and
     `--fg-soft` drops far enough to keep a step between the two without crowding
     `--fg-muted` at 44.2%. **Lightening either one puts the app back under AA**, and
     the a11y suite says so on every screen rather than in one place. */
  --fg-soft: oklch(48.5% 0.016 285.938); /* captions, meta, table headers — 5.85:1 worst */
  --fg-subtle: oklch(53% 0.015 286.067); /* hints, decorative icons — 4.82:1 worst */
  --fg-on-primary: oklch(1 0 0); /* label text on a brand or danger fill */

  /* Destructive actions. Deliberately NOT aliased to --due-over-*: that pair is the
     "overdue" status chip, a softer red at L 0.501, and a delete button borrowing it
     would drag the chip's colour along whenever the button was retuned. */
  --danger: oklch(97.1% 0.013 17.38); /* red-50 — subtle fill */
  --danger-border: oklch(88.5% 0.062 18.334); /* red-200 */
  --danger-border-strong: oklch(80.8% 0.114 19.571); /* red-300 */
  /* One step past -strong, and only used for the border of an invalid field while it has
     focus. Without it the field's border does not change on focus, which is the one
     signal that it is the field being edited. */
  --danger-border-focus: oklch(70.4% 0.191 22.216); /* red-400 */
  --danger-fg: oklch(57.7% 0.245 27.325); /* red-600 — text, icons */
  --danger-fg-strong: oklch(50.5% 0.213 27.518); /* red-700 — headings */
  /* One step brighter than -fg, for an icon or stroke sitting beside -fg-strong text.
     The confidence ramp uses the pair; collapsing them flattens it to one colour. */
  --danger-accent: oklch(63.7% 0.237 25.331); /* red-500 */
  --danger-solid: oklch(57.7% 0.245 27.325); /* red-600 — destructive button fill */
  --danger-solid-hover: oklch(50.5% 0.213 27.518); /* red-700 */

  /* Warnings. Distinct from --glyph-* (the folder-icon amber) for the same reason
     danger is distinct from due-over. */
  --warn: oklch(98.7% 0.022 95.277); /* amber-50 */
  --warn-border: oklch(87.9% 0.169 91.605); /* amber-300 */
  --warn-fg: oklch(55.5% 0.163 48.998); /* amber-700 */
  --warn-fg-strong: oklch(47.3% 0.137 46.201); /* amber-800 */
  --warn-accent: oklch(76.9% 0.188 70.08); /* amber-500 — the -fg pair, as with danger */

  /* Something checked and fine: a passed publish check, a listing that is live. The
     app's first green, so it is its own family rather than a primary reused — a pass
     drawn in brand blue reads as a selection, not as a result. */
  --success: oklch(98.2% 0.018 155.826); /* green-50 */
  --success-border: oklch(92.5% 0.084 155.995); /* green-200 */
  --success-fg: oklch(52.7% 0.154 150.069); /* green-700 */
  --success-fg-strong: oklch(44.8% 0.119 151.328); /* green-800 */

  /* The collaborator avatar's identity gradient. Decoration, never behind body text —
     the only thing drawn on it is 10px initials at --fg-on-primary. Tokens rather than
     `via-purple-400 to-pink-400` so the avatar is reachable from the theme layer like
     everything else; it is the one place the app uses a hue outside the palette. */
  --avatar-via: oklch(71.4% 0.203 305.504); /* purple-400 */
  --avatar-to: oklch(71.8% 0.202 349.761); /* pink-400 */

  /* Chip pairs, named so the "New" chip can be changed without knowing it happens to
     equal the active-nav colour. Only the red and amber are new hues.
     The `later` pair was written as `var(--color-zinc-*)`; those are Tailwind's own
     theme variables, which are not in scope in a plain `:root` that is imported before
     `@theme` runs, so they are resolved to their literal zinc-100/zinc-600 values. */
  --due-over-bg: oklch(0.956 0.019 22);
  --due-over-fg: oklch(0.501 0.181 28);
  --due-new-bg: var(--primary-100);
  --due-new-fg: var(--primary-700);
  --due-later-bg: oklch(96.7% 0.001 286.375);
  --due-later-fg: oklch(44.2% 0.017 285.786);
  --glyph-bg: oklch(0.962 0.029 81);
  --glyph-fg: oklch(0.619 0.125 71);

  /* The four session grades. Each is a foreground, a chip fill and a border.
     Six of the twelve are colours the palette already carries under another name —
     Again is the overdue red, Hard's fill is the folder-glyph amber, Good is brand —
     so they alias rather than restate. Only the greens and two of the borders are new. */
  --grade-again-fg: var(--due-over-fg);
  --grade-again-bg: var(--due-over-bg);
  --grade-again-border: oklch(0.895 0.03 22.8);
  --grade-hard-fg: oklch(0.509 0.103 70.8);
  --grade-hard-bg: var(--glyph-bg);
  --grade-hard-border: oklch(0.908 0.037 82.2);
  --grade-good-fg: var(--primary-800);
  --grade-good-bg: var(--primary-100);
  --grade-good-border: var(--primary-200);
  --grade-easy-fg: oklch(0.472 0.091 160.6);
  --grade-easy-bg: oklch(0.96 0.014 162.5);
  --grade-easy-border: oklch(0.9 0.027 163.1);

  /* The design is flat: every surface is separated by a 1px hairline, so the panel,
     raised and brand shadow tokens are gone. Only floating overlays keep a shadow,
     retuned from brand-violet to neutral.
     Named --elevation-* rather than --shadow-* so the @theme inline mapping in index.css
     is not self-referential. Both spellings happen to work against tailwindcss 4.3.3 —
     the literal is emitted after @theme's block and wins — but only by source order.
     The landing site uses the same rename for the same reason. */
  --elevation-overlay: 0 8px 24px oklch(0.21 0.006 286 / 0.12), 0 2px 6px oklch(0.21 0.006 286 / 0.08);
}

/* The account's own rules, on top of tokens.css (served after it, as one
 * stylesheet). Only var(--...) colours: every literal colour is in tokens.css.
 * Fonts are self-hosted; the font URLs are served by the binary. */

@font-face {
  font-family: "Inter Variable";
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url(/assets/fonts/inter-5.3.0-cyrillic-wght-normal.woff2) format("woff2-variations");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

@font-face {
  font-family: "Inter Variable";
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url(/assets/fonts/inter-5.3.0-latin-ext-wght-normal.woff2) format("woff2-variations");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308,
    U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113,
    U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Inter Variable";
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url(/assets/fonts/inter-5.3.0-latin-wght-normal.woff2) format("woff2-variations");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304,
    U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

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

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--canvas);
  color: var(--fg-body);
  font-family: "Inter Variable", system-ui, sans-serif;
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

a {
  color: var(--primary-700);
  text-underline-offset: 2px;
}

a:hover {
  color: var(--primary-900);
}

:focus-visible {
  outline: 2px solid var(--primary-500);
  outline-offset: 2px;
}

/* The header: the mark and the word, linking home. */
.top {
  padding: 20px 24px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--fg);
  text-decoration: none;
  font-weight: 650;
  letter-spacing: -0.01em;
}

.brand svg {
  width: 26px;
  height: 26px;
  color: var(--primary-800);
}

.brand span {
  color: var(--fg-soft);
  font-weight: 500;
}

/* One column, one panel: every screen here is a short form or a short list. */
main {
  flex: 1;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  padding: 24px 16px 64px;
}

.panel {
  width: 100%;
  max-width: 420px;
  background: var(--surface);
  border: 1px solid var(--hairline-strong);
  border-radius: 12px;
  padding: 32px;
}

.panel.wide {
  max-width: 560px;
}

h1 {
  margin: 0 0 8px;
  color: var(--fg);
  font-size: 22px;
  line-height: 1.3;
  font-weight: 650;
  letter-spacing: -0.015em;
}

h2 {
  margin: 24px 0 8px;
  color: var(--fg);
  font-size: 16px;
  font-weight: 600;
}

p {
  margin: 0 0 12px;
}

.lede {
  color: var(--fg-soft);
}

.foot {
  padding: 16px 24px 24px;
  color: var(--fg-soft);
  font-size: 13px;
  text-align: center;
}

/* Forms, for the screens that follow. Defined once here so every screen
 * looks the same. */
form {
  margin: 0;
}

label {
  display: block;
  margin: 16px 0 6px;
  color: var(--fg);
  font-size: 14px;
  font-weight: 550;
}

input[type="email"],
input[type="password"],
input[type="text"] {
  display: block;
  width: 100%;
  padding: 9px 12px;
  border: 1px solid var(--divider);
  border-radius: 8px;
  background: var(--surface);
  color: var(--fg);
  font: inherit;
}

input:focus-visible {
  outline: none;
  border-color: var(--primary-500);
  box-shadow: 0 0 0 3px var(--primary-100);
}

input[aria-invalid="true"] {
  border-color: var(--danger-border-strong);
}

.hint {
  margin-top: 6px;
  color: var(--fg-subtle);
  font-size: 13px;
}

.button {
  display: inline-flex;
  justify-content: center;
  align-items: center;
  gap: 8px;
  width: 100%;
  margin-top: 24px;
  padding: 10px 16px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: var(--primary-800);
  color: var(--fg-on-primary);
  font: inherit;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}

.button:hover {
  background: var(--primary-900);
  color: var(--fg-on-primary);
}

.button.secondary {
  border-color: var(--divider);
  background: var(--surface);
  color: var(--fg-body);
}

.button.secondary:hover {
  background: var(--surface-hover);
}

.button.danger {
  background: var(--danger-solid);
}

.button.danger:hover {
  background: var(--danger-solid-hover);
}

.notice {
  margin: 16px 0;
  padding: 10px 12px;
  border: 1px solid var(--hairline-strong);
  border-radius: 8px;
  background: var(--surface-sunken);
  font-size: 14px;
}

.notice.error {
  border-color: var(--danger-border);
  background: var(--danger);
  color: var(--danger-fg-strong);
}

.notice.success {
  border-color: var(--success-border);
  background: var(--success);
  color: var(--success-fg-strong);
}

@media (max-width: 480px) {
  .panel {
    padding: 24px 20px;
  }
}

/* A line under a form: the way to the next screen. */
.aside {
  margin: 16px 0 0;
  color: var(--fg-soft);
  font-size: 14px;
}

.panel .button + .button {
  margin-top: 12px;
}

/* The account page: what the account is, as label and value rows. */
.facts {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 8px 16px;
  margin: 16px 0 0;
  font-size: 14px;
}

.facts dt {
  color: var(--fg-soft);
}

.facts dd {
  margin: 0;
  color: var(--fg);
  overflow-wrap: anywhere;
}

/* The products a person has signed in to, one row each. */
.products {
  margin: 8px 0 0;
  padding: 0;
  list-style: none;
}

.products li {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 12px 0;
  border-top: 1px solid var(--hairline-strong);
}

.products .name {
  color: var(--fg);
  font-weight: 600;
}

.products .when {
  color: var(--fg-subtle);
  font-size: 13px;
}

form + form .button {
  margin-top: 12px;
}
