/* ============================================================
   EazyCal shared UI polish
   Home/Gym dashboard is the visual source of truth.
   CSS-only: no layout, routing, state, API, or data changes.
   ============================================================ */

/* Colour/shape roles come straight from css/tokens.css Tier 2 — the parallel
   --ec-* layer this file used to define is gone (same resolved values). */

body {
  color: var(--text-ink);
  text-rendering: optimizeLegibility;
}

button,
input,
select,
textarea {
  font-family: var(--font-display);
}

:where(button, a, input, select, textarea, [role="button"], [tabindex]):focus-visible {
  /* The token, not a translucent literal: rgba(168,85,247,.48) measured
     1.13–1.93:1 against its own surroundings (audit 2026-11-02 TOK-001),
     under the 3:1 a focus indicator needs (WCAG 2.2 SC 1.4.11). */
  outline: var(--focus-outline);
  outline-offset: var(--focus-ring-offset);
  box-shadow: var(--focus-ring-soft);
}

/* Where a dialog puts focus when it opens (core/modal-ins-chart.js openDialog):
   its title, made focusable only so a screen reader starts there. It is not a
   control, so it draws no ring; the first Tab lands on a control that does. */
[data-dialog-start]:focus {
  outline: none;
  box-shadow: none;
}

:where(button, .btn, .admin-tab):disabled {
  cursor: not-allowed;
  opacity: 0.6;
  transform: none;
  box-shadow: none;
}

/* ── The one scrollbar ────────────────────────────────────────────────────
   Opt in with `u-scroll` on anything that scrolls. It lives here because this
   is the only shared sheet BOTH entry points load — base.css, where the other
   .u-* utilities sit, is index.html-only, so a rule there never reaches admin.

   Why the pseudo-elements rather than `scrollbar-width`/`scrollbar-color`,
   which are the standard: on Windows, Chrome draws the platform bar for both
   standard values. `thin` is merely narrower — measured 10px against auto's
   15px — and keeps the grey track and an arrow button at either end; adding
   `scrollbar-color` recolours the thumb and leaves the arrows. The
   pseudo-elements are the only route that removes them, and the track with
   them.

   The two families must never meet on one element. Since Chrome 121 a
   non-auto `scrollbar-width`/`scrollbar-color` makes that element's
   ::-webkit-scrollbar rules dead: measured here, a box declaring `thin` plus a
   30px webkit width comes out 10px, while the same webkit rule alone comes out
   30px. Seven blocks in this tree shipped both and had been drawing nothing
   since. So the standard pair is stated behind `@supports not
   selector(::-webkit-scrollbar)` — where Chromium never reads it — instead of
   beside rules it would silently cancel. `not` is the safe half of that query:
   an engine answering it wrongly falls back to its own default bar, never to a
   fat one we forced on it.

   tests/scrollbar-contract.test.js holds the pairing rule for every stylesheet,
   so the next scroller cannot re-learn it the way those seven did. */
.u-scroll {
  /* The gutter is what the LAYOUT pays for; the visible thumb is what is left
     once the transparent ring is taken off either side. Declared as the pair
     they are, so neither can be tuned into the other's territory by accident. */
  --scroll-gutter: 8px;
  --scroll-inset: 2px;
}

.u-scroll::-webkit-scrollbar {
  width: var(--scroll-gutter);
  height: var(--scroll-gutter);
}

/* No track and no corner: the bar IS the thumb, floating on whatever surface
   the scroller already paints. */
.u-scroll::-webkit-scrollbar-track,
.u-scroll::-webkit-scrollbar-corner {
  background: transparent;
}

.u-scroll::-webkit-scrollbar-thumb {
  border: var(--scroll-inset) solid transparent;
  border-radius: var(--r-pill);
  /* padding-box makes the border read as clearance rather than as thumb: the
     grab target stays the full gutter while the ink is only the middle of it.
     Set once, and the states below move `background-color` — never the
     `background` shorthand, which would reset this clip back to border-box. */
  background-clip: padding-box;
  /* Gray-400, not the lighter Gray-300 that --surface-muted resolves to: at the
     4px this geometry leaves visible, Gray-300 washes out against the panel and
     stops answering the only question a resting bar is asked — is there more
     below? Compared side by side at 3× before choosing. */
  background-color: var(--text-tertiary);
}

.u-scroll::-webkit-scrollbar-thumb:hover {
  background-color: var(--text-secondary);
}

@supports not selector(::-webkit-scrollbar) {
  .u-scroll {
    scrollbar-width: thin;
    scrollbar-color: var(--text-tertiary) transparent;
  }
}

