/* Layout is built from two elements:
     .panel  a titled region of the page (implicit containment: no box, set apart
             by spacing and a label heading) that groups related cards.
     .card   one subject (a number, a chart, a table) on an outlined surface
             (explicit containment).
   Mobile first; colours follow the system light/dark setting. */

:root {
  color-scheme: light;
  --color-page: #f6f6f3;
  --color-surface: #ffffff;
  --color-text: #1b1b1a;
  --color-muted: #6b6a65;
  --color-border: #e3e2dc;
  --color-accent: #2a78d6;
  --color-accent-soft: #eaf1fb;
  --color-better: #2a78d6;
  --color-worse: #d03b3b;
  --color-up: #1a7f37;
  --color-down: #c93434;
  --color-neutral: #c3c2b7;

  --font-body: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-mono: ui-monospace, Menlo, "DejaVu Sans Mono", Consolas, monospace;
  --radius-card: 12px;
  --radius-control: 8px;
  --space-panel: 2rem;
  --space-card: 1.25rem;
  --content-width: 64rem;
}

@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;
    --color-page: #111110;
    --color-surface: #1a1a19;
    --color-text: #f0efe9;
    --color-muted: #a3a29b;
    --color-border: #2c2c2a;
    --color-accent: #3987e5;
    --color-accent-soft: #1b2a3d;
    --color-better: #3987e5;
    --color-worse: #e66767;
    --color-up: #3fb950;
    --color-down: #f0706a;
    --color-neutral: #5c5b56;
  }
}

/* ---------------------------------------------------------------- base */

[hidden] {
  display: none !important;
}

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

