@layer components {
  /* ── buttons: every button is a pill ── */
  .pill {
    display: inline-flex; align-items: center; justify-content: center; gap: 10px;
    min-height: 40px; padding: 9px 18px; border-radius: var(--r-pill);
    border: 1px solid transparent; background: transparent; color: var(--fg);
    font-weight: 700; font-size: var(--fs-body-sm); letter-spacing: -0.01em; white-space: nowrap; text-decoration: none;
    transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast), transform var(--t-fast) var(--ease-spring);
    &:active:not(:disabled) { transform: scale(.98); }
    &:disabled { opacity: .5; cursor: not-allowed; }
    &.pri { background: var(--btn-bg); color: var(--btn-fg); }
    &.pri:hover:not(:disabled) { background: color-mix(in oklch, var(--btn-bg) 88%, var(--grad-b)); }
    &.gh { border-color: var(--line-2); }
    &.gh:hover:not(:disabled) { background: var(--surface-2); }
    &.danger { border-color: color-mix(in oklch, var(--wrong) 50%, var(--line-2)); color: var(--wrong); }
    &.danger:hover:not(:disabled) { background: color-mix(in oklch, var(--wrong) 10%, transparent); }
    &.sm { min-height: 32px; padding: 5px 13px; font-size: var(--fs-sm); }
    /* the one thing a page wants you to do next */
    &.lg { min-height: 48px; padding: 12px 24px; font-size: var(--fs-md); }
    &.block { width: 100%; }
    & kbd { background: transparent; border-color: color-mix(in oklch, currentColor 30%, transparent); color: inherit; opacity: .7; }
    & svg { width: 16px; height: 16px; flex: none; }
  }
  .link-btn {
    border: 0; background: none; padding: 0; color: var(--fg); font-weight: 600;
    text-decoration: underline; text-decoration-color: var(--line-2); text-underline-offset: 3px;
    &:hover { text-decoration-color: currentColor; }
  }

  /* icon button: small, round, quiet until hovered. Every close, remove and tool button, e.g.
     h('button', { type: 'button', class: 'icon-btn', 'aria-label': 'close' }, icon('x')) */
  .icon-btn {
    width: 30px; height: 30px; padding: 0; border-radius: 50%; display: grid; place-items: center; flex: none;
    border: 0; background: transparent; color: var(--muted);
    transition: background var(--t-fast), color var(--t-fast);
    & svg { width: 14px; height: 14px; }
    &:hover:not(:disabled) { color: var(--fg); background: var(--surface-2); }
    &:disabled { opacity: .45; cursor: not-allowed; }
  }

  kbd {
    font-family: var(--mono); font-size: var(--fs-label); line-height: 1; font-weight: 500;
    padding: 3px 6px; border-radius: var(--r-item); border: 1px solid var(--line-2); color: var(--muted); background: var(--surface);
  }
  /* Offline: what you see is the copy from when you were last online (sw.js). */
  .offline-strip {
    position: fixed; z-index: 55; left: 50%; bottom: calc(14px + env(safe-area-inset-bottom, 0px)); translate: -50% 0;
    width: max-content; max-width: calc(100vw - 32px); text-align: center;
    margin: 0; padding: 5px 12px; border-radius: var(--r-pill); border: 1px solid var(--line-2); background: var(--surface);
    font-family: var(--mono); font-size: var(--fs-label); letter-spacing: var(--track-label); color: var(--muted);
    box-shadow: var(--shadow-float); pointer-events: none;
    &[hidden] { display: none; }
  }
  /* key hints mean nothing without a keyboard */
  @media (hover: none) and (pointer: coarse) { kbd { display: none; } }

  .chip {
    display: inline-flex; align-items: center; gap: 7px; white-space: nowrap;
    border: 1px solid var(--line-2); border-radius: var(--r-pill); padding: 3px 11px;
    font-size: var(--fs-sm); font-weight: 600; color: var(--fg-2);
  }
  .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--muted); flex: none; }
  .dot.known { background: var(--known); } .dot.learning { background: var(--learning); }
  .dot.due { background: var(--due); } .dot.right { background: var(--right); } .dot.wrong { background: var(--wrong); }
  .dot.ready { background: transparent; box-shadow: inset 0 0 0 1.5px var(--fg); }
  .dot.new { background: transparent; box-shadow: inset 0 0 0 1.5px var(--faint); }

  .card { border: 1px solid var(--line); border-radius: var(--r-card); background: var(--surface); padding: var(--pad-card); }

  /* The one label: mono, small, quiet. Section labels, counts, metadata, eyebrows. Copy is lowercase
     at the source; no text-transform, so a class called "calculus I" keeps its capital. */
  .label, .eyebrow, .sb-label {
    font-family: var(--mono); font-size: var(--fs-label); font-weight: 500; line-height: 1.4;
    letter-spacing: var(--track-label); color: var(--muted);
  }
  .h-page { font-size: var(--fs-3xl); letter-spacing: -0.05em; line-height: 1.02; }
  .h-sec { font-size: var(--fs-xl); letter-spacing: -0.035em; }
  .lede { color: var(--fg-2); font-size: var(--fs-lg); max-width: 60ch; }

  /* ── form fields ── */
  .field { display: grid; gap: 7px; }
  .field > label, .field-label { font-size: var(--fs-sm); font-weight: 700; color: var(--fg); }
  .field .hint { font-size: var(--fs-meta); color: var(--muted); }
  .field .err { font-size: var(--fs-meta); color: var(--wrong); font-weight: 600; }
  .input {
    width: 100%; min-height: 44px; padding: 10px 14px; border-radius: var(--r-input);
    border: 1px solid var(--line-2); background: var(--surface); color: var(--fg); font-size: var(--fs-md);
    transition: border-color var(--t-fast), box-shadow var(--t-fast);
    &::placeholder { color: var(--muted); }
    &:hover { border-color: color-mix(in oklch, var(--fg) 25%, var(--line-2)); }
    &:focus-visible {
      outline: none; border-color: color-mix(in oklch, var(--fg) 45%, transparent);
      box-shadow: 0 0 0 4px color-mix(in oklch, var(--focus) 20%, transparent);
    }
    &[aria-invalid="true"] { border-color: var(--wrong); }
  }
  .form { display: grid; gap: 16px; }
  .form > .pill:not(.block) { justify-self: start; }
  .form-error {
    padding: 10px 14px; border-radius: var(--r-input); font-size: var(--fs-body-sm); font-weight: 600;
    color: var(--wrong); background: color-mix(in oklch, var(--wrong) 10%, transparent);
    border: 1px solid color-mix(in oklch, var(--wrong) 30%, transparent);
  }
  /* a status line by a form: plain text, no box */
  .form-note { font-size: var(--fs-body-sm); color: var(--fg-2); overflow-wrap: anywhere; }

  /* segmented control: one size everywhere; the picked one is filled. Too wide for its room, it
     scrolls sideways instead of pushing the page out. */
  .seg {
    display: inline-flex; width: fit-content; max-width: 100%; padding: 3px; gap: 2px;
    border-radius: var(--r-pill); border: 1px solid var(--line); background: var(--surface);
    overflow-x: auto; scrollbar-width: none;
    &::-webkit-scrollbar { display: none; }
  }
  .seg button {
    flex: none; border: 0; background: transparent; color: var(--muted); font-weight: 600; font-size: var(--fs-sm); white-space: nowrap;
    padding: 6px 14px; border-radius: var(--r-pill); transition: background var(--t-fast), color var(--t-fast);
    &:hover { color: var(--fg); }
    &:focus-visible { outline-offset: -2px; }
    &[aria-pressed="true"] { background: color-mix(in oklch, var(--fg) 10%, var(--surface)); color: var(--fg); }
    &:disabled { opacity: .5; cursor: not-allowed; }
  }

  /* banner: one line, one action */
  .banner {
    display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px;
    padding: var(--pad-row); border-radius: var(--r-tile); border: 1px solid var(--line); background: var(--surface);
    font-size: var(--fs-body-sm);
    & .dot { margin-right: -4px; }
    & .banner-text { flex: 1 1 260px; }
  }

  /* spinner */
  .spin {
    width: 14px; height: 14px; border-radius: 50%; flex: none;
    border: 1.8px solid color-mix(in oklch, currentColor 25%, transparent); border-top-color: currentColor;
    animation: spin 0.9s linear infinite;
  }
  @keyframes spin { to { transform: rotate(360deg); } }
  @media (prefers-reduced-motion: reduce) { .spin { animation-duration: 3s; } }

  /* the wordmark: in the sidebar, the phone's top bar, the sign-in page */
  .wordmark, .sb-logo { font-weight: 800; font-size: 20px; letter-spacing: -0.05em; color: var(--fg); text-decoration: none; }

  /* sidebar */
  .sb-logo { padding: 2px 10px 16px; }
  .sb-item {
    display: flex; align-items: center; gap: 10px; padding: 7px 10px; border-radius: var(--r-item);
    color: var(--muted); font-weight: 600; font-size: var(--fs-body-sm); text-decoration: none; border: 0; background: none; text-align: left; width: 100%;
    & svg { width: 16px; height: 16px; flex: none; }
    &:hover { color: var(--fg); background: var(--surface-2); }
    &[aria-current="page"] { color: var(--fg); background: var(--surface-2); }
  }
  .sb-label { padding: 18px 10px 6px; }
  .sb-empty { padding: 2px 10px 6px; font-size: var(--fs-meta); color: var(--muted); }
  .sb-subject { color: var(--fg-2); }
  .sb-subject-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .sb-count { font-family: var(--mono); font-size: var(--fs-label); color: var(--due); }
  .sb-foot { margin-top: auto; display: grid; gap: 2px; padding-top: 8px; border-top: 1px solid var(--line); }
  /* you: avatar and name (to settings), level and streak, then sign out */
  .sb-you { display: flex; align-items: center; gap: 2px; }
  .sb-you-main {
    flex: 1; min-width: 0; display: flex; align-items: center; gap: 10px; padding: 7px 10px; border-radius: var(--r-item);
    color: var(--fg-2); font-size: var(--fs-body-sm); font-weight: 600; text-decoration: none;
    &:hover, &[aria-current="page"] { background: var(--surface-2); color: var(--fg); }
  }
  .sb-you .streak { font-size: var(--fs-xs); }
  .sb-you .streak svg { width: 14px; height: 14px; }
  .sb-out { flex: none; color: var(--muted); }
  .sb-search {
    display: flex; align-items: center; justify-content: space-between; gap: 8px; width: 100%;
    padding: 8px 10px; border-radius: var(--r-item); border: 1px solid var(--line); background: var(--surface);
    color: var(--muted); font-size: var(--fs-sm); text-align: left; margin-bottom: 10px;
    &:hover { color: var(--fg); border-color: var(--line-2); }
  }
  .avatar {
    width: 22px; height: 22px; border-radius: var(--r-item); display: grid; place-items: center; flex: none;
    font-size: var(--fs-label); font-weight: 800; color: var(--fg-2); background: var(--surface-2); border: 1px solid var(--line-2);
  }

  /* Toasts are dark in both themes: the usual dark toast on a light page, a raised panel (not a
     white slab) on a dark one. Their own color-scheme flips every light-dark() token inside, so the
     text and dots keep their contrast. A dot only for good or bad news. */
  .toasts {
    position: fixed; z-index: 60; left: 50%; bottom: calc(18px + env(safe-area-inset-bottom, 0px));
    translate: -50% 0; display: grid; gap: 8px; width: min(420px, calc(100vw - 32px)); pointer-events: none;
  }
  .toast {
    color-scheme: dark;
    pointer-events: auto; display: flex; align-items: center; gap: 12px;
    padding: 11px 14px 11px 16px; border-radius: var(--r-tile); border: 1px solid var(--line-2);
    background: var(--surface); color: var(--fg); font-size: var(--fs-body-sm); font-weight: 600; box-shadow: var(--shadow-float);
    animation: toast-in var(--t) var(--ease-spring);
    &[data-tone="error"] .dot { background: var(--wrong); }
    &[data-tone="success"] .dot { background: var(--success); }
    & .toast-msg { flex: 1; }
    & button { border: 0; background: none; color: inherit; font-weight: 700; text-decoration: underline; text-underline-offset: 3px; }
  }
  @keyframes toast-in { from { opacity: 0; translate: 0 8px; } }

  /* Floating panels (dialogs, sheets, the palette, popovers): --surface, a --line-2 border, --r-card
     and --shadow-float, 16px clear of a phone's edges. Every dialog dims the page the same way: the
     scrim, no blur. (The fallback is for browsers whose ::backdrop can't see the tokens.) */
  dialog::backdrop { background: var(--scrim, rgb(0 0 0 / .45)); }
  dialog.modal {
    width: min(460px, calc(100vw - 32px)); padding: 0; border: 1px solid var(--line-2); border-radius: var(--r-card);
    background: var(--surface); color: var(--fg-2); box-shadow: var(--shadow-float);
    &[open] { animation: pop var(--t) var(--ease-liquid); }
    & .modal-body { padding: var(--pad-card) var(--pad-card) 16px; display: grid; gap: 10px; }
    & h2 { font-size: var(--fs-panel); }
    & .modal-actions { display: flex; justify-content: flex-end; gap: 8px; padding: 0 var(--pad-card) var(--pad-card); flex-wrap: wrap; }
  }
  @keyframes pop { from { opacity: 0; scale: .97; } }

  /* command palette */
  dialog.palette {
    width: min(560px, calc(100vw - 32px)); margin-top: 12vh; padding: 0;
    border: 1px solid var(--line-2); border-radius: var(--r-card); background: var(--surface); color: var(--fg-2);
    box-shadow: var(--shadow-float);
    & input { width: 100%; border: 0; border-bottom: 1px solid var(--line); background: transparent; padding: 16px 18px; font-size: var(--fs-field); color: var(--fg); }
    & input:focus-visible { outline: none; }
    & ul { list-style: none; margin: 0; padding: 6px; max-height: 50vh; overflow-y: auto; }
    & li { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 9px 12px; border-radius: var(--r-item); font-size: var(--fs-body-sm); font-weight: 600; cursor: pointer; }
    & li[aria-selected="true"] { background: var(--surface-2); color: var(--fg); }
    & li .hint { font-weight: 400; font-size: var(--fs-meta); color: var(--muted); }
    /* a long name or class is cut, never wrapped: the name keeps the room, its kind and class the rest */
    & .palette-label { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    & li .hint { flex: 0 1 auto; min-width: 0; max-width: 45%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    & .palette-empty { padding: 14px 18px; color: var(--muted); font-size: var(--fs-body-sm); }
    /* on a touch screen the palette itself takes the focus (the keyboard stays down): no ring for that */
    &:focus { outline: none; }
  }

  /* rows: one bordered list, hairlines between its rows */
  .rows { display: grid; border: 1px solid var(--line); border-radius: var(--r-card); background: var(--surface); overflow: hidden; }
  .row { display: flex; align-items: center; gap: 12px 16px; padding: var(--pad-row); border-bottom: 1px solid var(--line); flex-wrap: wrap; }
  .row:last-child { border-bottom: 0; }
  .row .row-main { flex: 1 1 240px; min-width: 0; }
  .row .row-title { color: var(--fg); font-weight: 700; font-size: var(--fs-row); overflow-wrap: anywhere; }
  .row .row-sub { color: var(--muted); font-size: var(--fs-meta); }

  /* meter */
  .meter { position: relative; height: 6px; border-radius: 3px; background: var(--track); overflow: hidden; }
  .meter > i { position: absolute; inset: 0 auto 0 0; border-radius: 3px; background: var(--known); width: var(--v, 0%); transition: width var(--t) var(--ease-liquid); }
  .meter.due > i { background: var(--due); }

  /* rich text from markdown (sanitized) */
  .rich { overflow-wrap: anywhere; }
  .rich > * + * { margin-top: .75em; }
  .rich pre { overflow-x: auto; padding: 12px 14px; border-radius: var(--r-input); background: var(--surface-2); }
  .rich code { background: var(--surface-2); padding: 1px 6px; border-radius: var(--r-item); }
  .rich pre code { background: none; padding: 0; }
  .rich .katex-display { overflow-x: auto; overflow-y: hidden; padding: 4px 0; }
  /* Tables read as tables (and scroll sideways inside themselves when they're wide). */
  .rich table { display: block; max-width: 100%; overflow-x: auto; border-collapse: collapse; font-size: .95em; }
  .rich :is(th, td) { padding: 5px 12px; border-bottom: 1px solid var(--line); text-align: left; vertical-align: top; }
  .rich th { color: var(--fg); font-weight: 700; }
}