/* Surfaces */
:where(
  .auth-modal-content,
  .upload-modal-content,
  .edit-profile-modal,
  .add-topic-content,
  .quiz-modal-content,
  .ins-chart-card,
  .ins-card,
  .ins-kpi-card,
  .ins2-stats-card,
  .ins2-heatmap-card,
  .ins2-mastery-card,
  .form-card,
  .topic-main-card,
  .topic-summary-drawer
) {
  border: 1px solid var(--border-subtle);
  background: var(--surface-glass-strong);
  box-shadow: var(--shadow-card);
}

:where(.auth-modal-content, .upload-modal-content, .edit-profile-modal, .add-topic-content, .quiz-modal-content) {
  border-radius: 24px;
}

:where(.ins-chart-card, .ins-card, .ins-kpi-card, .ins2-stats-card, .ins2-heatmap-card, .ins2-mastery-card, .form-card, .topic-main-card) {
  border-radius: var(--r-card);
}

/* Type and muted text */
:where(
  .auth-form h2,
  .upload-area h3,
  .add-topic-title,
  .quiz-modal-title,
  .ins-chart-title,
  .ins-card-title,
  .ins-kpi-val,
  .ins2-kpi-val,
  .topic-summary-title,
  .topic-main-name,
  .form-card h2
) {
  color: var(--text-ink);
  letter-spacing: 0;
}

:where(.profile-email, .form-group label, .upload-hint, .add-topic-sub, .quiz-modal-sub, .ins-kpi-lbl, .topic-main-pill) {
  color: var(--text-tertiary);
}

/* Inputs */
:where(
  .form-group input,
  .form-group select,
  .form-group textarea,
  .search-input,
  .filter-select,
  .topic-summary-search,
  .topic-summary-filter,
  .ec-stat-select,
  .mst-sort-select
) {
  border: 1.5px solid var(--border-subtle);
  border-radius: var(--r-control-lg);
  background: color-mix(in srgb, var(--surface-card) 86%, transparent);
  color: var(--text-ink);
  box-shadow: none;
}

:where(
  .form-group input,
  .form-group select,
  .form-group textarea,
  .search-input,
  .filter-select,
  .topic-summary-search,
  .topic-summary-filter,
  .ec-stat-select,
  .mst-sort-select
):focus {
  border-color: rgba(168, 85, 247, 0.46);
  background: var(--surface-card);
  box-shadow: var(--focus-ring-soft);
  outline: none;
}

/* Buttons, tabs, badges */
:where(.btn, .stats-action-btn, .topic-summary-export, .admin-tab) {
  border-radius: var(--r-pill);
  font-weight: 700;
  transition: transform 0.16s ease, box-shadow 0.16s ease, background 0.16s ease, color 0.16s ease, border-color 0.16s ease;
}

:where(.btn-primary, .btn-pink, .admin-tab.active, .edit-profile-tab.active) {
  border-color: transparent;
  background: var(--gradient-brand);
  color: var(--white);
  box-shadow: 0 8px 22px rgba(168, 85, 247, 0.22);
}

:where(.btn-outline, .btn-gray, .admin-tab) {
  border: 1px solid var(--border-subtle);
  background: color-mix(in srgb, var(--surface-card) 76%, transparent);
  color: var(--text-ink-soft);
}

:where(.btn, .admin-tab, .stats-action-btn, .topic-summary-export):hover {
  box-shadow: var(--shadow-card);
}

:where(.edit-profile-tabs, .admin-tabs) {
  border: 1px solid var(--border-subtle);
  border-radius: var(--r-control-lg);
  background: rgba(245, 240, 255, 0.9);
  background: light-dark(rgba(245, 240, 255, 0.9), rgba(38, 30, 61, 0.9));
}

:where(.ins-badge, .add-topic-count) {
  border: 1px solid rgba(255, 94, 145, 0.18);
  border-radius: var(--r-pill);
  background: rgba(255, 240, 247, 0.86);
  background: light-dark(rgba(255, 240, 247, 0.86), rgba(44, 27, 40, 0.86));
  color: var(--pink-700);
  color: light-dark(var(--pink-700), rgba(249, 168, 212, 1));
}

.upload-area {
  border-color: rgba(168, 85, 247, 0.3); /* one-off emphasised dropzone border (was --ec-border-strong) */
  border-radius: 24px;
  background: linear-gradient(145deg, color-mix(in srgb, var(--surface-card) 86%, transparent), color-mix(in srgb, var(--surface-accent-soft) 82%, transparent));
}

.add-topic-header,
.topic-summary-head {
  border-bottom-color: var(--border-subtle);
  background: linear-gradient(180deg, color-mix(in srgb, var(--surface-accent-soft) 96%, transparent), color-mix(in srgb, var(--surface-card) 92%, transparent));
}

.admin-header {
  border-bottom: 1px solid var(--border-subtle);
  background: color-mix(in srgb, var(--surface-card) 90%, transparent);
  box-shadow: var(--shadow-card);
}

.logo-icon {
  background: var(--gradient-brand);
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
    transition-duration: 0.01ms !important;
  }
}
