/* The signed-in homepage (index.html, the only page that loads this file):
   the bar, the menu, the lesson player's columns and the cards beside it.
   The chessboard stays in the lesson player; this file only places it. */

/* ===== TOKENS =====
   A light page: white surfaces on a cool grey, hairline borders rather than
   shadows, blue for what the player acts on, amber only for what is earned
   or aimed at, green for success. */
body:has(#main-content:not(.hidden)) {
  --hp-bg: #f5f7fa;
  --hp-surface: #ffffff;
  --hp-subtle: #f8fafc;
  --hp-blue: #2563eb;
  --hp-blue-hover: #1d4ed8;
  --hp-blue-line: #bfdbfe;
  --hp-selected: #eff6ff;
  --hp-amber: #f59e0b;
  --hp-amber-ink: #b45309;
  /* The rating beside the board, a shade deeper than the accent so it holds
     its contrast as text; a training session's Terminare wears it too. */
  --hp-rating: #d97706;
  --hp-green: #16a34a;
  --hp-text: #1e293b;
  --hp-muted: #64748b;
  --hp-border: #e2e8f0;
  --hp-divider: #f1f5f9;
  --hp-radius-card: 16px;
  --hp-radius-item: 12px;
  --hp-radius-btn: 10px;
  --hp-ease: 160ms ease;
  --hp-font: "Nunito Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --hp-font-play: "Fredoka", var(--hp-font);
  /* The bar, and over it the admins' message when there is one (below). */
  --navbar-block-size: 62px;
  --header-block-size: calc(var(--navbar-block-size) + var(--announcement-block-size, 0px));

  background: var(--hp-bg);
  color: var(--hp-text);
  font-family: var(--hp-font);
}

body:has(#main-content:not(.hidden)) :is(button, input, select, textarea) {
  font-family: inherit;
}

/* ===== THE BAR =====
   White, over a hairline: the ratings, the bug report, the trophies and the
   account menu with the player's first name. */
/* Above the menu when the page scrolls under it (both were z-index 100). */
body:has(#main-content:not(.hidden)) .header-bar {
  z-index: 101;
  background: var(--hp-surface);
  box-shadow: 0 1px 0 var(--hp-border);
}

body:has(#main-content:not(.hidden)) .header-bar .section-inner {
  max-inline-size: none;
  padding-inline: 8px 18px;
}

/* ===== THE ADMINS' MESSAGE =====
   A slim strip over the bar, the page's width, while the admins have
   something to say (#announcement-bar, filled by whichever stream the page
   has open) and the viewer has not hidden it with its × (`is-hidden`,
   js/announcement-bar.js); otherwise no strip. One line, the whole text in
   its title, swiped along on a touch screen. Its height is the header's
   too: every height rule that leaves room for the header
   (--header-block-size) leaves room for it, and the toasts move down by
   it. */
.announcement-bar {
  display: none;
}

body:has(#main-content:not(.hidden)):has(#announcement-bar:not(.is-hidden) > *) {
  --announcement-block-size: 26px;

  .announcement-bar {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    block-size: var(--announcement-block-size);
    padding-inline: 32px;
    background: var(--color-warning-bg);
    box-shadow: inset 0 -1px 0 rgb(133 100 4 / 15%);
    color: var(--color-warning-text);
    font-size: 13px;
    font-weight: 600;
    line-height: 1.2;
  }

  .header-bar .section-inner {
    block-size: var(--navbar-block-size);
  }

  toast-notification {
    translate: 0 var(--announcement-block-size);
  }
}

.announcement-text {
  min-inline-size: 0;
  max-inline-size: 1200px;
  margin: 0;
  overflow: hidden;
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.announcement-hide {
  position: absolute;
  inset-block: 0;
  inset-inline-end: 0;
  inline-size: 32px;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
}

/* No title to hover on a touch screen: a long message is swiped along. */
@media (pointer: coarse) {
  .announcement-text {
    overflow-x: auto;
    text-overflow: clip;
    scrollbar-width: none;
  }
}

@media (max-width: 575.98px) {
  body:has(#main-content:not(.hidden)):has(#announcement-bar:not(.is-hidden) > *) {
    --announcement-block-size: 22px;

    .announcement-bar {
      font-size: 12px;
    }
  }
}

body:has(#main-content:not(.hidden)) .score-container {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  margin-right: 0;
  padding: 0.15rem 0.35rem;
  border-radius: 8px;
  color: var(--hp-text);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transition: background-color var(--hp-ease);
}

body:has(#main-content:not(.hidden)) .score-container:hover {
  background: var(--hp-subtle);
}

/* The best Quick Game rating: a link to its leaderboard. */
a.score-container {
  text-decoration: none;
}

.score-icon {
  display: inline-flex;
  color: var(--hp-muted);
}

.score-icon svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.score-icon-dice svg circle {
  fill: currentColor;
  stroke: none;
}

/* A narrow bar drops what it has no room for: the training ranking's link
   under 700px, the puzzles' rating under 640px (with it the bar needs 616px:
   four-digit ratings, six-digit points and a name of twelve letters). The
   Quick Game's rating and the points stay. */
@media (max-width: 699px) {
  #training-elo-container {
    display: none !important;
  }
}

@media (max-width: 639.98px) {
  #score-container {
    display: none !important;
  }
}

/* Whatever room is still missing, the account's name gives: it is cut short
   (…), and nothing is pushed off the screen. */
body:has(#main-content:not(.hidden)) .header-bar .logo {
  flex-shrink: 0;
}

body:has(#main-content:not(.hidden)) .header-bar .actions {
  min-width: 0;
}

body:has(#main-content:not(.hidden)) .header-bar .actions > * {
  flex-shrink: 0;
}

body:has(#main-content:not(.hidden)) .header-bar .actions > #account-dropdown {
  flex-shrink: 1;
  min-width: 0;
}

body:has(#main-content:not(.hidden)) #account-dropdown .dropdown-toggle {
  max-width: 100%;
}

body:has(#main-content:not(.hidden)) #bug-report-btn {
  border: none;
  padding-inline: 0.2rem;
}

/* The player's trophies, beside their name: the gold cup (img/trophies). */
.nav-trophies-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.2rem 0.3rem;
  border: none;
  border-radius: 8px;
  background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.nav-trophies-btn img {
  width: 24px;
  height: 26px;
  object-fit: contain;
}

.nav-trophies-btn:hover {
  background: var(--hp-divider);
}

.nav-trophies-btn:focus-visible {
  outline: 2px solid var(--hp-blue);
  outline-offset: 2px;
}

body:has(#main-content:not(.hidden)) #account-dropdown .dropdown-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.3rem 0.65rem;
  border: none;
  border-radius: var(--hp-radius-btn);
  color: var(--hp-text);
  font-weight: 600;
}

