/* Components on top of tokens.css. Every control has rest, hover, focus, pressed, disabled,
   loading (aria-busy="true") and error (aria-invalid="true") states. Why: vault note 36. */

/* Base */
body { margin: 0; background: var(--paper); color: var(--ink); font: 400 var(--text-base)/var(--leading-body) var(--font-body); }
:lang(bn) { line-height: var(--leading-bangla); }
h1, h2, h3, h4 { font-family: var(--font-heading); font-weight: 600; line-height: var(--leading-tight); margin: 0; text-wrap: balance; }
:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.num { font-variant-numeric: tabular-nums; }

/* One state layer for every control (Material 3): the text colour over the fill */
.btn, .chip, .tab, .table tbody tr { background: var(--_bg, transparent); transition: background-color var(--dur-fast), color var(--dur-fast); }
:is(.btn, .chip, .tab):hover:not(:disabled, [aria-disabled="true"], [aria-busy="true"], .chip-tag),
.table tbody tr:hover { background: color-mix(in oklch, currentColor var(--state-hover), var(--_bg, transparent)); }
:is(.btn, .chip, .tab):active:not(:disabled, [aria-disabled="true"], [aria-busy="true"], .chip-tag) { background: color-mix(in oklch, currentColor var(--state-press), var(--_bg, transparent)); }
:is(.btn, .chip, .tab, .input):is(:disabled, [aria-disabled="true"]) { opacity: var(--disabled); cursor: not-allowed; }

/* Loading: spinner in place of the label, size kept so nothing jumps */
.spinner, [aria-busy="true"].btn::after { width: 1em; height: 1em; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: spin .7s linear infinite; }
[aria-busy="true"].btn { color: transparent; position: relative; cursor: progress; }
[aria-busy="true"].btn::after { content: ""; position: absolute; inset: 0; margin: auto; color: var(--_fg, var(--ink)); }
.skeleton { background: linear-gradient(90deg, var(--rule) 30%, color-mix(in oklch, var(--rule) 40%, transparent) 50%, var(--rule) 70%) 0 0 / 300% 100%; border-radius: var(--radius-item); animation: shimmer 1.4s linear infinite; color: transparent; }
@keyframes spin { to { rotate: 1turn; } }
@keyframes shimmer { to { background-position: -150% 0; } }
@media (prefers-reduced-motion: reduce) { .spinner, [aria-busy="true"].btn::after, .skeleton { animation-duration: 2.4s; } }

/* Buttons: primary (solid), tonal (in cards), ghost, danger; sizes sm and lg */
.btn { --_bg: var(--paper-warm); --_fg: var(--ink); color: var(--_fg); display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  height: var(--control-md); padding: 0 var(--space-5); border: 0; border-radius: var(--radius-pill); box-shadow: inset 0 0 0 1px var(--rule-heavy);
  font: 600 var(--text-sm)/1 var(--font-body); white-space: nowrap; text-decoration: none; cursor: pointer; }
.btn-primary { --_bg: var(--accent); --_fg: var(--on-accent); box-shadow: none; }
.btn-tonal { --_bg: var(--accent-soft); --_fg: var(--accent-strong); box-shadow: none; }
.btn-ghost { --_bg: transparent; box-shadow: none; }
.btn-danger { --_bg: var(--sale); --_fg: var(--paper-warm); box-shadow: none; }
.btn-sm { height: var(--control-sm); padding: 0 var(--space-4); font-size: var(--text-xs); }
.btn-lg { height: var(--control-lg); padding: 0 var(--space-6); font-size: var(--text-base); }

/* Fields: label above, hint or error below, error says how to fix it */
.field { display: grid; gap: var(--space-1); }
.field label { font-size: var(--text-sm); font-weight: 600; }
.hint { font-size: var(--text-xs); color: var(--ink-muted); }
.input { box-sizing: border-box; width: 100%; min-height: var(--control-md); padding: var(--space-2) var(--space-3); border: 1px solid var(--ink-muted); border-radius: var(--radius-input); /* 3:1 edge (WCAG 1.4.11) */
  background: var(--paper-warm); color: var(--ink); font: inherit; transition: border-color var(--dur-fast); }
.input::placeholder { color: var(--ink-muted); }
.input:hover:not(:disabled, :focus) { border-color: var(--ink); }
.input:focus { outline: 2px solid var(--focus); outline-offset: -1px; border-color: var(--focus); }
.input[aria-invalid="true"] { border-color: var(--sale); }
.input[aria-invalid="true"]:focus { outline-color: var(--sale); }
.error { font-size: var(--text-xs); color: var(--sale); font-weight: 600; }
.error::before { content: "⚠ "; } /* not colour alone (WCAG 1.4.1) */
.input-wrap { position: relative; }
.input-wrap .spinner { position: absolute; right: var(--space-3); top: 0; bottom: 0; margin: auto; color: var(--ink-muted); }