body {
  margin: 0;
  background: var(--color-page);
  color: var(--color-text);
  font: 16px/1.5 var(--font-body);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, p, figure, table, ul, ol {
  margin: 0;
}

ul,
ol {
  padding: 0;
  list-style: none;
}

a {
  color: var(--color-accent);
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.skip-link {
  position: absolute;
  left: 1rem;
  top: -3rem;
}

.skip-link:focus {
  top: 1rem;
}

.icon-sprite {
  display: none;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* ---------------------------------------------------------------- layout */

.site-header,
.site-main,
.site-footer {
  width: 100%;
  max-width: var(--content-width);
  margin: 0 auto;
  padding-left: 1rem;
  padding-right: 1rem;
}

.site-main {
  display: grid;
  gap: var(--space-panel);
  padding-bottom: var(--space-panel);
}

/* ---------------------------------------------------------------- panels */

.panel {
  display: grid;
  gap: 0.75rem;
  min-width: 0;
}

.panel__title {
  color: var(--color-muted);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.panel__note {
  color: var(--color-muted);
  font-size: 0.875rem;
}

.panel__cards {
  display: grid;
  gap: 1rem;
}

@media (min-width: 48rem) {
  .panel__cards--pair {
    grid-template-columns: 1fr 1fr;
  }

  .panel__cards--rating {
    grid-template-columns: minmax(12rem, 1fr) 3fr;
  }
}

@media (min-width: 60rem) {
  .panel__cards--triple {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* Header panels: brand and pages on the left, account and filters on the right. Phones put
   the filters on a row of their own. */
.site-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1.5rem;
  padding-top: 1rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--color-border);
  margin-bottom: 1.5rem;
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--color-text);
  font-size: 1.125rem;
  font-weight: 700;
}

.brand:hover {
  text-decoration: none;
}

.config {
  display: flex;
  flex-wrap: wrap;
  order: 1;
  width: 100%;
  gap: 0.5rem;
}

.config__select {
  padding: 0.3rem 0.5rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-control);
  background: var(--color-surface);
  color: var(--color-text);
  font: inherit;
  font-size: 0.875rem;
}

@media (min-width: 48rem) {
  .config {
    order: 0;
    width: auto;
    margin-left: auto;
  }
}

.page-message {
  font-size: 1.125rem;
}

/* ---------------------------------------------------------------- cards */

.card {
  display: grid;
  align-content: start;
  gap: 0.75rem;
  min-width: 0;
  padding: var(--space-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  background: var(--color-surface);
}

.card--highlight {
  border-color: var(--color-accent);
}

.card__title {
  font-size: 1rem;
}

.card__note {
  color: var(--color-muted);
  font-size: 0.875rem;
}

/* ---------------------------------------------------------------- rating card */

.rating__value {
  font-size: 3.5rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.02em;
}

/* Change over the range, led by the logo: upright and green when rising,
   flipped and red when falling. */
.rating__trend {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.rating__mood {
  width: 2rem;
  height: 2rem;
  flex: none;
}

.rating__mood--up { color: var(--color-up); }
.rating__mood--down { color: var(--color-down); transform: scaleY(-1); }
.rating__mood--flat { color: var(--color-neutral); }

.rating__change {
  font-size: 1.5rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.rating__change--up { color: var(--color-up); }
.rating__change--down { color: var(--color-down); }

.rating__period {
  color: var(--color-muted);
}

/* Games and win share, overall and by colour: count, result bar, win %. */
.rating__stats {
  display: grid;
  gap: 0.625rem;
  padding-top: 0.875rem;
  border-top: 1px solid var(--color-border);
  font-variant-numeric: tabular-nums;
}

.rating__stats-head,
.rating__stat {
  display: grid;
  grid-template-columns: 1.5rem 2rem 1fr 2.75rem;
  align-items: center;
  gap: 0.625rem;
}

.rating__stats-head {
  color: var(--color-muted);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.rating__stats-head :first-child {
  grid-column: 1 / 4;
}

.rating__stats-head :last-child,
.rating__stat-share {
  text-align: right;
}

.rating__stat-label {
  color: var(--color-muted);
  font-size: 0.75rem;
}

.rating__stat-games {
  font-weight: 600;
}

.rating__stat-share {
  font-weight: 600;
}

.result-bar {
  display: flex;
  gap: 2px;
  height: 0.375rem;
  overflow: hidden;
  border-radius: 999px;
}

.result-bar > * { min-width: 0; }
.result-bar__wins { background: var(--color-up); }
.result-bar__draws { background: var(--color-neutral); }
.result-bar__losses { background: var(--color-down); }

.piece {
  width: 1.25rem;
  height: 1.25rem;
  flex: none;
  stroke-width: 1.2;
}

.piece--white { fill: #f4f3ee; stroke: #6b6a65; }
.piece--black { fill: #1b1b1a; stroke: #a3a29b; }

/* ---------------------------------------------------------------- chart card */

.rating-chart {
  position: relative;
}

.rating-chart__svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
  font-family: var(--font-body);
}

.rating-chart__grid { stroke: var(--color-border); stroke-width: 1; }
.rating-chart__tick { fill: var(--color-muted); font-size: 11px; }
.rating-chart__area { fill: url(#rating-chart-fill); }
.rating-chart__fill-top { stop-color: var(--color-accent); stop-opacity: 0.45; }
.rating-chart__fill-bottom { stop-color: var(--color-accent); stop-opacity: 0.02; }
.rating-chart__line { fill: none; stroke: var(--color-accent); stroke-width: 2.5; stroke-linejoin: round; }
.rating-chart__point { fill: var(--color-accent); stroke: var(--color-surface); stroke-width: 2; }
.rating-chart__cursor { stroke: var(--color-muted); stroke-width: 1; }

.rating-chart__tooltip {
  position: absolute;
  top: 0;
  padding: 0.25rem 0.5rem;
  border: 1px solid var(--color-border);
  border-radius: 6px;
  background: var(--color-surface);
  font-size: 0.8125rem;
  white-space: nowrap;
  pointer-events: none;
}

/* ---------------------------------------------------------------- gains and losses */

.points--gain { color: var(--color-up); font-weight: 600; }
.points--loss { color: var(--color-down); font-weight: 600; }

/* ---------------------------------------------------------------- repertoire cards */

.repertoire__summary {
  color: var(--color-muted);
  font-size: 0.875rem;
}

.repertoire-table {
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
  font-size: 0.875rem;
}

.repertoire-table__against { width: 28%; }
.repertoire-table__choices { width: 47%; }
.repertoire-table__strength { width: 25%; }

.repertoire-table th {
  padding: 0 0.5rem 0.375rem 0;
  color: var(--color-muted);
  font-weight: 500;
  font-size: 0.75rem;
  text-align: left;
}

.repertoire-table td {
  padding: 0.5rem 0.5rem 0.5rem 0;
  border-top: 1px solid var(--color-border);
  vertical-align: top;
}

.repertoire-table__move {
  display: block;
  font-family: var(--font-mono);
}

.repertoire-table__details {
  display: block;
  color: var(--color-muted);
  font-size: 0.75rem;
}

.choice {
  display: block;
}

.choice__move {
  font-family: var(--font-mono);
}

.choice__share {
  color: var(--color-muted);
}

/* Score against expectation: blue to the right is better, red to the left worse. */
.strength {
  display: grid;
  grid-template-columns: minmax(2rem, 4rem) auto;
  align-items: center;
  gap: 0.5rem;
  white-space: nowrap;
}

.strength__bar {
  position: relative;
  height: 0.5rem;
  background: linear-gradient(var(--color-neutral), var(--color-neutral)) center / 1px 100% no-repeat;
}

.strength__fill {
  position: absolute;
  top: 0;
  bottom: 0;
}

.strength__fill--better {
  left: 50%;
  background: var(--color-better);
  border-radius: 0 4px 4px 0;
}

.strength__fill--worse {
  right: 50%;
  background: var(--color-worse);
  border-radius: 4px 0 0 4px;
}

.status {
  display: block;
  margin-top: 0.125rem;
  color: var(--color-muted);
}

.status--good { color: var(--color-up); }
.status--act { color: var(--color-down); font-weight: 600; }

/* ---------------------------------------------------------------- footer */

.site-footer {
  padding-bottom: 2rem;
  color: var(--color-muted);
  font-size: 0.8125rem;
}

.site-footer__warning {
  color: var(--color-down);
}

/* ---------------------------------------------------------------- onboarding and refresh */

.onboarding__fields {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.onboarding__input {
  flex: 1 1 12rem;
  padding: 0.3rem 0.625rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-control);
  background: var(--color-surface);
  color: var(--color-text);
  font: inherit;
}

.onboarding__button,
.site-footer__refresh {
  padding: 0.3rem 0.875rem;
  border: 1px solid var(--color-accent);
  border-radius: var(--radius-control);
  background: var(--color-accent);
  color: #fff;
  font: inherit;
  cursor: pointer;
}

.site-footer__refresh {
  margin-left: 0.75rem;
  padding: 0.125rem 0.625rem;
  background: none;
  color: var(--color-accent);
  font-size: 0.8125rem;
}

/* ---------------------------------------------------------------- page navigation */

/* The dashboard, Openings and Log tabs share index.html; main's data-view picks the panels. */
.site-main[data-view="dashboard"] > [data-view]:not([data-view="dashboard"]),
.site-main[data-view="openings"] > [data-view]:not([data-view="openings"]),
.site-main[data-view="log"] > [data-view]:not([data-view="log"]) {
  display: none;
}

.site-nav {
  display: flex;
  gap: 1rem;
}

.site-nav__link {
  color: var(--color-muted);
  font-weight: 600;
}

.site-nav__link[aria-current="page"] {
  color: var(--color-text);
}

/* ---------------------------------------------------------------- training */

.train {
  display: grid;
  gap: 1rem;
  align-items: start;
}

@media (min-width: 60rem) {
  .train {
    grid-template-columns: minmax(20rem, 34rem) 1fr;
  }
}

/* The position's chess mistake and its game, above the board. */
.train__context {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.875rem;
}

.tag {
  display: inline-block;
  padding: 0.0625rem 0.5rem;
  border-radius: 999px;
  background: var(--color-accent-soft);
  color: var(--color-accent);
  font-size: 0.75rem;
  font-weight: 600;
  white-space: nowrap;
}

.train__steps {
  display: grid;
  gap: 0.375rem;
  padding-left: 1.25rem;
  list-style: decimal;
  font-size: 0.875rem;
}

.train__board {
  width: 100%;
  aspect-ratio: 1;
}

.train__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}

.train__button {
  padding: 0.3rem 0.75rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-control);
  background: var(--color-surface);
  color: var(--color-text);
  font: inherit;
  font-size: 0.875rem;
  cursor: pointer;
}

.train__button--primary {
  border-color: var(--color-accent);
  background: var(--color-accent);
  color: #fff;
}

.train__list {
  display: grid;
  gap: 0.375rem;
  max-height: 44rem;
  overflow-y: auto;
}

.exercise {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.125rem 0.75rem;
  width: 100%;
  padding: 0.625rem 0.875rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-control);
  background: var(--color-surface);
  color: var(--color-text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.exercise[aria-current="true"] {
  border-color: var(--color-accent);
}

.exercise__move {
  font-family: var(--font-mono);
  font-weight: 600;
}

.exercise__badge {
  margin-left: 0.5rem;
  font-family: var(--font-body);
  font-size: 0.75rem;
  font-weight: 600;
}

.exercise__badge--blunder { color: var(--color-down); }
.exercise__badge--mistake { color: #d9822b; }
.exercise__badge--inaccuracy { color: var(--color-muted); }

.exercise__status {
  color: var(--color-muted);
  font-size: 0.8125rem;
  text-align: right;
}

.exercise__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.375rem;
  grid-column: 1 / -1;
  color: var(--color-muted);
  font-size: 0.8125rem;
}

.exercise__status {
  color: var(--color-muted);
  font-size: 0.8125rem;
  text-align: right;
}

.exercise__status--learned { color: var(--color-up); }
.exercise__status--failed { color: var(--color-down); }

/* ---------------------------------------------------------------- where your points went */

.causes__summary {
  font-size: 1.125rem;
  font-weight: 600;
}

.causes__rows {
  display: grid;
  gap: 0.5rem;
}

.causes__row {
  display: grid;
  grid-template-columns: minmax(9rem, 12rem) 1fr 3.5rem;
  grid-template-areas: "name bar value";
  align-items: center;
  column-gap: 0.75rem;
}

.causes__name { grid-area: name; font-weight: 600; }
.causes__detail { display: block; color: var(--color-muted); font-size: 0.75rem; font-weight: 400; }
.causes__track { grid-area: bar; height: 0.75rem; }
.causes__bar { display: block; height: 100%; border-radius: 4px; }
.causes__bar--gain { background: var(--color-up); }
.causes__bar--loss { background: var(--color-down); }
.causes__value { grid-area: value; text-align: right; font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------- today and streak */

@media (min-width: 48rem) {
  .panel__cards--today {
    grid-template-columns: 2fr 1fr;
  }
}

.today {
  gap: 0.625rem;
}

.today__pending {
  padding-top: 0.625rem;
  border-top: 1px solid var(--color-border);
}

.losses,
.pending {
  display: grid;
  gap: 0.375rem;
}

.loss {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.375rem;
  font-size: 0.9375rem;
}

.pending__train {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}

.streak__count {
  font-size: 1rem;
}

.streak__count strong {
  font-size: 2rem;
}

/* The last 30 days, one square each, darker for more positions trained. */
.calendar {
  display: grid;
  grid-template-columns: repeat(10, 1fr);
  gap: 3px;
}

.calendar__day {
  aspect-ratio: 1;
  border-radius: 3px;
  background: var(--color-border);
}

.calendar__day--1 { background: color-mix(in srgb, var(--color-up) 35%, var(--color-surface)); }
.calendar__day--2 { background: color-mix(in srgb, var(--color-up) 65%, var(--color-surface)); }
.calendar__day--3 { background: var(--color-up); }

/* ---------------------------------------------------------------- log */

.tracking {
  display: grid;
  gap: 0.375rem;
}

.log__table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
  font-variant-numeric: tabular-nums;
}

.log__table th,
.log__table td {
  padding: 0.5rem 0.75rem 0.5rem 0;
  border-top: 1px solid var(--color-border);
  text-align: left;
  vertical-align: top;
}

.log__table thead th {
  border-top: 0;
  color: var(--color-muted);
  font-size: 0.75rem;
  font-weight: 500;
}

.log__table tbody th,
.log__table td:nth-child(2),
.log__table td:nth-child(3) {
  white-space: nowrap;
}

.log__table tbody th {
  font-weight: 600;
}

.log__flags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
}

.log__loss {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
}

a.train__button {
  display: inline-block;
  text-decoration: none;
}

.exercise__badge--play-it-out { color: var(--color-accent); }

.train__queue {
  display: grid;
  gap: 0.75rem;
  align-content: start;
}

/* ---------------------------------------------------------------- verdict (as lichess's puzzle feedback) */

.verdict {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-height: 3.5rem;
  padding: 0.625rem 0.875rem;
  border-radius: var(--radius-control);
  background: var(--color-page);
}

.verdict__icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 50%;
  background: var(--color-surface);
  font-size: 1.25rem;
  line-height: 1;
}

.verdict__title {
  font-size: 1.0625rem;
}

.verdict__detail {
  color: var(--color-muted);
  font-size: 0.875rem;
}

.verdict--good { background: color-mix(in srgb, var(--color-up) 12%, var(--color-surface)); }
.verdict--good .verdict__icon { background: var(--color-up); color: #fff; }
.verdict--good .verdict__title { color: var(--color-up); }
.verdict--bad { background: color-mix(in srgb, var(--color-down) 12%, var(--color-surface)); }
.verdict--bad .verdict__icon { background: var(--color-down); color: #fff; }
.verdict--bad .verdict__title { color: var(--color-down); }

.flag {
  display: inline-block;
  padding: 0.0625rem 0.5rem;
  border-radius: 999px;
  background: var(--color-down);
  color: #fff;
  font-size: 0.75rem;
  font-weight: 700;
  white-space: nowrap;
}

/* ---------------------------------------------------------------- woodpecker cycle */

.cycle {
  gap: 0.625rem;
}

.cycle__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
}

.cycle__title {
  font-size: 1.375rem;
}

.cycle__count {
  font-size: 1.125rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* One cell per position, like lichess's puzzle session: green solved, red missed, grey to do. */
.strip {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.strip__cell {
  display: block;
  width: 1.375rem;
  height: 1.375rem;
  padding: 0;
  border: 0;
  border-radius: 4px;
  background: var(--color-border);
  cursor: pointer;
}

.strip__cell--good { background: var(--color-up); }
.strip__cell--bad { background: var(--color-down); }
.strip__cell--repeat { box-shadow: inset 0 0 0 2px var(--color-down); }
.strip__cell--bad.strip__cell--repeat { box-shadow: inset 0 0 0 2px var(--color-surface); }
.strip__cell[aria-current="true"] { outline: 2px solid var(--color-accent); outline-offset: 1px; }

.cycle__stats {
  font-variant-numeric: tabular-nums;
}

.cycle__next {
  padding: 0.5rem 0.75rem;
  border-left: 3px solid var(--color-accent);
  background: var(--color-accent-soft);
  font-size: 0.875rem;
  font-weight: 600;
}

.cycles {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.8125rem;
  font-variant-numeric: tabular-nums;
}

.cycles th {
  color: var(--color-muted);
  font-weight: 500;
  text-align: left;
}

.cycles td {
  padding: 0.25rem 0;
  border-top: 1px solid var(--color-border);
}

.train__help-title {
  cursor: pointer;
  font-weight: 700;
}

.train__help[open] .train__help-title {
  margin-bottom: 0.5rem;
}

/* A position's results, oldest first. */
.reps {
  display: flex;
  justify-content: flex-end;
  gap: 3px;
}

.reps__dot {
  width: 0.625rem;
  height: 0.625rem;
  border-radius: 50%;
}

.reps__dot--true { background: var(--color-up); }
.reps__dot--false { background: var(--color-down); }

/* ---------------------------------------------------------------- sign in */

.login {
  display: grid;
  min-height: 100vh;
  place-items: center;
  padding: 1rem;
}

.login__form {
  width: min(100%, 22rem);
  gap: 0.875rem;
}

.login__brand {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 1.375rem;
}

.login__error {
  color: var(--color-down);
  font-size: 0.875rem;
}