body:has(#main-content:not(.hidden)) #account-dropdown .dropdown-toggle:hover,
body:has(#main-content:not(.hidden)) #account-dropdown.open .dropdown-toggle {
  background: var(--hp-divider);
}

.nav-account-name {
  max-width: 12ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* A chevron in place of the ▾ glyph; it turns over while the menu is open. */
body:has(#main-content:not(.hidden)) #account-dropdown .dropdown-toggle::after {
  content: "";
  width: 8px;
  height: 8px;
  border-right: 2.2px solid #94a3b8;
  border-bottom: 2.2px solid #94a3b8;
  border-radius: 1px;
  transform: translateY(-2px) rotate(45deg);
  transition: transform 0.15s ease;
}

body:has(#main-content:not(.hidden)) #account-dropdown.open .dropdown-toggle::after {
  transform: translateY(2px) rotate(-135deg);
}

body:has(#main-content:not(.hidden)) .dropdown-menu {
  border-color: var(--hp-border);
  border-radius: var(--hp-radius-item);
  box-shadow: 0 10px 30px rgba(15, 23, 42, 0.1);
}

body:has(#main-content:not(.hidden)) .dropdown-item {
  color: var(--hp-text);
  font-size: 0.92rem;
}

body:has(#main-content:not(.hidden)) .dropdown-item:hover {
  background: var(--hp-selected);
}

/* A phone (under 480px, where the bar without the puzzles' rating no longer
   fits a long name): its items closer together, so that the account's name
   is shown whole on most; under 300px the name gives way first. */
@media (max-width: 479.98px) {
  body:has(#main-content:not(.hidden)) .header-bar .section-inner {
    padding-inline: 4px 6px;
  }

  body:has(#main-content:not(.hidden)) .header-bar .actions {
    gap: 2px;
  }

  body:has(#main-content:not(.hidden)) .score-container {
    padding: 0.1rem 0.2rem;
  }

  body:has(#main-content:not(.hidden)) #bug-report-btn,
  .nav-trophies-btn {
    padding-inline: 0.1rem;
  }

  body:has(#main-content:not(.hidden)) #account-dropdown .dropdown-toggle {
    gap: 0.3rem;
    padding-inline: 0.3rem;
  }
}

@media (max-width: 299.98px) {
  .nav-account-name {
    max-width: 4ch;
  }

  body:has(#main-content:not(.hidden)) #account-dropdown .dropdown-toggle::after {
    content: none;
  }

  body:has(#main-content:not(.hidden)) .header-bar .logo {
    block-size: 68%;
  }
}

/* ===== THREE COLUMNS ===== */
/* The menu widens into the room the board does not use. The board is the
   smaller of its height (100vh - 118px) and the width beside it
   (100vw - menu - 614px); the two are equal at a menu of 100vw - 100vh -
   496px, and 16px more is kept in hand, so the menu never takes from the
   board. Only from 1280px, where the cards are beside the board; below it,
   app.css's 228px. */
@media (min-width: 1280px) {
  .app-layout {
    --nav-w: clamp(228px, 100vw - 100vh - 512px, 272px);
  }
}


.lessons-sidebar.collapsed {
  margin-left: calc(-1 * var(--nav-w));
}




.sidebar-controls .btn {
  width: 30px;
  height: 30px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--hp-border);
  border-radius: 8px;
  background: var(--hp-surface);
  color: var(--hp-muted);
  font-size: 0.78rem;
  line-height: 1;
  transition: background-color var(--hp-ease), border-color var(--hp-ease), color var(--hp-ease);
}

.sidebar-controls .btn:hover,
.lessons-sidebar.pinned #pin-sidebar-btn {
  background: var(--hp-selected);
  border-color: var(--hp-blue-line);
  color: var(--hp-blue);
}

.sidebar-toggle-tab {
  background: var(--hp-surface);
  color: var(--hp-text);
  border: 1px solid var(--hp-border);
  border-left: none;
  box-shadow: 0 2px 8px rgba(15, 23, 42, 0.08);
}



button.lesson-item {
  display: block;
  width: 100%;
  margin: 0 0 2px;
  padding: 0;
  border: none;
  background: transparent;
  color: var(--hp-text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.sidebar-content a.lesson-item {
  display: block;
  text-decoration: none;
  color: inherit;
}

.sidebar-content > .lesson-item,
.sidebar-content > .lesson-item:hover {
  background: transparent;
  border-color: transparent;
  box-shadow: none;
  transform: none;
  padding: 0;
}

.lesson-item .lesson-content {
  color: var(--hp-text);
}

/* Rows at every width: common.css stacks .lesson-content on phones, which
   suits its lesson lists, not this menu. */
.lessons-sidebar .lesson-content {
  flex-direction: row;
  align-items: center;
}

.lessons-sidebar .category-header {
  flex-wrap: nowrap;
}

.lessons-sidebar .lesson-count {
  margin: 0 0 0 auto;
}

.sidebar-content > .lesson-item .lesson-content {
  border-radius: var(--hp-radius-btn);
  padding: 0.42rem 0.6rem;
  transition: background-color var(--hp-ease), border-color var(--hp-ease), color var(--hp-ease);
}

.sidebar-content > .lesson-item:hover .lesson-content {
  background: var(--hp-subtle);
}

.lesson-icon {
  width: 22px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
}

.lesson-icon svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.lesson-icon svg circle {
  fill: currentColor;
  stroke: none;
}

/* ===== NAVIGATION ===== */
/* Combinații tactice and Sesiune de antrenament: neutral cards, each
   with its icon on a tinted tile. */
.sidebar-content .nav-wide {
  margin: 0 0 6px;
  cursor: pointer;
}

.sidebar-content .nav-wide .lesson-content {
  justify-content: flex-start;
  gap: 0.55rem;
  padding: 0.5rem 0.6rem;
  border: 1px solid var(--hp-border);
  border-radius: var(--hp-radius-item);
  background: var(--hp-surface);
  transition: background-color var(--hp-ease), border-color var(--hp-ease), color var(--hp-ease);
}

.sidebar-content .nav-wide:hover .lesson-content {
  background: var(--hp-selected);
  border-color: var(--hp-blue-line);
}

.sidebar-content .nav-wide.is-active .lesson-content {
  background: var(--hp-selected);
  border-color: var(--hp-blue);
}

/* A session's state shows while the card is not hovered; hovered, it is
   like every other card. */
.sidebar-content .training-session-btn.training-session-active:not(:hover) .lesson-content {
  background: #f0fdf4;
  border-color: #86efac;
  box-shadow: none;
}

.sidebar-content
  .training-session-btn:not(.training-session-active):has(.ts-resume):not(:hover)
  .lesson-content {
  background: #fffbeb;
  border-color: #fcd34d;
  box-shadow: none;
}

.sidebar-content .training-session-btn:hover .lesson-content {
  box-shadow: none;
}

.nav-wide .lesson-icon {
  width: 32px;
  height: 32px;
  border-radius: var(--hp-radius-btn);
  background: var(--hp-selected);
  color: var(--hp-blue);
}

.training-session-btn .lesson-icon {
  background: #fef3c7;
  color: var(--hp-amber-ink);
}

/* Joacă: the Quick Game's lobby, and a public challenge at each clock, in a
   card of their own. */
.nav-play-group {
  margin: 0.6rem 0 0.75rem;
  padding: 6px;
  border: 1px solid var(--hp-border);
  border-radius: 14px;
  background: var(--hp-surface);
}

.sidebar-content .nav-play-group a.nav-play-link,
.sidebar-content .nav-play-group a.nav-play-link:hover {
  display: block;
  padding: 0;
  border: none;
  background: transparent;
  box-shadow: none;
  transform: none;
  color: var(--hp-text);
  text-decoration: none;
}

.sidebar-content .nav-play-group .nav-play-link .lesson-content,
.sidebar-content .nav-play-group .nav-play-link:hover .lesson-content {
  border-color: transparent;
}

.nav-play-group .lesson-icon {
  background: #dcfce7;
  color: #15803d;
}

.nav-play-menu {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
}

.nav-play-option {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 0.45rem 0.3rem 0.5rem;
  border: 1px solid var(--hp-border);
  border-radius: var(--hp-radius-btn);
  background: var(--hp-subtle);
  color: var(--hp-text);
  text-decoration: none;
  line-height: 1.1;
  transition: background-color var(--hp-ease), border-color var(--hp-ease), color var(--hp-ease);
}

.nav-play-option strong {
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--hp-muted);
}

.nav-play-option span {
  font-size: 1.4rem;
  font-weight: 800;
  color: var(--hp-text);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

.nav-play-option:hover,
.nav-play-option:focus-visible {
  background: var(--hp-selected);
  border-color: var(--hp-blue-line);
}

.nav-play-option:hover strong,
.nav-play-option:hover span {
  color: var(--hp-blue-hover);
}

.nav-play-option:focus-visible {
  outline: 2px solid var(--hp-blue);
  outline-offset: 2px;
}

/* Under the clocks: the player's games in play and open challenges
   (quick_home.html), each a row; empty, nothing. */
.quick-home-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin: 6px 0 0;
  padding: 6px 0 0;
  border-top: 1px solid var(--hp-divider);
  list-style: none;
}

.quick-home-item {
  display: flex;
  align-items: center;
  gap: 4px;
  border-radius: var(--hp-radius-btn);
  background: var(--hp-subtle);
}

/* A game in play: the card's one call to be pressed, a green button sending
   out the lobby's ring for something live (quick-game.css's qg-seeking), in
   green, at the searching dot's pace. Its ▶ is the sidebar's mark for going
   back to what runs (the training button's). The "Joacă" icon's deep green,
   not --hp-green: white text on it reads (5:1). */
.quick-home-item.is-live {
  position: relative;
  background: #15803d;
  animation: quick-home-live 1.6s ease-out infinite;
  transition: background-color var(--hp-ease);
}

.quick-home-item.is-live:hover,
.quick-home-item.is-live:focus-within {
  background: #166534;
}

.quick-home-item.is-live .quick-home-link {
  padding-right: 2.6rem;
  color: #fff;
}

.quick-home-item.is-live .quick-home-link:focus-visible {
  outline: 2px solid var(--hp-text);
  outline-offset: 2px;
  border-radius: var(--hp-radius-btn);
}

.quick-home-item.is-live .quick-home-what,
.quick-home-item.is-live .quick-home-link:hover .quick-home-what,
.quick-home-item.is-live .quick-home-link:focus-visible .quick-home-what {
  color: #fff;
  font-weight: 700;
}

/* Its words whole: a long name goes to the next line, never cut. */
.quick-home-item.is-live .quick-home-what {
  display: block;
  white-space: normal;
}

.quick-home-item.is-live .quick-home-clock {
  color: #dcfce7;
}

/* Over the link's right end, which takes its click. */
.quick-home-go {
  position: absolute;
  top: 50%;
  right: 0.55rem;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: #fff;
  color: #15803d;
  transform: translateY(-50%);
  pointer-events: none;
}

.quick-home-go svg {
  width: 14px;
  height: 14px;
  fill: currentColor;
}

.quick-home-item.is-live:hover .quick-home-go {
  color: #166534;
}

@keyframes quick-home-live {
  0% {
    box-shadow: 0 0 0 0 rgba(22, 163, 74, 0.5);
  }
  70%,
  100% {
    box-shadow: 0 0 0 8px rgba(22, 163, 74, 0);
  }
}

.quick-home-link {
  display: flex;
  flex: 1;
  min-width: 0;
  flex-direction: column;
  gap: 1px;
  padding: 0.4rem 0.55rem;
  color: var(--hp-text);
  text-decoration: none;
  line-height: 1.2;
}

.quick-home-link:hover .quick-home-what,
.quick-home-link:focus-visible .quick-home-what {
  color: var(--hp-blue-hover);
}

.quick-home-what {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.82rem;
  font-weight: 600;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.quick-home-what strong {
  overflow: hidden;
  text-overflow: ellipsis;
}

.quick-home-clock {
  font-size: 0.74rem;
  color: var(--hp-muted);
  font-variant-numeric: tabular-nums;
}

/* Searching: its line blinks, the dot and the words together. */
.quick-home-pulse {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--hp-green);
}

.quick-home-searching {
  animation: quick-home-pulse 1.6s ease-in-out infinite;
}

@keyframes quick-home-pulse {
  50% {
    opacity: 0.3;
  }
}

@media (prefers-reduced-motion: reduce) {
  .quick-home-item.is-live,
  .quick-home-searching {
    animation: none;
  }
}

.quick-home-cancel {
  flex: none;
  width: 28px;
  height: 28px;
  margin-right: 4px;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--hp-muted);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.quick-home-cancel:hover,
.quick-home-cancel:focus-visible {
  background: #fee2e2;
  color: #b91c1c;
}

/* A game that has just started and waits for the player (quick_alert.html):
   a banner over the page, at the top, whatever is open under it: over the
   phone's menu button too (app.css, 10000). */
.quick-alert-host {
  position: fixed;
  top: 12px;
  left: 50%;
  z-index: 10001;
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: min(560px, calc(100vw - 24px));
  transform: translateX(-50%);
  pointer-events: none;
}

.quick-alert {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 12px 12px 16px;
  border: 1px solid #86efac;
  border-radius: var(--hp-radius-card);
  background: var(--hp-surface);
  box-shadow: 0 12px 32px rgba(15, 23, 42, 0.18);
  color: var(--hp-text);
  font-family: var(--hp-font);
  pointer-events: auto;
  animation: quick-alert-in 260ms ease-out;
}

.quick-alert[hidden] {
  display: none;
}

@keyframes quick-alert-in {
  from {
    opacity: 0;
    transform: translateY(-12px);
  }
}

.quick-alert-text {
  display: flex;
  flex: 1;
  min-width: 0;
  flex-direction: column;
  gap: 2px;
  font-size: 0.88rem;
  line-height: 1.3;
}

.quick-alert-title {
  font-family: var(--hp-font-play);
  font-size: 1.05rem;
  color: #15803d;
}

.quick-alert-due {
  color: var(--hp-amber-ink);
  font-weight: 600;
}

.quick-alert-due[hidden] {
  display: none;
}

.quick-alert.is-urgent .quick-alert-due {
  color: #b91c1c;
}

.quick-alert-seconds {
  font-variant-numeric: tabular-nums;
}

.quick-alert-go {
  flex: none;
  padding: 0.55rem 0.95rem;
  border-radius: var(--hp-radius-btn);
  background: var(--hp-green);
  color: #fff;
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
}

.quick-alert-go:hover,
.quick-alert-go:focus-visible {
  background: #15803d;
  color: #fff;
}

.quick-alert-close {
  flex: none;
  width: 30px;
  height: 30px;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--hp-muted);
  font-size: 1.2rem;
  line-height: 1;
  cursor: pointer;
}

.quick-alert-close:hover,
.quick-alert-close:focus-visible {
  background: var(--hp-divider);
  color: var(--hp-text);
}

@media (max-width: 479.98px) {
  .quick-alert {
    flex-wrap: wrap;
  }

  .quick-alert-text {
    flex-basis: calc(100% - 42px);
  }

  .quick-alert-close {
    order: 1;
  }

  .quick-alert-go {
    order: 2;
    flex: 1;
    text-align: center;
  }
}

.nav-wide .lesson-icon svg {
  width: 20px;
  height: 20px;
}

.sidebar-content .nav-wide .lesson-title {
  font-size: 0.92rem;
  font-weight: 700;
  line-height: 1.2;
}

/* Lecții începători: the tree's heading, under a hairline. */
/* Hovered too: the menu items' hover reset (padding 0, no border) would
   otherwise lift the heading and take its hairline away. */
.sidebar-content > button.nav-lessons-toggle,
.sidebar-content > button.nav-lessons-toggle:hover {
  margin-top: 0.25rem;
  padding-top: 0.6rem;
  border-top: 1px solid var(--hp-border);
  border-radius: 0;
}

.sidebar-content .nav-lessons-toggle .lesson-title {
  font-size: 0.9rem;
  font-weight: 700;
}

.nav-lessons-toggle .lesson-icon {
  color: var(--hp-muted);
}

.nav-caret {
  width: 8px;
  height: 8px;
  margin-left: auto;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(-45deg);
  transition: transform 0.15s ease;
  color: #94a3b8;
}

.nav-lessons-toggle[aria-expanded="true"] .nav-caret {
  transform: rotate(45deg);
}

#lesson-container[hidden] {
  display: none;
}