/* Cards: white on paper with a hairline, no shadow (note 29); a whole-card link lifts its edge on hover */
.card { background: var(--paper-warm); box-shadow: var(--edge); border-radius: var(--radius-card); padding: var(--space-5); color: inherit; text-decoration: none; display: block; }
a.card { transition: box-shadow var(--dur-fast); }
a.card:hover { box-shadow: inset 0 0 0 1px var(--rule-heavy); }
.card[aria-invalid="true"] { box-shadow: inset 0 0 0 1px var(--sale); }

/* Chips: filters and tags; selected = aria-pressed; a tag (not clickable) is .chip-tag */
.chip { --_fg: var(--ink-soft); color: var(--_fg); display: inline-flex; align-items: center; gap: var(--space-1); height: var(--control-sm); padding: 0 var(--space-3);
  border: 0; border-radius: var(--radius-pill); box-shadow: inset 0 0 0 1px var(--rule-heavy); font: 500 var(--text-sm)/1 var(--font-body); cursor: pointer; }
.chip[aria-pressed="true"] { --_bg: var(--accent-soft); --_fg: var(--accent-strong); box-shadow: inset 0 0 0 1px var(--accent); }
.chip-tag { height: auto; padding: 2px var(--space-2); border-radius: 6px; box-shadow: none; --_bg: var(--accent-soft); --_fg: var(--accent-strong); font-size: var(--text-xs); cursor: default; }

/* Tabs: role="tablist" > role="tab" with aria-selected */
.tabs { display: flex; gap: var(--space-1); border-bottom: 1px solid var(--rule); overflow-x: auto; }
.tab { --_fg: var(--ink-muted); color: var(--_fg); height: var(--control-md); padding: 0 var(--space-4); border: 0; border-radius: var(--radius-item) var(--radius-item) 0 0;
  font: 500 var(--text-sm)/1 var(--font-body); cursor: pointer; white-space: nowrap; box-shadow: inset 0 -2px 0 transparent; margin-bottom: -1px; }
.tab[aria-selected="true"] { --_fg: var(--ink); box-shadow: inset 0 -2px 0 var(--accent); font-weight: 600; }

/* Table: tabular numbers, sticky head, row hover; scrolls sideways inside its own box on phones */
.table-wrap { overflow-x: auto; border-radius: var(--radius-card); box-shadow: var(--edge); background: var(--paper-warm); }
.table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); font-variant-numeric: tabular-nums; }
.table th { position: sticky; top: 0; background: var(--paper-warm); text-align: left; font-weight: 600; color: var(--ink-muted); font-size: var(--text-xs); }
.table th, .table td { padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--rule); white-space: nowrap; }
.table tbody tr:last-child td { border-bottom: 0; }
.table .end { text-align: right; }
.table .table-empty { padding: var(--space-6); text-align: center; color: var(--ink-muted); white-space: normal; }

/* Toast: a region with role="status" (aria-live) at the bottom; error toasts use role="alert" */
.toasts { position: fixed; inset: auto var(--space-4) var(--space-4); display: grid; gap: var(--space-2); justify-items: center; z-index: 50; pointer-events: none; }
.toast { color-scheme: dark; /* always the dark palette, so status icons pass 3:1 */ pointer-events: auto; display: flex; align-items: center; gap: var(--space-3); max-width: 28rem; padding: var(--space-3) var(--space-4); border-radius: var(--radius-item);
  background: var(--ink-fill); color: var(--on-fill); box-shadow: var(--shadow-lg); font-size: var(--text-sm); animation: arrive var(--dur) var(--ease-arrive); }
.toast-ok::before { content: "✓"; color: var(--ok); font-weight: 700; }
.toast-error::before { content: "⚠"; color: var(--sale); }
.toast .btn { --_fg: var(--on-fill); margin-left: auto; height: var(--control-sm); }

/* Dialog: native <dialog> (focus trap, Esc, top layer for free) */
.dialog { border: 0; padding: var(--space-6); width: min(32rem, calc(100% - 2 * var(--space-4))); border-radius: var(--radius-card); background: var(--paper-warm); color: var(--ink); box-shadow: var(--shadow-lg); }
.dialog[open] { animation: arrive var(--dur) var(--ease-arrive); }
.dialog::backdrop { background: color-mix(in oklch, var(--ink-fill) 55%, transparent); }
.dialog-actions { display: flex; justify-content: flex-end; gap: var(--space-2); margin-top: var(--space-5); flex-wrap: wrap; }
@keyframes arrive { from { opacity: 0; translate: 0 8px; } }