.nav-wide:focus-visible,
.nav-lessons-toggle:focus-visible,
.sidebar-controls .btn:focus-visible,
.category-header:focus-visible {
  outline: 2px solid var(--hp-blue);
  outline-offset: 2px;
}

/* The lesson tree: quiet folders, an indent line per level. */
.category-header {
  background: transparent;
  border-left: none;
  border-radius: 8px;
  padding: 0.34rem 0.45rem;
  transition: background-color var(--hp-ease);
}

.category-header:hover {
  background: var(--hp-subtle);
  transform: none;
}

.category-icon {
  opacity: 0.8;
  filter: saturate(0.65);
}

.category-name,
.lesson-item .lesson-title {
  font-size: 0.86rem;
  line-height: 1.25;
  white-space: normal;
}

.category-name {
  color: var(--hp-text);
  font-weight: 600;
}

.lessons-sidebar .lesson-title {
  color: inherit;
}

.tree-view .lesson-item .lesson-title {
  font-weight: 500;
}

.lesson-count,
.lesson-count.bg-primary {
  background: var(--hp-divider);
  color: var(--hp-muted);
  border-radius: 999px;
  font-weight: 700;
}

.subcategories,
.lessons-list {
  margin-left: 0.85rem;
  padding-left: 0.35rem;
  border-left: 1px solid var(--hp-border);
}

.tree-view .lesson-item,
.tree-view .lesson-item:hover {
  background: transparent;
  border-color: transparent;
  box-shadow: none;
  transform: none;
}

.tree-view .lesson-item:hover {
  background: var(--hp-subtle);
}

/* A lesson is one row, opened by a click anywhere on it: the menu is too
   narrow for its title and a labelled button side by side. Its button
   (app.js's .play-lesson-btn) covers the row, its words left to screen
   readers; a lesson done says so with its ✅. */
.tree-view .lesson-item {
  position: relative;
}

.tree-view .lesson-item .lesson-actions {
  display: contents;
}

.tree-view .lesson-item .lesson-play-btn,
.tree-view .lesson-item.lesson-completed .lesson-play-btn {
  position: absolute;
  inset: 0;
  margin: 0;
  padding: 0;
  border: none !important;
  border-radius: inherit;
  background: transparent !important;
  color: transparent !important;
  font-size: 0;
  box-shadow: none;
  transform: none;
  cursor: pointer;
}

.tree-view .lesson-item .lesson-play-btn:focus-visible {
  outline: 2px solid var(--hp-blue);
  outline-offset: -2px;
}

.tree-view .lesson-item.lesson-completed .lesson-title {
  color: var(--hp-muted);
}

.dashboard-center {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr);
  column-gap: 8px;
  align-items: stretch;
  padding: 4px 8px 4px 8px;
  background: var(--hp-bg);
}

.dashboard-center > .chess-lesson-area {
  grid-column: 1;
  grid-row: 1;
  min-width: 0;
  min-height: 0;
}





.training-session-summary {
  background: var(--hp-surface);
  border: 1px solid var(--hp-border);
  border-radius: var(--hp-radius-card);
  padding: 1.1rem 1.25rem;
  box-shadow: none;
  max-width: 440px;
  width: 100%;
}

/* The trophy case (trophy_case.html) in its own window: as it was in the
   profile, its heading the window's. */
.trophies-window .trophy-case {
  margin-top: 0;
  padding-top: 0;
  border-top: none;
}

.trophies-window .trophy-case > h5 {
  display: none;
}

/* A game's PGN to replay (navbar-dialogs.js): what to do, the box (a file
   dragged over it outlined), why the PGN was refused, then the file's and
   the replay's buttons. */
.pgn-form-note {
  margin: 0 0 0.75rem;
  color: var(--hp-muted);
  font-size: 0.92rem;
}

.pgn-form .pgn-text {
  min-height: 11rem;
  resize: vertical;
  font-size: 1rem;
  line-height: 1.45;
}

.pgn-form .pgn-text.is-dropping {
  border-color: var(--hp-blue);
  background: var(--hp-selected);
}

.pgn-error {
  margin: 0.5rem 0 0;
  color: #b91c1c;
  font-size: 0.9rem;
  font-weight: 600;
}

.pgn-form-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
  margin-top: 0.9rem;
}


.session-summary-actions .btn {
  width: min(100%, 18rem);
  padding: 0.6rem 1rem;
  font-size: 1.05rem;
  font-weight: 700;
  line-height: 1.2;
  white-space: nowrap;
}

.session-summary-actions .session-ranking-btn {
  border: 1px solid var(--hp-blue);
  background: var(--hp-blue);
  color: white;
}

.session-summary-actions .session-ranking-btn:hover {
  border-color: var(--hp-blue-hover);
  background: var(--hp-blue-hover);
  color: white;
}

.session-summary-actions .session-ranking-btn:focus-visible {
  outline: 2px solid var(--hp-blue);
  outline-offset: 2px;
}



/* Under the board. */
.lichess-attribution {
  display: block;
  min-width: 0;
  color: var(--hp-muted);
  font-size: 0.68rem;
  line-height: 18px;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Beside the board: the player's puzzle rating, the number alone and as large
   as the column takes, and under it the puzzle's own, the one to beat. */
/* Puzzles only: a lesson has no rating to show, at any width. */
.lesson-player-root:not([data-lesson-id^="puzzle-"]) .board-side {
  display: none;
}

.board-side-stats {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.8rem;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* In a training session, the session's rating (dashboard.js). */
.board-player-elo {
  position: relative;
  color: var(--hp-rating);
  font-weight: 800;
  line-height: 0.9;
  letter-spacing: -0.04em;
  white-space: nowrap;
}

/* The rating's change (dashboard.js), above it for a moment, coloured as the
   navbar's points flash (app.css's fadeInOut). */
.board-elo-change {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  margin-bottom: 0.15em;
  color: var(--color-success);
  font-size: 0.4em;
  letter-spacing: 0;
  text-align: center;
  pointer-events: none;
  animation: fadeInOut 1.5s ease-in-out forwards;
}

.board-elo-change.rating-negative {
  color: var(--color-danger);
}

/* The puzzle's own rating, "Rating puzzle 1450" on one line: the number
   larger than its label, smaller than the player's rating over it. */
.board-puzzle-rating {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 0.35em;
  white-space: nowrap;
}

.board-puzzle-rating-label {
  color: var(--hp-muted);
  font-size: 0.82rem;
  font-weight: 600;
  white-space: nowrap;
}

/* Under the player's rating, what it is (dashboard.js puts it there): theirs
   at puzzles, or in a training session the session's. */
.board-elo-note {
  color: var(--hp-muted);
  font-size: 0.8rem;
  font-weight: 600;
  line-height: 1.25;
  text-align: center;
  max-width: 100%;
  text-wrap: balance;
}

.board-puzzle-rating-value {
  color: var(--hp-text);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.02em;
  white-space: nowrap;
}

/* "Revizuire" while an earlier position is shown: in the rating's column on
   a wide screen (below); on a phone the board's own label says it
   (chess-lesson-player.css's .board-locked). */
.board-review-badge {
  display: none;
  max-width: 100%;
  padding: 0.35rem 0.75rem;
  border-radius: var(--hp-radius-btn);
  background: rgba(15, 23, 42, 0.85);
  color: white;
  font-size: 0.9rem;
  font-weight: 700;
  white-space: nowrap;
}



.training-session-bar::before {
  content: "";
  flex: 1 1 0;
}

/* The puzzle's number in the session, then the session's name. */
.training-session-bar .ts-heading {
  flex: 0 1 auto;
  min-width: 0;
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 0.7rem;
}

.training-session-bar .ts-count {
  flex: none;
  color: var(--hp-muted);
  font-size: 1.75rem;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}

.training-session-bar .ts-title {
  min-width: 0;
  font-weight: 800;
  letter-spacing: -0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The name in full, but "Antrenament" alone on a phone. */
.training-session-bar .ts-title-short {
  display: none;
}


.training-session-bar .ts-actions {
  flex: 1 1 0;
  display: flex;
  justify-content: flex-end;
}



.training-session-bar .ts-end-btn:focus-visible {
  outline: 2px solid var(--hp-amber-ink);
  outline-offset: 2px;
}

/* Over the rating beside the board, what it is the rating of: the puzzles'
   ("Combinații"), or in a training session the session's ("Antrenament"),
   tinted as the rating. */
.board-elo-caption {
  padding: 0.3rem 0.8rem;
  border: 1px solid #fcd34d;
  border-radius: 999px;
  background: #fffbeb;
  color: #92400e;
  font-size: 0.95rem;
  font-weight: 800;
  line-height: 1.2;
  white-space: nowrap;
}

:is(.board-elo-caption, .board-elo-note) .caption-session,
body.session-active :is(.board-elo-caption, .board-elo-note) .caption-puzzles {
  display: none;
}

body.session-active :is(.board-elo-caption, .board-elo-note) .caption-session {
  display: inline;
}

/* A session's time left, under its rating. */
.board-session-side {
  display: flex;
  justify-content: center;
  line-height: 1;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.board-session-clock {
  color: var(--hp-text);
  font-weight: 700;
  letter-spacing: -0.03em;
}

/* The fragment's own buttons: one white card, as wide as the king's, at the
   foot of the comment's column (the free space above it pushes it down). */
.move-controls {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  margin-top: auto;
  padding: 12px;
  border: 1px solid var(--hp-border);
  border-radius: var(--hp-radius-card);
  background: var(--hp-surface);
}

.move-controls .btn {
  width: 100%;
  min-height: 44px;
  margin: 0;
  border: 1px solid var(--hp-border);
  border-radius: var(--hp-radius-btn);
  padding: 0.45rem 0.8rem;
  background: var(--hp-surface);
  color: var(--hp-text);
  font-weight: 700;
  font-size: 0.92rem;
  line-height: 1.2;
  box-shadow: none;
  transition: background-color var(--hp-ease), border-color var(--hp-ease), color var(--hp-ease);
}

.move-controls .btn:hover:not(:disabled) {
  background: var(--hp-subtle);
  border-color: #cbd5e1;
  color: var(--hp-text);
}

/* Înapoi: secondary, over the player's own grey for #back-move-btn; and no
   lift on hover for any of these buttons. */
.move-controls #back-move-btn {
  background: var(--hp-surface);
  border-color: var(--hp-border);
  color: var(--hp-text);
}

.move-controls #back-move-btn:hover:not(:disabled) {
  background: var(--hp-subtle);
  border-color: #cbd5e1;
  color: var(--hp-text);
}

.move-controls :is(.btn, #back-move-btn, #next-computer-move-btn):hover {
  transform: none;
  box-shadow: none;
}

.move-controls .btn:focus-visible {
  outline: 2px solid var(--hp-blue);
  outline-offset: 2px;
}

.move-controls .btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Idee: the hint, in amber. */
.move-controls #hint-btn {
  background: #fffbeb;
  border-color: #fcd34d;
  color: #92400e;
}

.move-controls #hint-btn:hover:not(:disabled) {
  background: #fef3c7;
  border-color: var(--hp-amber);
  color: #92400e;
}

/* A session's Sari peste, scored as a miss: grey, quieter than what moves
   the lesson on for free. */
.move-controls #session-skip-btn {
  background: var(--hp-divider);
  border-color: #cbd5e1;
  color: #475569;
}

.move-controls #session-skip-btn:hover:not(:disabled) {
  background: var(--hp-border);
  border-color: #94a3b8;
  color: var(--hp-text);
}

/* What moves the lesson on (both Următorul buttons included): blue. */
.move-controls #next-computer-move-btn,
.move-controls #next-lesson-btn,
.move-controls #return-to-live-btn,
.move-controls .puzzle-skip-btn,
.move-controls .lesson-next-btn {
  background: var(--hp-blue);
  border-color: var(--hp-blue);
  color: white;
}

.move-controls #next-computer-move-btn:hover:not(:disabled),
.move-controls #next-lesson-btn:hover:not(:disabled),
.move-controls #return-to-live-btn:hover:not(:disabled),
.move-controls .puzzle-skip-btn:hover:not(:disabled),
.move-controls .lesson-next-btn:hover:not(:disabled) {
  background: var(--hp-blue-hover);
  border-color: var(--hp-blue-hover);
  color: white;
}

.move-controls #next-computer-move-btn:active:not(:disabled),
.move-controls #next-lesson-btn:active:not(:disabled),
.move-controls #return-to-live-btn:active:not(:disabled),
.move-controls .puzzle-skip-btn:active:not(:disabled),
.move-controls .lesson-next-btn:active:not(:disabled) {
  background: #1e40af;
  border-color: #1e40af;
}

/* The auto-next switch, at the top of the button card. */
.auto-next-toggle {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 2px 2px 4px;
  color: var(--hp-muted);
  font-size: 0.84rem;
  font-weight: 600;
  line-height: 1.25;
  cursor: pointer;
  user-select: none;
}

.auto-next-toggle input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
}

.auto-next-track {
  position: relative;
  flex: none;
  width: 34px;
  height: 20px;
  border-radius: 999px;
  background: #cbd5e1;
  transition: background-color var(--hp-ease);
}

.auto-next-track::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: white;
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.25);
  transition: transform var(--hp-ease);
}

.auto-next-toggle input:checked + .auto-next-track {
  background: var(--hp-green);
}

.auto-next-toggle input:checked + .auto-next-track::after {
  transform: translateX(14px);
}

.auto-next-toggle input:focus-visible + .auto-next-track {
  outline: 2px solid var(--hp-blue);
  outline-offset: 2px;
}

.auto-next-toggle:hover .auto-next-label,
.auto-next-toggle input:checked ~ .auto-next-label {
  color: var(--hp-text);
}

/* The lesson's comment and buttons: the column beside the board (the grid
   below), under it on a phone. */
.chess-info-panel {
  flex: none;
  min-width: 0;
  min-height: 0;
  overflow: auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

@media (min-width: 900px) {
  .chess-lesson-area,
  chess-lesson-player.chess-lesson-content,
  .lesson-player-root {
    flex: 1 1 0;
    min-height: 0;
    min-width: 0;
    max-height: none;
  }

  /* The player's own box is what the board below is sized from. */
  chess-lesson-player.chess-lesson-content {
    container-type: size;
  }

  /* The area holding the player (and a training session's bar over it) is
     a container too, so the bar can work out the player's columns (below).
     The columns' minimums and shares are given here for both, and what the
     rating's column gives the comment's out of its share. */
  .chess-lesson-area {
    container-type: size;
    --rating-min: 140px;
    --info-min: 190px;
    --board-gap: 16px;
    --rating-share: 0.55;
    --rating-give: 20px;
  }

  /* A session's bar is as tall as given, so the player under it is the
     area's height less the bar and its margin, and its Terminare sits over
     the right-hand column (the comment's), centred: the bar works out that
     column's width as the player's grid does for a puzzle (a session's
     puzzles have no title row), and an empty part as wide at the left keeps
     the name centred over the whole bar. */
  .training-session-bar {
    --bar-h: 54px;
    --board: max(
      0px,
      min(
        100cqh - var(--bar-h) - 4px - 22px,
        100cqw - var(--rating-min) - var(--info-min) - 2 * var(--board-gap)
      )
    );
    --side-room: calc(100cqw - var(--board) - 2 * var(--board-gap));
    --info-w: calc(
      var(--side-room) + var(--rating-give) -
        max(
          var(--rating-min),
          min(
            var(--side-room) * var(--rating-share) / (1 + var(--rating-share)),
            var(--side-room) - var(--info-min)
          )
        )
    );
    height: var(--bar-h);
    padding-inline: 0;
  }

  .training-session-bar::before,
  .training-session-bar .ts-actions {
    flex: 0 0 var(--info-w);
  }

  .training-session-bar .ts-actions {
    justify-content: center;
  }

  .training-session-bar .ts-heading {
    flex: 1 1 0;
  }

  /* A puzzle's three columns: the rating, the board with the attribution
     under it, and the comment, moves and buttons. The board is the largest
     square that leaves each side its minimum; room to spare goes mostly to
     the right-hand column (1 part to the rating's 0.55), so the board sits
     left of centre. A puzzle has no title (its rating says what it is), so
     the board starts at the column's top, level with the right-hand cards;
     --frame is the height the board leaves to the rows around it. The
     rating's column is its share (--side-w, its minimum while the board
     takes the rest) less --rating-give, which the comment's column gets. */
  .lesson-player-root {
    --frame: 22px;
    --board: max(
      0px,
      min(
        100cqh - var(--frame),
        100cqw - var(--rating-min) - var(--info-min) - 2 * var(--board-gap)
      )
    );
    --side-room: calc(100cqw - var(--board) - 2 * var(--board-gap));
    --side-w: max(
      var(--rating-min),
      min(
        var(--side-room) * var(--rating-share) / (1 + var(--rating-share)),
        var(--side-room) - var(--info-min)
      )
    );
    display: grid;
    grid-template-columns:
      calc(var(--side-w) - var(--rating-give)) var(--board)
      minmax(var(--info-min), 1fr);
    grid-template-rows: var(--board) 18px;
    grid-template-areas:
      "rating board       info"
      ".      attribution info";
    column-gap: var(--board-gap);
    row-gap: 4px;
    align-content: start;
  }

  .lesson-player-root[data-lesson-id^="puzzle-"] .lesson-header-bar {
    display: none;
  }

  /* A lesson (any id but a puzzle's "puzzle-", as the player itself tells
     them apart) has no rating: the board, the same size, at the left, under
     the lesson's title, and the explanation's column takes the rest. */
  .lesson-player-root:not([data-lesson-id^="puzzle-"]) {
    --frame: 56px;
    grid-template-columns: var(--board) minmax(var(--info-min), 1fr);
    grid-template-rows: 30px var(--board) 18px;
    grid-template-areas:
      "title       ."
      "board       info"
      "attribution info";
  }

  /* Its children are the grid's. */
  .chess-panels-container {
    display: contents;
  }

  .lesson-header-bar {
    grid-area: title;
  }

  /* The column beside the board, as tall as it: "Revizuire" at the top,
     the player's rating under its caption three fifths of the way up (two
     parts of the free height above it, three below), a training session's
     clock a third of the way on from it to the puzzle's rating, at the
     bottom. */
  .board-side {
    grid-area: rating;
    min-width: 0;
    display: grid;
    grid-template-rows: 2fr auto auto auto 1fr auto 2fr;
    justify-items: center;
  }

  /* Clear of the rating's change flashing over the rating (0.4em of it,
     0.15em above it). */
  .board-elo-caption {
    grid-row: 2;
    align-self: end;
    margin-bottom: calc(var(--elo-size) * 0.62);
  }

  .board-session-side {
    grid-row: 6;
    font-size: clamp(2rem, var(--col-w) / 3.6, 5.5rem);
  }

  .board-side-stats {
    display: contents;
  }

  .board-review-badge {
    display: block;
    grid-row: 1;
    align-self: start;
  }

  .board-player-elo {
    grid-row: 3;
  }

  .board-elo-note {
    grid-row: 4;
    margin-top: 0.5rem;
  }

  .board-puzzle-rating {
    grid-row: 7;
    align-self: end;
  }

  /* A puzzle's board leaves "Revizuire" to the column. */
  .lesson-player-root[data-lesson-id^="puzzle-"] .board-locked::after {
    display: none;
  }

  /* Mutări efectuate: one pair of moves to a row (the box's height is set
     after its own rules, below). */
  .moves-history-list .move-pair {
    display: grid;
    grid-template-columns: 2.75em 1fr 1fr;
    align-items: baseline;
    margin: 0;
  }

  .moves-history-list :is(.white-move, .black-move) {
    justify-self: start;
    margin: 0;
    padding: 0 4px;
    border-radius: 4px;
  }

  /* The rating sized from the left column's own width (the root's --side-w
     less what it gives), over about four digits' worth, so a four-digit
     rating keeps clear of the board. */
  .board-side {
    --col-w: calc(var(--side-w) - var(--rating-give));
    --elo-size: clamp(2.75rem, var(--col-w) / 2.55, 7.5rem);
  }

  .lesson-player-root:not([data-lesson-id^="puzzle-"]) .board-side {
    display: none;
  }

  .board-player-elo {
    font-size: var(--elo-size);
  }

  .board-puzzle-rating-value {
    font-size: clamp(1.1rem, var(--col-w) / 8, 1.8rem);
  }

  .lichess-attribution {
    grid-area: attribution;
  }

  .chess-info-panel {
    grid-area: info;
  }

  /* The column runs on past the board by the attribution's row (18px and
     the 4px gap); the button card ends level with the board instead. */
  .move-controls {
    margin-bottom: 22px;
  }

  .chess-board-panel {
    grid-area: board;
    min-width: 0;
    min-height: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    overflow: hidden;
    /* Size containment: the square below is a fraction of this panel.
       The panel's own size comes from the grid/flex column, not from the
       board, so a move that replaces the board cannot change the panel. */
    container-type: size;
  }

  /* Largest square that fits the panel. Both axes are set from the panel's
     container size so the used box is square on the first layout.
     `#chessboard { width: 100% }` would otherwise win over a class rule and
     stretch the board to the full panel width whenever the panel is wider
     than it is tall. width:100% + max-height + aspect-ratio does not pull
     that width back down. */
  #chessboard.chessboard-container {
    width: min(100cqw, 100cqh);
    height: min(100cqw, 100cqh);
    min-width: 0;
    min-height: 0;
    aspect-ratio: 1 / 1;
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.06), 0 6px 18px rgba(15, 23, 42, 0.07);
  }
}

/* The right-hand column, top to bottom: the side's card with the comment
   joined under it, the commentary's audio player (the player mounts it
   right after the header), the moves played, and the button card. */
#comment-header {
  order: 1;
}

#move-comment-container {
  order: 2;
}

.lesson-commentary {
  order: 3;
}


.move-controls {
  order: 5;
}

/* The lesson's comment. */
#comment-header {
  border: 1px solid var(--hp-border);
  border-radius: var(--hp-radius-card);
  background: var(--hp-surface);
  color: var(--hp-muted);
  box-shadow: none;
  font-size: 0.9rem;
  font-weight: 600;
  text-align: center;
}

/* "Joci cu albul / negrul", and the side's king under it at twice its size. */
#comment-header .player-side {
  font-size: 1rem;
  font-weight: 700;
  color: var(--hp-text);
}

/* The side's king: the card's main figure, whichever colour; 96px while the
   column is tall enough, a little less on a short screen, where the moves
   and the buttons need the room. */
#comment-header .king-piece-icon {
  display: block;
  width: auto;
  height: clamp(64px, 12cqh, 96px);
  max-width: 100%;
  margin: 0.4rem auto 0.1rem;
  object-fit: contain;
}


#comment-header.has-comment {
  border-radius: var(--hp-radius-card) var(--hp-radius-card) 0 0;
  border-bottom: none;
}

/* A correct move's comment: Chessnut's green, as a hairline. */
#comment-header.comment-success,
#move-comment-container.comment-success {
  border-color: #bbf7d0;
}

#move-comment-container.comment-success .move-comment-text {
  color: #166534;
}

#move-comment-container {
  flex: 0 1 auto;
  min-height: 3.5rem;
  overflow: auto;
  margin: 0;
  border: 1px solid var(--hp-border);
  border-top: 1px solid var(--hp-divider);
  border-radius: 0 0 var(--hp-radius-card) var(--hp-radius-card);
}

/* Joined to the side's card above it, across the column's gap. */
#comment-header.has-comment ~ #move-comment-container {
  margin-top: -8px;
}

/* The commentary's own player, shown only while a commentary exists. */
.lesson-commentary {
  display: block;
  flex: none;
  width: 100%;
  height: 40px;
  border-radius: 999px;
}




.moves-history-list .move-pair.game-history :is(.white-move, .black-move) {
  color: var(--hp-muted);
}

.moves-history-list .move-number {
  color: var(--hp-muted);
  font-weight: 700;
}

.moves-history-list .white-move,
.moves-history-list .black-move {
  font-weight: 600;
}

.moves-history-list .clickable-move:hover {
  background: var(--hp-selected);
  color: var(--hp-blue-hover);
}

/* The move that sets a puzzle, the last of its game before it: the puzzle's
   position is the one after it. */
.moves-history-list .move-pair .clickable-move.puzzle-start {
  outline: 2px solid var(--hp-blue);
  outline-offset: 1px;
  color: var(--hp-blue-hover);
}

/* The move the board shows (the last one while live). */
.moves-history-list .move-pair .clickable-move.current-move,
.moves-history-list .move-pair .clickable-move.current-move:hover {
  background: var(--hp-blue);
  color: white;
  font-weight: 800;
}

/* Beside the board the box takes the column's height down to the button
   card. */
@media (min-width: 900px) {
  .moves-history-container {
    flex: 1 1 0;
    max-height: none;
  }
}

/* ===== RIGHT RAIL =====
   Two groups, each one white card: the player's own points, then today's
   rankings; the sections inside a group are divided by hairlines. */
.dashboard-rail {
  width: 236px;
  flex: none;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 4px 8px 4px 0;
  overflow: auto;
  background: var(--hp-bg);
}

.dashboard-rail > .rail-group {
  flex: 0 0 auto;
}

.rail-group {
  background: var(--hp-surface);
  border: 1px solid var(--hp-border);
  border-radius: var(--hp-radius-card);
  padding: 12px 12px 4px;
}

.rail-card {
  padding: 14px 0;
}

.rail-group > .rail-card:first-child {
  padding-top: 8px;
}

.rail-card + .rail-card {
  border-top: 1px solid var(--hp-border);
}

.rail-card h3 {
  margin: 0;
  font-size: 0.9rem;
  font-weight: 800;
  color: var(--hp-text);
  white-space: nowrap;
}

/* A card's title: a heading, or a ranking's button. */
.rail-card-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  column-gap: 8px;
  row-gap: 1px;
  margin-bottom: 6px;
}

/* A ranking card's title, and the way into the whole ranking: a button,
   so a discreet blue outline around the title's own words. */
.rail-title-link {
  flex: none;
  padding: 2px 9px;
  border: 2px solid var(--hp-blue-line);
  border-radius: 999px;
  background: none;
  color: var(--hp-blue);
  font: inherit;
  font-size: 0.9rem;
  font-weight: 800;
  line-height: 1.3;
  cursor: pointer;
  transition: background-color var(--hp-ease), border-color var(--hp-ease);
}

.rail-title-link:hover {
  border-color: var(--hp-blue);
  background: var(--hp-selected);
}

.rail-title-link:focus-visible {
  outline: 2px solid var(--hp-blue);
  outline-offset: 2px;
}

.rail-rank-body {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.rail-rank-place {
  margin: 0;
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--hp-muted);
}

.rail-rank-place span {
  font-size: 1.6rem;
  font-weight: 800;
  color: var(--hp-blue);
  margin: 0 0.15rem;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.rail-rank-delta {
  margin: 0.25rem 0 0;
  font-size: 0.72rem;
  line-height: 1.4;
  color: var(--hp-muted);
}

/* Beside the place, the place's trophy, large (img/trophies/*-large: 176px
   squares, sharp at twice this size). */
.rail-trophy {
  width: 88px;
  height: 88px;
  flex: none;
  /* In from the card's edge, and up beside the card's title, level with it. */
  align-self: flex-start;
  margin: -34px 0 0 0;
  background: center / contain no-repeat;
}

.rail-trophy.trophy-1 {
  background-image: url("/img/trophies/gold-large.webp?v=1");
}

.rail-trophy.trophy-2 {
  background-image: url("/img/trophies/silver-large.webp?v=1");
}

.rail-trophy.trophy-3 {
  background-image: url("/img/trophies/bronze-large.webp?v=1");
}

.rail-points-today {
  position: relative;
  margin-bottom: 0.6rem;
}

.rail-points-value {
  margin: 0;
  font-size: 1.6rem;
  font-weight: 800;
  color: var(--hp-text);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}

/* The day's goal reached: its bonus over the day's points, for a moment
   (dashboard.js unhides it and hides it again when the animation ends). */
.rail-bonus {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 6px 10px;
  border-radius: var(--hp-radius-item);
  background: linear-gradient(135deg, #fff7ed, #ffedd5);
  border: 1px solid #fdba74;
  box-shadow: 0 6px 18px rgba(234, 88, 12, 0.25);
  color: #9a3412;
  pointer-events: none;
  transform-origin: left bottom;
  animation: rail-bonus-pop 3.2s ease-out forwards;
}

.rail-bonus[hidden] {
  display: none;
}

.rail-bonus strong {
  font-family: var(--hp-font-play);
  font-size: 2rem;
  font-weight: 700;
  line-height: 1;
  color: #ea580c;
}

.rail-bonus span {
  font-size: 0.74rem;
  font-weight: 700;
  line-height: 1.25;
}

@keyframes rail-bonus-pop {
  0% {
    opacity: 0;
    transform: translateY(6px) scale(0.6);
  }
  12% {
    opacity: 1;
    transform: translateY(-4px) scale(1.08);
  }
  20% {
    transform: translateY(-4px) scale(1);
  }
  85% {
    opacity: 1;
    transform: translateY(-4px) scale(1);
  }
  100% {
    opacity: 0;
    transform: translateY(-14px) scale(1);
  }
}

.rail-points-target {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 6px;
  font-size: 0.8rem;
  color: var(--hp-muted);
}

.rail-points-target strong {
  color: var(--hp-text);
}

/* The goal reached: its bonus beside it. */
.rail-points-target .rail-goal-bonus {
  color: var(--hp-green);
}

.rail-points-target strong::before {
  content: "🔥 ";
}

.rail-progress {
  height: 8px;
  border-radius: 999px;
  background: var(--hp-divider);
  overflow: hidden;
}

/* The day's progress toward its goal, in the fire's orange. */
.rail-progress span {
  display: block;
  height: 100%;
  width: 0;
  max-width: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, #fb923c, #ea580c);
  transition: width 600ms ease;
}

.rail-top-list {
  --rail-row-h: 30px;
  --rail-row-gap: 2px;
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--rail-row-gap);
}

.rail-top-row {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr) auto;
  align-items: center;
  gap: 8px;
  flex: none;
  height: var(--rail-row-h);
  padding: 2px 4px;
  border-radius: 8px;
}

/* A ranking shows a few rows and scrolls to the rest (up to fifty): five on
   a card, ten in its window. The viewer's own row, once below those, stays
   under it. */
.rail-scroll {
  --rail-in-sight: 5;
  max-height: calc(
    var(--rail-in-sight) * var(--rail-row-h) + (var(--rail-in-sight) - 1) * var(--rail-row-gap)
  );
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--hp-border) transparent;
}

.rail-scroll:focus-visible {
  outline: 2px solid var(--hp-blue);
  outline-offset: 2px;
  border-radius: 8px;
}

.rail-scroll.day-ranking {
  --rail-in-sight: 10;
}

/* A ranking's window: a tab per period over its ranking (the points' four,
   the training's two), the chosen one raised in white. */
.ranking-tabs {
  display: flex;
  gap: 4px;
  margin-bottom: 12px;
  padding: 4px;
  border-radius: var(--hp-radius-btn);
  background: var(--hp-divider);
}

.ranking-tab {
  flex: 1 1 0;
  min-width: 0;
  padding: 6px 8px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--hp-muted);
  font: 600 0.85rem/1.2 var(--hp-font);
  cursor: pointer;
  transition:
    background var(--hp-ease),
    color var(--hp-ease);
}

.ranking-tab:hover {
  color: var(--hp-text);
}

.ranking-tab[aria-selected="true"] {
  background: var(--hp-surface);
  color: var(--hp-blue);
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.08);
}

.ranking-tab:focus-visible {
  outline: 2px solid var(--hp-blue);
  outline-offset: 2px;
}

/* On a phone a quarter of the strip is narrower than "Săptămâna": a tab is
   never narrower than its longest word, the rest shared out equally. */
@media (max-width: 575.98px) {
  .ranking-tab {
    min-width: min-content;
    padding: 6px 4px;
    font-size: 0.8rem;
  }
}

/* What a paid place won, beside its points or rating: its ranking's prize. */
.rail-prize {
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 999px;
  background: #dcfce7;
  color: var(--hp-green);
  font-size: 0.74rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Under a past period's ranking while its prizes are not given yet. */
.ranking-note {
  margin: 10px 0 0;
  color: var(--hp-muted);
  font-size: 0.8rem;
}

.rail-own {
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px dashed var(--hp-border);
}

/* Kept on the card for the rail's stream to fill: nothing to show until the
   viewer is below the five in sight. */
.rail-own:not(:has(li)) {
  display: none;
}

.rail-top-row.is-me {
  background: var(--hp-selected);
  box-shadow: inset 0 0 0 1.5px var(--hp-blue);
}

.rail-top-row.is-me .rail-name {
  font-weight: 700;
}

.rail-medal {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--hp-font-play);
  font-size: 0.74rem;
  font-weight: 600;
  background: var(--hp-divider);
  color: var(--hp-muted);
}

/* The first three hold a trophy, gold, silver or bronze (img/trophies, the
   pictures beside "Locul", smaller), with the place written over its
   cup: the picture's own number is too small to read at this size. */
:root {
  --trophy-gold: url("/img/trophies/gold.webp?v=1");
  --trophy-silver: url("/img/trophies/silver.webp?v=1");
  --trophy-bronze: url("/img/trophies/bronze.webp?v=1");
}

.rail-medal.medal-1,
.rail-medal.medal-2,
.rail-medal.medal-3 {
  width: 22px;
  height: 26px;
  align-items: flex-start;
  padding-top: 3px;
  border-radius: 0;
  font-size: 0.68rem;
  font-weight: 700;
  line-height: 1;
  background: var(--trophy) center / contain no-repeat;
  color: #fff;
  text-shadow:
    0 0 1px var(--trophy-ink),
    0 0 2px var(--trophy-ink),
    0 0 2px var(--trophy-ink),
    0 0 3px var(--trophy-ink);
}

.rail-medal.medal-1 {
  --trophy: var(--trophy-gold);
  --trophy-ink: #6b3f00;
}

.rail-medal.medal-2 {
  --trophy: var(--trophy-silver);
  --trophy-ink: #1f2937;
}

.rail-medal.medal-3 {
  --trophy: var(--trophy-bronze);
  --trophy-ink: #4a1f05;
}


.rail-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.86rem;
  font-weight: 500;
  color: var(--hp-text);
}

.rail-score {
  justify-self: end;
  min-width: 4ch;
  text-align: right;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--hp-text);
  font-size: 0.86rem;
}

/* The training and the total leaderboards, in their windows: a ranking's
   table shows ten rows and scrolls to the rest (up to fifty), its header on
   top and, once the viewer is below the ten, their own row (the tfoot) kept
   under the list, as the day rankings' lists. */
.ranking-table {
  --ranking-head-h: 2.75rem;
  --ranking-row-h: 2.5rem;
  --ranking-in-sight: 10;
  --ranking-rows-h: calc(var(--ranking-in-sight) * var(--ranking-row-h));
  max-height: min(calc(var(--ranking-head-h) + var(--ranking-rows-h) + 2px), calc(70vh - 3rem));
  overflow: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--hp-border) transparent;
  border: 1px solid var(--hp-border);
  border-radius: 10px;
  font-family: var(--hp-font);
}

.ranking-table.has-own {
  --ranking-rows-h: calc((var(--ranking-in-sight) + 1) * var(--ranking-row-h));
}

.ranking-table:focus-visible {
  outline: 2px solid var(--hp-blue);
  outline-offset: 2px;
}

.ranking-table .table {
  margin: 0;
  border-collapse: separate;
  border-spacing: 0;
}

.ranking-table th,
.ranking-table td {
  height: var(--ranking-row-h);
  padding: 0 0.85rem;
  border: none;
  white-space: nowrap;
  vertical-align: middle;
  font-size: 0.9rem;
  color: var(--hp-text);
  background: #fff;
}

.ranking-table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  height: var(--ranking-head-h);
  background: var(--color-gray);
  color: #fff;
  font-weight: 700;
}

.ranking-table tbody tr:nth-child(even) td {
  background: var(--hp-divider);
}

.ranking-table tbody tr:hover td {
  background: var(--hp-border);
}

.ranking-table tr.is-me td,
.ranking-table tbody tr.is-me:hover td {
  background: var(--hp-selected);
}

.ranking-table tr.is-me .ranking-name {
  font-weight: 800;
}

/* The stripes are nearly the highlight's colour: the viewer's row, in the
   list and kept under it, is outlined too, drawn inside its cells so that
   no row moves. */
.ranking-table tr.is-me td {
  box-shadow:
    inset 0 2px 0 var(--hp-blue),
    inset 0 -2px 0 var(--hp-blue);
}

.ranking-table tr.is-me td:first-child {
  border-radius: 8px 0 0 8px;
  box-shadow:
    inset 2px 0 0 var(--hp-blue),
    inset 0 2px 0 var(--hp-blue),
    inset 0 -2px 0 var(--hp-blue);
}

.ranking-table tr.is-me td:last-child {
  border-radius: 0 8px 8px 0;
  box-shadow:
    inset -2px 0 0 var(--hp-blue),
    inset 0 2px 0 var(--hp-blue),
    inset 0 -2px 0 var(--hp-blue);
}

.ranking-table tfoot td {
  position: sticky;
  bottom: 0;
  z-index: 1;
  box-shadow: inset 0 2px 0 var(--hp-blue);
}

.ranking-table td .rail-medal {
  vertical-align: middle;
}

/* Past the trophies a place is a pill, outlined so that it shows on every
   row's colour, and wide enough for a place in the thousands. */
.ranking-table td .rail-medal:not(.medal-1, .medal-2, .medal-3) {
  width: auto;
  min-width: 22px;
  padding: 0 6px;
  border-radius: 11px;
  background: #fff;
  box-shadow: inset 0 0 0 1px var(--hp-border);
}

.ranking-name {
  max-width: 14rem;
  overflow: hidden;
  text-overflow: ellipsis;
  font-weight: 600;
}

/* A paid place's name with its prize after it: a long name gives way, the
   prize never does. */
.ranking-user {
  display: flex;
  align-items: center;
  min-width: 0;
}

.ranking-username {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ranking-user .rail-prize {
  flex: none;
}

.ranking-table .ranking-empty {
  text-align: center;
  color: var(--hp-muted);
  white-space: normal;
}

@media (max-width: 575.98px) {
  .ranking-table th,
  .ranking-table td {
    padding: 0 0.55rem;
    font-size: 0.84rem;
  }
}

.rail-empty {
  color: var(--hp-muted);
  font-size: 0.76rem;
  line-height: 1.4;
  padding: 4px;
}

.rail-rank-list:not(:empty) {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--hp-divider);
}

/* ===== TABLET: board and training panel stay side by side; widgets drop ===== */
@media (max-width: 1279px) {
  body:has(.app-layout),
  body:has(.app-layout):has(.chess-lesson-content) {
    overflow: auto;
    height: auto;
  }

  .main-content:has(.app-layout) {
    overflow: auto;
    height: auto;
    min-height: 100dvh;
  }

  .app-layout {
    flex-wrap: wrap;
    align-items: stretch;
    height: auto;
    min-height: calc(100dvh - var(--header-block-size));
    overflow: visible;
  }

  .dashboard-center {
    flex: 1 1 0;
    height: calc(100dvh - var(--header-block-size));
    max-height: calc(100dvh - var(--header-block-size));
  }

  .dashboard-rail {
    width: 100%;
    flex: 1 1 100%;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: flex-start;
    overflow: visible;
    padding: 0 10px 16px;
  }

  .dashboard-rail > .rail-group {
    flex: 1 1 300px;
  }
}

/* ===== PHONE AND NARROW TABLET: board first, then buttons, then stats ===== */
@media (max-width: 899px) {
  .dashboard-center {
    display: flex;
    flex-direction: column;
    height: auto;
    max-height: none;
    padding: 6px 6px 12px;
    gap: 8px;
  }

  .dashboard-center > .chess-lesson-area {
    order: 2;
    flex: 0 0 auto;
    height: auto;
    min-height: 0;
    overflow: visible;
  }

  chess-lesson-player.chess-lesson-content,
  .lesson-player-root,
  .chess-panels-container {
    flex: 0 0 auto;
    height: auto;
    max-height: none;
    min-height: 0;
    block-size: auto;
    overflow: visible;
  }

  /* Above the board, side by side. */
  .board-side {
    margin: 0 0 6px;
  }

  .board-side-stats {
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: 1.4rem 1.25rem;
  }

  /* The caption on a line of its own, over the numbers, clear of the
     rating's change flashing over the rating. */
  .board-side-stats::before {
    content: "";
    order: 1;
    flex-basis: 100%;
  }

  .board-side-stats > :not(.board-elo-caption) {
    order: 2;
  }

  .board-player-elo {
    font-size: 2.65rem;
  }

  .board-session-side {
    flex-direction: row;
    align-items: baseline;
    gap: 0.6rem;
    font-size: 2rem;
  }

  .board-puzzle-rating-value {
    font-size: 1.2rem;
  }

  /* Above the board the caption over the numbers says what the rating is. */
  .board-elo-note {
    display: none;
  }

  .lichess-attribution {
    margin-top: 4px;
  }

  /* The panel's box comes from its width and aspect-ratio, not from the
     board, so a move cannot resize it. max-height keeps the action row on
     screen on short viewports; the square inside then uses the smaller axis. */
  .chess-board-panel {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: auto;
    aspect-ratio: 1 / 1;
    max-height: calc(100dvh - var(--header-block-size) - 9.2rem);
    padding: 0;
    overflow: hidden;
    container-type: size;
  }

  #chessboard.chessboard-container {
    width: min(100cqw, 100cqh);
    height: min(100cqw, 100cqh);
    min-width: 0;
    min-height: 0;
    aspect-ratio: 1 / 1;
    margin: 0 auto;
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.06), 0 6px 18px rgba(15, 23, 42, 0.07);
  }

  /* Under the board: the fragment's buttons first, then the side's card and
     the comment, which scrolls inside its own height. */
  .chess-info-panel {
    height: auto;
    overflow: visible;
    margin-top: 8px;
  }

  #move-comment-container {
    max-height: 12rem;
  }

  .move-controls {
    order: -1;
    flex-direction: row;
    flex-wrap: wrap;
    margin-top: 0;
  }

  .move-controls .auto-next-toggle {
    flex: 1 1 100%;
  }

  #comment-header .king-piece-icon {
    height: 72px;
  }

  .move-controls .btn {
    flex: 1 1 9.5rem;
    width: auto;
    min-height: 44px;
  }
}

@media (max-width: 767px) {

  .training-session-bar .ts-count {
    font-size: 1.4rem;
  }
}

/* ===== PHONE: the whole game on one screen, with nothing to scroll =====
   Top to bottom: the side played and the player's rating (a session's, in a
   session), beside the menu tab; the board, as wide as the screen; the
   moves on one scrolling line; the button card (the auto-next switch over
   the buttons, side by side); the day's points, one line over their bar.
   Left out: the caption over the rating and its note, the puzzle's own
   rating, the Lichess line and the rankings. A training session has its
   bar over these and no points; a lesson has its title in the side's row,
   its comment over the buttons and no switch nor points.

   The fragment is not changed (the WASM renders the same one): its root
   becomes a grid, the panels' children its cells. Every row has a fixed
   height (--ph-*), so the board is as wide as the screen whenever they fit
   under it, and gives way to them on a screen too short. */
@media (max-width: 575.98px) {
  .app-layout {
    --ph-gap: 4px;
    --ph-row: 44px; /* the menu tab's height */
    --ph-moves: 34px;
    --ph-pad: 6px;
    --ph-switch: 20px;
    --ph-button: 38px;
    --ph-controls: calc(var(--ph-switch) + var(--ph-button) + 3 * var(--ph-pad) + 2px);
    --ph-points: 43px;
    --ph-rows: calc(
      var(--ph-row) + var(--ph-moves) + var(--ph-controls) + var(--ph-points) + 5 * var(--ph-gap)
    );
  }

  .dashboard-center {
    padding: 0 var(--ph-gap);
    gap: 0;
  }

  /* No row gap: a row whose cell is not there (no comment, no commentary)
     would keep its gaps; each cell under the first keeps its own margin. */
  .lesson-player-root {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "side elo"
      "board board"
      "moves moves"
      "comment comment"
      "audio audio"
      "controls controls";
    column-gap: 8px;
    align-items: center;
  }

  .chess-panels-container,
  .chess-info-panel,
  .lesson-player-root .board-side,
  .lesson-player-root:not([data-lesson-id^="puzzle-"]) .board-side {
    display: contents;
  }

  /* The side played, level with the menu tab (fixed under the bar) and
     clear of it. */
  #comment-header,
  #comment-header.has-comment {
    grid-area: side;
    display: flex;
    align-items: center;
    gap: 0.4rem;
    height: var(--ph-row);
    margin: 0 0 0 50px;
    padding: 0;
    border: none;
    border-radius: 0;
    background: none;
    text-align: left;
  }

  #comment-header::before {
    content: none;
  }

  #comment-header .player-side {
    font-size: 0.95rem;
    white-space: nowrap;
  }

  #comment-header .king-piece-icon {
    height: 28px;
    margin: 0;
  }

  /* The player's puzzle rating, or in a training session the session's with
     its clock (dashboard.js), in the rating's orange, larger than the side's
     words. */
  .board-side-stats {
    grid-area: elo;
    flex-wrap: nowrap;
    align-items: baseline;
    gap: 0.75rem;
    margin-right: 4px;
  }

  .board-side-stats::before,
  .board-elo-caption,
  .board-elo-note,
  .board-puzzle-rating,
  .lichess-attribution {
    display: none;
  }

  .board-player-elo {
    font-size: 1.85rem;
  }

  .board-session-side {
    font-size: 1.25rem;
  }

  /* The rating's change, at its left: over it there is only the bar. */
  .board-elo-change {
    top: 0;
    bottom: auto;
    left: auto;
    right: 100%;
    margin: 0 0.3em 0 0;
    font-size: 0.5em;
    line-height: 1.8;
    text-align: right;
  }

  .chess-board-panel {
    grid-area: board;
    margin-top: var(--ph-gap);
    max-height: calc(100dvh - var(--header-block-size) - var(--ph-rows));
  }

  /* An earlier position: the board is dimmed, and says so under the moves,
     over the switch's line, rather than over its pieces. */
  .board-locked::after {
    content: none;
  }

  .board-review-badge {
    grid-area: controls;
    align-self: start;
    z-index: 11; /* over the button card's own 10 (chess-lesson-player.css) */
    display: flex;
    align-items: center;
    justify-content: center;
    height: calc(var(--ph-switch) + 4px);
    margin: calc(var(--ph-gap) + var(--ph-pad) - 2px) 6px 0;
    padding: 0 0.75rem;
    /* Opaque: the switch is under it. Its own colour over white. */
    background: #333a4a;
    font-size: 0.82rem;
  }

  .moves-history-container {
    grid-area: moves;
    height: var(--ph-moves);
    min-height: 0;
    margin: var(--ph-gap) 0 0;
  }

  .moves-history-list {
    height: 100%;
    padding: 0 8px;
    scrollbar-width: none;
  }

  .moves-history-list::-webkit-scrollbar {
    display: none;
  }

  #move-comment-container,
  #comment-header.has-comment ~ #move-comment-container {
    grid-area: comment;
    align-self: start;
    min-height: 0;
    max-height: calc(100% - var(--ph-gap));
    margin: var(--ph-gap) 0 0;
    border-top-color: var(--hp-border);
    border-radius: var(--hp-radius-card);
  }

  .move-comment-text {
    padding: 6px 10px;
    font-size: 0.88rem;
    line-height: 1.4;
  }

  .lesson-commentary {
    grid-area: audio;
    margin-top: var(--ph-gap);
  }

  .move-controls {
    grid-area: controls;
    position: static;
    height: var(--ph-controls);
    gap: var(--ph-pad);
    margin: var(--ph-gap) 0 0;
    padding: var(--ph-pad) 8px;
    background: var(--hp-surface);
  }

  .move-controls .auto-next-toggle {
    height: var(--ph-switch);
    padding: 0;
  }

  /* Every button on one line, sharing it (the ids outweigh the player's
     own touch-size rule). */
  .move-controls :is(.btn, #back-move-btn, #next-computer-move-btn) {
    flex: 1 1 0;
    min-width: 0;
    height: var(--ph-button);
    min-height: 0;
    padding: 0 0.5rem;
    font-size: 0.88rem;
    white-space: nowrap;
  }

  /* The day's points, one line over their bar. */
  .dashboard-rail {
    gap: 0;
    padding: var(--ph-gap);
  }

  .dashboard-rail > .rail-group:not(:first-child) {
    display: none;
  }

  .dashboard-rail > .rail-group {
    height: var(--ph-points);
    padding: 6px 10px;
  }

  .dashboard-rail > .rail-group:first-child > .rail-card {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto;
    align-items: baseline;
    column-gap: 0.4rem;
    row-gap: 5px;
    padding: 0;
  }

  .dashboard-rail .rail-card-head {
    margin: 0;
  }

  .dashboard-rail .rail-card h3 {
    font-size: 0.86rem;
  }

  /* The card opens today's points ranking (dashboard.js): a chevron after
     its title says so. */
  .dashboard-rail > .rail-group:first-child {
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }

  .dashboard-rail > .rail-group:first-child:active {
    background: var(--hp-selected);
  }

  .dashboard-rail > .rail-group:first-child h3::after {
    content: " ›";
    color: var(--hp-blue);
    font-size: 1.1em;
  }

  /* The goal's bonus, over the whole card. */
  .dashboard-rail .rail-points-today {
    position: static;
    margin: 0;
  }

  .dashboard-rail .rail-points-value {
    font-size: 1.1rem;
    line-height: 1;
  }

  .dashboard-rail .rail-points-target {
    gap: 0.4rem;
    margin: 0;
    font-size: 0.78rem;
  }

  .dashboard-rail .rail-points-target > span:first-child {
    display: none;
  }

  .dashboard-rail .rail-points-target::before {
    content: "/";
  }

  .dashboard-rail .rail-progress {
    grid-column: 1 / -1;
    height: 5px;
  }

  /* --- A training session's summary: its rows closer, so that it and its
     two buttons are on the screen with the day's points. --- */
  .lesson-welcome:has(.training-session-summary) {
    padding: var(--ph-gap) 0 0;
  }

  .training-session-summary {
    padding: 0.75rem 0.9rem;
  }

  .session-summary-title {
    margin-bottom: 0.4rem;
    font-size: 1.2rem;
  }

  .session-stats {
    margin-bottom: 0.75rem;
  }

  .stat-row {
    padding: 0.45rem 0.5rem;
  }

  /* --- A puzzle: no title. --- */
  .lesson-player-root[data-lesson-id^="puzzle-"] .lesson-header-bar {
    display: none;
  }

  /* --- A training session: its bar beside the menu tab, in the side's
     place (the side's row then has the width), and no points under the
     buttons. --- */
  body.session-active .app-layout {
    --ph-rows: calc(2 * var(--ph-row) + var(--ph-moves) + var(--ph-controls) + 4 * var(--ph-gap));
  }

  body.session-active .training-session-bar {
    height: var(--ph-row);
    margin: 0 0 var(--ph-gap) 50px;
    padding-top: 0;
    padding-bottom: 0;
  }

  body.session-active #comment-header {
    margin-left: 4px;
  }

  /* "#1 Antrenament" at the left, Terminare at the right; the name smaller
     on a screen too narrow for it at full size (it needs about 6.2 times
     its size in width, beside some 210px of tab, number and button). */
  body.session-active .training-session-bar::before {
    content: none;
  }

  .training-session-bar .ts-heading {
    flex: 1 1 auto;
    justify-content: flex-start;
    gap: 0.45rem;
  }

  .training-session-bar .ts-count {
    font-size: 1.2rem;
  }

  .training-session-bar .ts-title {
    font-size: clamp(0.65rem, calc(15.5vw - 33px), 1rem);
  }

  .training-session-bar .ts-title-long {
    display: none;
  }

  .training-session-bar .ts-title-short {
    display: inline;
  }

  .training-session-bar .ts-actions {
    flex: none;
  }

  .training-session-bar .ts-end-btn {
    padding: 0.35rem 0.75rem;
    font-size: 0.92rem;
  }

  body.session-active .dashboard-rail {
    display: none;
  }

  /* --- A lesson: its title in the side's row, beside the menu tab, and
     its side the king alone at the right (a lesson has no rating); its
     comment between the moves and the buttons, taking what the screen has
     left (it scrolls in it); one button line and no switch (the saved
     choice still applies), and no points. Its root is the screen's height,
     so the buttons stay at its foot. The board gives way, if it must, to
     two lines of comment. --- */
  .lesson-player-root:not([data-lesson-id^="puzzle-"]) {
    --ph-button: 36px;
    --ph-controls: calc(var(--ph-button) + 2 * var(--ph-pad) + 2px);
    --ph-rows: calc(
      var(--ph-row) + var(--ph-moves) + var(--ph-controls) + 2.7rem + 4 * var(--ph-gap)
    );
    grid-template-rows: auto auto auto minmax(0, 1fr) auto auto;
    height: calc(100dvh - var(--header-block-size));
  }

  .app-layout:has(.lesson-player-root:not([data-lesson-id^="puzzle-"])) .dashboard-rail {
    display: none;
  }

  .lesson-player-root:not([data-lesson-id^="puzzle-"]) .lesson-header-bar {
    grid-area: side;
    display: flex;
    align-items: center;
    min-width: 0;
    height: var(--ph-row);
    margin: 0 0 0 50px;
    padding: 0;
  }

  .lesson-player-root:not([data-lesson-id^="puzzle-"]) .lesson-title-display {
    margin: 0;
    font-size: 1rem;
    line-height: 1.25;
    text-align: left;
  }

  .lesson-player-root:not([data-lesson-id^="puzzle-"]) #comment-header {
    grid-area: elo;
    margin: 0 4px 0 0;
  }

  .lesson-player-root:not([data-lesson-id^="puzzle-"]) #comment-header .player-side,
  .lesson-player-root:not([data-lesson-id^="puzzle-"]) .board-side-stats,
  .lesson-player-root:not([data-lesson-id^="puzzle-"]) .auto-next-toggle {
    display: none;
  }

  /* An earlier position of a lesson is said in the side's row, in the
     king's place: there is no switch to lie over. */
  .lesson-player-root:not([data-lesson-id^="puzzle-"]) .board-review-badge {
    grid-area: elo;
    align-self: center;
    margin: 0 4px 0 0;
  }

  .lesson-player-root:not([data-lesson-id^="puzzle-"])[data-viewing-past="true"] #comment-header {
    visibility: hidden;
  }
}

/* A short phone (an iPhone SE's 568px, say): the switch beside the buttons,
   its words on two lines, so that the board keeps the screen's width. */
@media (max-width: 575.98px) and (max-height: 640px) {
  .app-layout {
    --ph-controls: calc(var(--ph-button) + 2 * var(--ph-pad) + 2px);
  }

  .move-controls {
    flex-wrap: nowrap;
    align-items: center;
  }

  .move-controls .auto-next-toggle {
    flex: 0 1 8.5rem;
    height: auto;
    font-size: 0.74rem;
    line-height: 1.15;
  }

  /* A long label ("Înapoi la ultima mutare") takes two lines. */
  .move-controls :is(.btn, #back-move-btn, #next-computer-move-btn) {
    white-space: normal;
    line-height: 1.1;
  }

  /* Over the switch alone: the button beside it takes the player back. */
  .lesson-player-root[data-lesson-id^="puzzle-"] .board-review-badge {
    justify-self: start;
    width: 8.5rem;
    height: var(--ph-button);
    margin: calc(var(--ph-gap) + var(--ph-pad)) 0 0 8px;
    padding: 0 0.5rem;
  }
}

/* The fragment's puzzle skip is the page's; a training session has its own, scored. */
body.session-active .puzzle-skip-btn {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .app-layout *,
  body:has(#main-content:not(.hidden)) .header-bar * {
    transition: none !important;
  }

  .rail-bonus {
    animation-name: rail-bonus-fade;
  }
}

@keyframes rail-bonus-fade {
  0%,
  85% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}
