/* Vektor: capa visual de la plataforma. Las plantillas no contienen estilos. */

:root {
  --ap-board-950: #0c211b;
  --ap-board-900: #123027;
  --ap-board-800: #193f34;
  --ap-board-700: #225345;
  --ap-board-600: #2e6958;
  --ap-board-500: #41806c;
  --ap-board-400: #4f7568;
  --ap-board-300: #9db7ae;
  --ap-board-200: #cddcd7;
  --ap-board-100: #e5efeb;
  --ap-board-50: #f3f7f4;
  --ap-flame-700: #965811;
  --ap-flame-600: #bd741c;
  --ap-flame-500: #dc9638;
  --ap-flame-400: #e8ad61;
  --ap-flame-100: #f9eedc;
  --ap-right-700: #087d61;
  --ap-right-600: #0b9b77;
  --ap-right-100: #ddf7ef;
  --ap-review-700: #b23352;
  --ap-review-600: #d44c69;
  --ap-review-100: #fde8ee;
  --ap-surface: #fffdf7;
  --ap-shadow-sm: 0 1px 2px rgba(12, 33, 27, 0.04), 0 6px 20px rgba(12, 33, 27, 0.06);
  --ap-shadow-md: 0 18px 45px rgba(12, 33, 27, 0.14);
  --ap-line: rgba(65, 128, 108, 0.16);
  --ap-line-strong: rgba(65, 128, 108, 0.3);
  --ap-radius: 1rem;
  --ap-radius-lg: 1.35rem;
  /* The header bar and its total height, derived rather than measured: the
     reading bar sticks directly below it and a magic number here would drift
     the day somebody changes the header's padding. */
  --ap-header-bar: 3.5rem;
  --ap-header-h: calc(var(--ap-header-bar) + 1px);
  /* The reading bar below it: its tap target, its padding and its border.
     Everything that has to clear both bars derives from these two. */
  --ap-reading-bar-h: calc(2.4rem + 1rem + 1px);
  --ap-stuck-h: calc(var(--ap-header-h) + var(--ap-reading-bar-h));
}

/* Smooth scrolling is a preference, not a default: for a reader with a
   vestibular disorder a page that slides under them is a page that makes them
   ill. The rest of this stylesheet already asks; this had forgotten to. */
@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}

body {
  min-height: 100vh;
  background:
    radial-gradient(circle at 5% 0%, rgba(65, 128, 108, 0.11), transparent 25rem),
    radial-gradient(circle at 95% 14%, rgba(220, 150, 56, 0.1), transparent 22rem),
    repeating-linear-gradient(0deg, rgba(18, 48, 39, 0.012) 0 1px, transparent 1px 5px),
    linear-gradient(rgba(65, 128, 108, 0.02) 1px, transparent 1px),
    linear-gradient(90deg, rgba(65, 128, 108, 0.02) 1px, transparent 1px),
    #f8f5ec;
  background-size: auto, auto, auto, 3rem 3rem, 3rem 3rem, auto;
  color: var(--ap-board-900);
  -webkit-font-smoothing: antialiased;
}

.app-shell {
  max-width: 68rem;
}

.page-content {
  position: relative;
  padding-top: 2rem;
  padding-bottom: 3rem;
}

/* Below Bootstrap's `sm`, where the bottom navigation is on screen, the page
   has to end above it. At 3rem the last eleven pixels of the practice page sat
   underneath the bar — measured, not guessed. The safe-area inset covers the
   phones with a home indicator on top of that. */
@media (max-width: 35.99em) {
  .page-content {
    padding-bottom: calc(3rem + 4rem + env(safe-area-inset-bottom, 0px));
  }
}

.site-header {
  background: rgba(255, 253, 247, 0.92);
  border-bottom: 1px solid var(--ap-line);
  box-shadow: 0 1px 12px rgba(12, 33, 27, 0.06);
  backdrop-filter: blur(14px);
}

/* Fixes the header's height so --ap-header-h is true and the reading bar
   lands exactly under it instead of one pixel into it. */
.site-header > .app-shell {
  min-height: var(--ap-header-bar);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.65rem;
  color: var(--ap-board-900);
  letter-spacing: -0.03em;
}

.brand:hover {
  color: var(--ap-board-700);
}

.brand-mark {
  display: grid;
  width: 2.2rem;
  height: 2.2rem;
  place-items: center;
  border-radius: 0.72rem;
  background: linear-gradient(145deg, var(--ap-board-500), var(--ap-board-800));
  box-shadow: 0 7px 16px rgba(34, 83, 69, 0.24);
  color: #fff;
  font-size: 1rem;
  transform: rotate(-3deg);
}

.brand-mark-logo {
  padding: 0;
  overflow: hidden;
  background: none;
  box-shadow: 0 7px 16px rgba(34, 83, 69, 0.22);
  transform: none;
}

.brand-mark-svg {
  display: block;
  width: 100%;
  height: 100%;
}

.brand-name,
.brand-wordmark {
  font-size: 1.18rem;
  letter-spacing: -0.03em;
}

.brand-name span,
.brand-accent {
  color: var(--ap-flame-600);
}

.brand-k {
  position: relative;
  display: inline-block;
  padding-top: 0.58em;
  color: var(--ap-board-900);
  font-weight: 800;
}

.brand-k-ornament {
  position: absolute;
  top: 0;
  left: 50%;
  width: 1em;
  height: 0.62em;
  pointer-events: none;
  background: no-repeat center / contain;
  /* Arrow on top, hat below — stacked with a clear gap. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 28' fill='none'%3E%3Cpath d='M6 5 H27 M23.5 2 L33 5 L23.5 8' stroke='%23dc9638' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M13 22 L20 15 L27 22' stroke='%23dc9638' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  transform: translateX(-50%);
}

.brand-auth {
  font-size: 1.35rem;
}

.brand-auth .brand-mark {
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 0.9rem;
}

.brand-auth .brand-wordmark {
  font-size: 1.55rem;
}

.desktop-nav {
  align-items: center;
  gap: 0.25rem;
  margin-left: 1.5rem;
}

.desktop-nav a {
  padding: 0.55rem 0.85rem;
  border-radius: 0.7rem;
  color: var(--ap-board-400);
  font-size: 0.875rem;
  font-weight: 650;
  text-decoration: none;
}

.desktop-nav a:hover,
.desktop-nav a.active {
  background: var(--ap-board-100);
  color: var(--ap-board-700);
}

.streak-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.45rem 0.65rem;
  border: 1px solid #ead3ad;
  border-radius: 999px;
  background: var(--ap-flame-100);
  color: var(--ap-flame-700);
  font-size: 0.78rem;
  font-weight: 750;
}

.profile-chip {
  display: grid;
  width: 2.25rem;
  height: 2.25rem;
  place-items: center;
  border: 2px solid #fff;
  border-radius: 50%;
  background: linear-gradient(145deg, var(--ap-board-500), var(--ap-board-700));
  box-shadow: 0 2px 8px rgba(12, 33, 27, 0.2);
  color: #fff;
  font-size: 0.82rem;
}

.profile-chip:hover {
  color: #fff;
  transform: translateY(-1px);
}

h1,
h2,
h3,
.h1,
.h2,
.h3 {
  letter-spacing: -0.025em;
}

.page-heading {
  position: relative;
  margin-bottom: 1.5rem;
  padding-left: 1rem;
}

.page-heading::before {
  position: absolute;
  top: 0.2rem;
  bottom: 0.15rem;
  left: 0;
  width: 4px;
  border-radius: 999px;
  background: linear-gradient(var(--ap-board-500), var(--ap-flame-500));
  content: "";
}

.eyebrow,
.section-title {
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.eyebrow {
  color: var(--ap-board-400);
}

.card-board .eyebrow {
  color: rgba(255, 255, 255, 0.68);
}

.section-title {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  margin-bottom: 0.75rem;
  color: var(--ap-board-400);
}

.section-title::after {
  width: min(5rem, 18vw);
  height: 1px;
  background: linear-gradient(90deg, var(--ap-line-strong), transparent);
  content: "";
}

.microcopy {
  font-size: 0.77rem;
}

/* Nine templates ask for this on the middle column of a row, and nothing
   defined it: Bootstrap has no `min-w-0`. A flex child defaults to
   `min-width: auto`, so it refuses to shrink below its longest word, and a
   subject with a long description pushed the whole page sideways on a phone.
   The body must never scroll horizontally, and it was. */
.min-w-0 {
  min-width: 0;
}

.tiny-label {
  font-size: 0.65rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.text-review {
  color: var(--ap-review-700) !important;
}

.breadcrumb {
  font-size: 0.78rem;
}

.breadcrumb a {
  text-decoration: none;
}

.page-content h1 > span[aria-hidden="true"] {
  display: inline-grid;
  width: 2.55rem;
  height: 2.55rem;
  place-items: center;
  border: 1px solid var(--ap-line-strong);
  border-radius: 0.85rem;
  background: linear-gradient(145deg, #f0f6f2, #e3eee9);
  box-shadow: 0 5px 14px rgba(34, 83, 69, 0.1);
}

.card {
  position: relative;
  border: 1px solid rgba(205, 220, 215, 0.96);
  border-radius: var(--ap-radius);
  background: rgba(255, 253, 247, 0.96);
  box-shadow: var(--ap-shadow-sm);
}

a.card {
  transition:
    transform 160ms ease,
    border-color 160ms ease,
    box-shadow 160ms ease,
    background-color 160ms ease;
}

/* Full-card hover: the old inset left stripe read as a border quirk, not as
   "this is tappable". Lift, wash and a whole-edge tint do that job. */
a.card:hover {
  border-color: color-mix(in srgb, var(--ap-board-500) 42%, var(--ap-line));
  background: color-mix(in srgb, var(--ap-board-50) 78%, #fffdf7);
  box-shadow: 0 12px 28px rgba(12, 33, 27, 0.1);
  transform: translateY(-2px);
}

@media (prefers-reduced-motion: reduce) {
  a.card:hover {
    transform: none;
  }
}

.card-board {
  position: relative;
  overflow: hidden;
  border-radius: var(--ap-radius-lg);
  background:
    radial-gradient(circle at 93% 10%, rgba(255, 255, 255, 0.16), transparent 9rem),
    linear-gradient(135deg, var(--ap-board-800), var(--ap-board-600));
  border: 1px solid rgba(255, 255, 255, 0.12);
  box-shadow: var(--ap-shadow-md);
}

.card-board::before {
  position: absolute;
  inset: 0;
  background-image: radial-gradient(rgba(255, 255, 255, 0.17) 1px, transparent 1px);
  background-position: 1rem 1rem;
  background-size: 1rem 1rem;
  clip-path: polygon(62% 0, 100% 0, 100% 100%, 82% 100%);
  content: "";
  opacity: 0.6;
  pointer-events: none;
}

.card-board::after {
  position: absolute;
  right: -2.5rem;
  bottom: -4rem;
  width: 13rem;
  height: 8rem;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 50%;
  content: "";
  pointer-events: none;
  transform: rotate(-18deg);
}

.card-board > * {
  position: relative;
  z-index: 1;
}

.callout-primary,
.callout-accent,
.callout-danger {
  border-left-width: 4px;
  border-left-style: solid;
}

.callout-primary {
  border-left-color: var(--ap-board-500);
}

.callout-accent {
  border-left-color: var(--ap-flame-500);
}

.callout-danger {
  border-left-color: var(--ap-review-600);
}

.btn {
  min-height: 2.85rem;
  padding-inline: 1rem;
  border-radius: 0.8rem;
  font-weight: 700;
  transition: transform 140ms ease, box-shadow 140ms ease, background-color 140ms ease;
  isolation: isolate;
}

.btn:hover {
  transform: translateY(-1px);
}

.btn-flame {
  border-color: #cb842b;
  background: linear-gradient(135deg, #e5a34e, #d68b2d);
  box-shadow: 0 8px 20px rgba(189, 116, 28, 0.24);
}

.btn-flame:hover {
  border-color: var(--ap-flame-600);
  background: linear-gradient(135deg, #ebb05f, #dc9638);
  box-shadow: 0 11px 24px rgba(189, 116, 28, 0.3);
}

.btn-outline-board {
  background: rgba(255, 255, 255, 0.8);
}

.badge {
  border: 1px solid rgba(34, 83, 69, 0.16);
  letter-spacing: 0.01em;
}

.stat {
  --stat-accent: var(--ap-board-500);
  position: relative;
  overflow: hidden;
  height: 100%;
  padding: 0.85rem 0.55rem;
  border-color: rgba(205, 220, 215, 0.96);
  box-shadow: var(--ap-shadow-sm);
}

.stat::before {
  position: absolute;
  top: 0;
  left: 22%;
  width: 56%;
  height: 3px;
  border-radius: 0 0 999px 999px;
  background: var(--stat-accent);
  content: "";
}

.row > [class*="col-"]:nth-child(2) .stat {
  --stat-accent: var(--ap-flame-500);
}

.row > [class*="col-"]:nth-child(3) .stat {
  --stat-accent: var(--ap-right-600);
}

.row > [class*="col-"]:nth-child(4) .stat {
  --stat-accent: #6d9487;
}

.stat-value {
  font-size: clamp(1.1rem, 3vw, 1.4rem);
}

.stat-value-risk {
  color: var(--ap-review-700);
}

.stat-value-accent {
  color: var(--ap-flame-700);
}

.text-review {
  color: var(--ap-review-700);
}

.card-icon,
.item-avatar,
.lesson-status,
.avatar-large {
  display: grid;
  flex: 0 0 auto;
  place-items: center;
}

.card-icon {
  position: relative;
  width: 3rem;
  height: 3rem;
  border: 1px solid #d1e0da;
  border-radius: 0.9rem;
  background: linear-gradient(145deg, #f0f6f2, #e3eee9);
  font-size: 1.3rem;
}

.card-icon::after {
  position: absolute;
  width: 1.05rem;
  height: 1.05rem;
  border: 1px solid rgba(65, 128, 108, 0.28);
  border-radius: 50%;
  content: "";
  transform: rotate(-30deg) scaleX(1.55);
}

.item-avatar {
  width: 2.65rem;
  height: 2.65rem;
  border-radius: 0.85rem;
  background: var(--ap-board-100);
  color: var(--ap-board-700);
}

.avatar-large {
  width: 4.5rem;
  height: 4.5rem;
  border: 3px solid rgba(255, 255, 255, 0.18);
  border-radius: 1.4rem;
  background: rgba(255, 255, 255, 0.12);
}

.lesson-status {
  width: 2.2rem;
  height: 2.2rem;
  border-radius: 50%;
  background: var(--ap-board-100);
  color: var(--ap-board-600);
  font-size: 0.8rem;
  font-weight: 800;
  box-shadow: 0 0 0 4px #fffdf7, 0 0 0 5px var(--ap-line);
}

.lesson-status-small {
  width: 1.8rem;
  height: 1.8rem;
  font-size: 0.72rem;
}

.lesson-status-complete {
  background: var(--ap-right-600);
  color: #fff;
}

.lesson-status-current {
  background: var(--ap-flame-500);
  color: var(--ap-board-950);
}

.lesson-status-locked {
  background: var(--ap-board-50);
  color: var(--ap-board-300);
}

/* ----------------------------------------------------------- lesson grid */
/* Hub of the week: square cards in a grid, not a stacked list. One glance
   shows the day number and where the student stopped. */
.lesson-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.85rem;
}

@media (min-width: 36em) {
  .lesson-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 1rem;
  }
}

@media (min-width: 56em) {
  .lesson-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 1.15rem;
  }
}

.lesson-grid-empty {
  grid-column: 1 / -1;
}

.lesson-card {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 11.5rem;
  border: 1px solid var(--ap-line);
  border-radius: 1.15rem;
  background: var(--ap-surface);
  box-shadow: 0 1px 2px rgba(12, 33, 27, 0.04);
  overflow: hidden;
  transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
}

.lesson-card:hover,
.lesson-card:focus-visible {
  border-color: color-mix(in srgb, var(--ap-board-400) 45%, var(--ap-line));
  box-shadow: 0 8px 22px rgba(12, 33, 27, 0.1);
  transform: translateY(-2px);
}

@media (prefers-reduced-motion: reduce) {
  .lesson-card {
    transition: none;
  }

  .lesson-card:hover,
  .lesson-card:focus-visible {
    transform: none;
  }
}

.lesson-card-art {
  display: grid;
  flex: 1 1 auto;
  place-items: center;
  min-height: 6.5rem;
  padding: 1.25rem 0.75rem 0.75rem;
  background:
    radial-gradient(circle at 30% 20%, color-mix(in srgb, var(--ap-board-100) 80%, transparent), transparent 55%),
    radial-gradient(circle at 80% 70%, color-mix(in srgb, var(--ap-flame-500) 12%, transparent), transparent 45%),
    linear-gradient(165deg, #fffdf8, var(--ap-board-50));
}

.lesson-card-complete .lesson-card-art {
  background:
    radial-gradient(circle at 50% 40%, color-mix(in srgb, var(--ap-right-600) 16%, transparent), transparent 60%),
    linear-gradient(165deg, #fffdf8, color-mix(in srgb, var(--ap-right-600) 8%, #fff));
}

.lesson-card-current .lesson-card-art {
  background:
    radial-gradient(circle at 50% 40%, color-mix(in srgb, var(--ap-flame-500) 22%, transparent), transparent 60%),
    linear-gradient(165deg, #fffdf8, color-mix(in srgb, var(--ap-flame-500) 10%, #fff));
}

.lesson-card-art .lesson-status {
  width: 3rem;
  height: 3rem;
  font-size: 1.05rem;
  box-shadow: 0 0 0 5px #fffdf7, 0 0 0 6px var(--ap-line);
}

.lesson-card-body {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  padding: 0.85rem 0.95rem 1rem;
  border-top: 1px solid var(--ap-line);
}

.lesson-card-title {
  display: -webkit-box;
  overflow: hidden;
  color: var(--ap-board-900);
  font-size: 0.92rem;
  font-weight: 700;
  line-height: 1.3;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
}

.lesson-card-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  color: var(--ap-board-400);
  font-size: 0.72rem;
  font-weight: 600;
}

/* Track and fill are tokens so a bar sitting on a coloured card can take that
   card's colour: a green bar on a violet card reads as a second, unrelated
   piece of information. */
.ap-progress {
  --ap-progress-track: var(--ap-board-100);
  --ap-progress-fill: var(--ap-board-500);
  display: block;
  width: 100%;
  height: 0.55rem;
  overflow: hidden;
  border: 1px solid rgba(65, 128, 108, 0.1);
  border-radius: 999px;
  background: var(--ap-progress-track);
  appearance: none;
}

.ap-progress::-webkit-progress-bar {
  border-radius: 999px;
  background: var(--ap-progress-track);
}

.ap-progress::-webkit-progress-value {
  border-radius: 999px;
  background: var(--ap-progress-fill);
  transition: width 180ms ease;
}

.ap-progress::-moz-progress-bar {
  border-radius: 999px;
  background: var(--ap-progress-fill);
}

/* --------------------------------------------------------------- the home */
/* Two columns from the tablet breakpoint up: the route is the page, the
   subjects and the objectives are reference. Below that everything stacks in
   the order a student reads it. */
.home-grid {
  display: grid;
  gap: 1.5rem;
}

.home-aside {
  display: grid;
  gap: 1.5rem;
  align-content: start;
}

.home-tile {
  gap: 0.85rem;
  padding: 0.95rem 1rem;
}

.home-tile .card-icon,
.home-tile .doubt-cta-icon {
  transition: transform 160ms ease, background-color 160ms ease;
}

.home-tile .home-tile-chevron {
  color: var(--ap-board-300);
  font-size: 1.05rem;
  line-height: 1;
  transition: color 160ms ease, transform 160ms ease;
}

@media (hover: hover) and (pointer: fine) {
  .home-tile:hover .card-icon,
  .home-tile:hover .doubt-cta-icon {
    transform: scale(1.06);
  }

  .home-tile:hover .home-tile-chevron {
    color: var(--ap-board-700);
    transform: translateX(2px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .home-tile .card-icon,
  .home-tile .doubt-cta-icon,
  .home-tile .home-tile-chevron {
    transition: none;
  }

  .home-tile:hover .card-icon,
  .home-tile:hover .doubt-cta-icon,
  .home-tile:hover .home-tile-chevron {
    transform: none;
  }
}

@media (min-width: 62em) {
  .home-grid {
    grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
    gap: 2.25rem;
    align-items: start;
  }
}

/* The week as seven boxes. A number says how long the streak is; the row says
   which days, and the one still empty is the one the student can act on. */
/* flex-direction is spelled out: .card ships column, and this row would
   silently inherit it. */
.week-strip {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 0.75rem;
  padding: 0.7rem 0.85rem;
}

.day-track {
  display: flex;
  gap: 0.3rem;
  margin-left: auto;
}

.day-cell {
  display: grid;
  width: 2rem;
  height: 2rem;
  place-items: center;
  border: 1px solid var(--ap-line-strong);
  border-radius: 0.6rem;
  background: #fff;
  color: var(--ap-board-300);
  font-size: 0.66rem;
  font-weight: 800;
}

.day-cell-done {
  border-color: var(--ap-board-600);
  background: var(--ap-board-600);
  color: #fff;
}

.day-cell-future {
  border-style: dashed;
  opacity: 0.6;
}

/* Today, still pending: amber and dashed, so an empty box never reads as done. */
.day-cell-today:not(.day-cell-done) {
  border: 2px dashed var(--ap-flame-500);
  background: var(--ap-flame-100);
  color: var(--ap-flame-700);
}

.day-cell-today.day-cell-done {
  box-shadow: 0 0 0 3px rgba(220, 150, 56, 0.35);
}

/* ------------------------------------------------------------- week route */
.route {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.route-node {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 0.85rem;
}

/* One segment per gap between two markers, rather than a single rail down the
   whole column: a line that runs past the last node reads as a road with no
   end, which is exactly what the route exists to deny. */
.route-node::before {
  position: absolute;
  top: 1.6rem;
  bottom: calc(-0.6rem - 2px);
  left: 1.1rem;
  width: 2px;
  background: var(--ap-board-200);
  content: "";
}

.route-node:last-child::before {
  display: none;
}

.route-marker {
  position: relative;
  z-index: 1;
  margin-top: 0.45rem;
}

.route-node-current .route-marker {
  margin-top: 1.05rem;
}

.route-node-locked {
  opacity: 0.62;
}

.route-body {
  min-width: 0;
  flex: 1 1 auto;
}

.route-line {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 0.75rem;
  padding: 0.7rem 0.85rem;
}

/* The three steps of a lesson, on the card of the day. This sequence is what
   the platform does — diagnostic first, evaluation last — and until now the
   student only met it after tapping into the lesson. */
.steps {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  margin: 1rem 0;
}

.step {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.5rem 0.65rem;
  border-radius: 0.7rem;
  background: rgba(255, 255, 255, 0.07);
  color: rgba(247, 245, 239, 0.85);
  font-size: 0.85rem;
}

.step-active {
  box-shadow: inset 0 0 0 1px rgba(247, 245, 239, 0.3);
  background: rgba(255, 255, 255, 0.14);
  color: #fff;
  font-weight: 600;
}

.step-marker {
  display: grid;
  width: 1.4rem;
  height: 1.4rem;
  flex: 0 0 auto;
  place-items: center;
  border: 1.5px solid rgba(247, 245, 239, 0.45);
  border-radius: 50%;
  font-size: 0.65rem;
  font-weight: 800;
}

/* A step that can no longer be taken: dimmed, never offered. */
.step-skipped {
  opacity: 0.55;
}

.step-done .step-marker {
  border-color: transparent;
  background: rgba(247, 245, 239, 0.92);
  color: var(--ap-board-800);
}

.step-active .step-marker {
  border-color: var(--ap-flame-500);
  background: var(--ap-flame-500);
  color: var(--ap-board-950);
}

.step-tag {
  color: rgba(247, 245, 239, 0.7);
  font-size: 0.72rem;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

/* --------------------------------------------------------- topic cards */
/* Six colours for six branches of physics, not twenty-one for twenty-one
   weeks. A colour per week is twenty-one things to learn; a colour per branch
   says something — four weeks in a row belong together. None of them is the
   green, coral or amber this app already spends on right, wrong and the one
   action.

   The colour is the card, not a stripe down its edge. A thick coloured left
   border is the cheapest way to claim a card has a colour without giving it
   one: at arm's length the list still reads as twenty-one white rectangles.

   Laid out as a grid of tiles: illustration on top, title and state below —
   the subject hub the student actually picks a topic from. */
.topic-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.85rem;
}

@media (min-width: 40em) {
  .topic-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 1rem;
  }
}

@media (min-width: 62em) {
  .topic-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 1.15rem;
  }
}

.topic-grid-empty {
  grid-column: 1 / -1;
}

.topic {
  --topic-ink: var(--ap-board-700);
  --topic-wash: var(--ap-board-100);
  --topic-image: url("../images/topic-cards/analisis-dimensional.36ccb7fd2932.webp");
  --topic-edge: color-mix(in srgb, var(--topic-ink) 22%, transparent);
  position: relative;
  isolation: isolate;
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
  align-items: stretch;
  gap: 0;
  padding: 0;
  border: 1px solid var(--topic-edge);
  border-radius: 1.15rem;
  background: var(--topic-wash);
  box-shadow: 0 1px 2px rgba(12, 33, 27, 0.04);
  overflow: hidden;
  transition: transform 0.15s ease, box-shadow 0.15s ease, background-color 0.15s ease;
}

.topic-art {
  position: relative;
  z-index: 0;
  flex: 0 0 auto;
  height: 8.25rem;
  background-color: var(--topic-wash);
  background-image:
    linear-gradient(180deg,
      color-mix(in srgb, var(--topic-wash) 12%, transparent) 0%,
      color-mix(in srgb, var(--topic-wash) 35%, transparent) 42%,
      color-mix(in srgb, var(--topic-wash) 92%, transparent) 100%),
    var(--topic-image);
  background-position: center, center;
  background-size: 100% 100%, cover;
  background-repeat: no-repeat;
  transition: filter 0.15s ease, transform 0.2s ease;
}

@media (prefers-reduced-motion: reduce) {
  .topic { transition: none; }
}

.topic:hover,
.topic:focus-visible {
  transform: translateY(-2px);
  box-shadow: 0 2px 4px rgba(12, 33, 27, 0.06), 0 10px 24px rgba(12, 33, 27, 0.08);
}

.topic:hover .topic-art,
.topic:focus-visible .topic-art {
  filter: saturate(1.05) contrast(1.02);
  transform: scale(1.02);
}

.family-general   { --topic-ink: #40566f; --topic-wash: #e7ecf2; }
.family-mechanics { --topic-ink: #285d4e; --topic-wash: #e2f0eb; }
.family-waves     { --topic-ink: #23596b; --topic-wash: #deeef4; }
.family-thermal   { --topic-ink: #8a4a2f; --topic-wash: #f7e8df; }
.family-electric  { --topic-ink: #5f4489; --topic-wash: #ece6f6; }
.family-optics    { --topic-ink: #6e591c; --topic-wash: #f4eeda; }
.family-modern    { --topic-ink: #7a3350; --topic-wash: #f8e5ec; }

/* Una ilustración creada para cada tema: no hay recortes compartidos ni
   imágenes genéricas repetidas entre tarjetas. */
.topic-analisis-dimensional { --topic-image: url("../images/topic-cards/analisis-dimensional.36ccb7fd2932.webp"); }
.topic-analisis-vectorial { --topic-image: url("../images/topic-cards/analisis-vectorial.1e456c9300c6.webp"); }
.topic-cinematica-una-dimension { --topic-image: url("../images/topic-cards/cinematica-una-dimension.caccdb74fc9c.webp"); }
.topic-cinematica-dos-dimensiones { --topic-image: url("../images/topic-cards/cinematica-dos-dimensiones.f0882ef847e2.webp"); }
.topic-graficas-del-movimiento { --topic-image: url("../images/topic-cards/graficas-del-movimiento.b359090cdccc.webp"); }
.topic-estatica { --topic-image: url("../images/topic-cards/estatica.be842ed34fa2.webp"); }
.topic-dinamica { --topic-image: url("../images/topic-cards/dinamica.8b196cebb283.webp"); }
.topic-trabajo-energia-potencia { --topic-image: url("../images/topic-cards/trabajo-energia-potencia.443e8398ddf0.webp"); }
.topic-impulso-cantidad-movimiento { --topic-image: url("../images/topic-cards/impulso-cantidad-movimiento.b50dc5a4e13e.webp"); }
.topic-gravitacion-universal { --topic-image: url("../images/topic-cards/gravitacion-universal.48ba3a09227b.webp"); }
.topic-oscilaciones-mas { --topic-image: url("../images/topic-cards/oscilaciones-mas.c2ec98f80b6e.webp"); }
.topic-ondas-mecanicas { --topic-image: url("../images/topic-cards/ondas-mecanicas.7fc51c8be466.webp"); }
.topic-estatica-fluidos { --topic-image: url("../images/topic-cards/estatica-fluidos.c3f718863a55.webp"); }
.topic-fenomenos-termicos { --topic-image: url("../images/topic-cards/fenomenos-termicos.1b0e22313301.webp"); }
.topic-termodinamica { --topic-image: url("../images/topic-cards/termodinamica.8b69de18ce9a.webp"); }
.topic-electrostatica { --topic-image: url("../images/topic-cards/electrostatica.c35df2454352.webp"); }
.topic-electrodinamica-capacitores { --topic-image: url("../images/topic-cards/electrodinamica-capacitores.f488881a2a31.webp"); }
.topic-electromagnetismo { --topic-image: url("../images/topic-cards/electromagnetismo.946daae20a61.webp"); }
.topic-ondas-electromagneticas { --topic-image: url("../images/topic-cards/ondas-electromagneticas.267e7f3ed4fd.webp"); }
.topic-optica-geometrica { --topic-image: url("../images/topic-cards/optica-geometrica.c13e73e2a30c.webp"); }
.topic-fisica-moderna { --topic-image: url("../images/topic-cards/fisica-moderna.4c72b1d3760b.webp"); }

/* The cover: the week's drawing, reversed out of a solid block of the branch
   colour. No image file and no extra request — it is a <use> of a sprite the
   page already carries. Scoped under .topic so the gate interstitial can reuse
   the same class without inheriting the tile's absolute placement. */
.topic > .topic-cover {
  position: absolute;
  z-index: 1;
  top: 6.35rem;
  left: 0.85rem;
  display: grid;
  width: 3.15rem;
  height: 3.15rem;
  flex: 0 0 auto;
  place-items: center;
  border: 2px solid color-mix(in srgb, var(--topic-wash) 70%, #fff);
  border-radius: 0.85rem;
  background: var(--topic-ink, var(--ap-board-700));
  color: var(--topic-wash, var(--ap-board-100));
  box-shadow: 0 4px 12px rgba(12, 33, 27, 0.12);
}

.topic-cover {
  display: grid;
  place-items: center;
  border-radius: 0.85rem;
  /* Fallbacks so the cover still works outside a .topic — the gate uses it. */
  background: var(--topic-ink, var(--ap-board-700));
  color: var(--topic-wash, var(--ap-board-100));
}

.topic-glyph {
  width: 1.75rem;
  height: 1.75rem;
}

.topic-body {
  position: relative;
  z-index: 1;
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  min-width: 0;
  padding: 1.85rem 0.95rem 1rem;
}

/* ----------------------------------------------------------- tema visual */
.theme-ready body,
.theme-ready .site-header,
.theme-ready .card,
.theme-ready .bottom-nav,
.theme-ready .form-control,
.theme-ready .form-select {
  transition: background-color 180ms ease, color 180ms ease, border-color 180ms ease;
}

.theme-toggle {
  display: inline-grid;
  width: 2.5rem;
  height: 2.5rem;
  flex: 0 0 auto;
  place-items: center;
  padding: 0;
  border: 1px solid var(--ap-line-strong);
  border-radius: 0.78rem;
  background: color-mix(in srgb, var(--ap-surface) 88%, transparent);
  color: var(--ap-board-700);
  cursor: pointer;
}

.theme-toggle:hover {
  background: var(--ap-board-100);
  color: var(--ap-board-900);
}

.theme-icon {
  width: 1.15rem;
  height: 1.15rem;
  fill: none;
  stroke: currentColor;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: 1.8;
}

.theme-icon-moon { fill: currentColor; stroke: none; }
.theme-icon-sun { display: none; }

[data-bs-theme="dark"] {
  --ap-surface: #10241f;
  --ap-line: rgba(157, 192, 179, 0.18);
  --ap-line-strong: rgba(157, 192, 179, 0.34);
  --ap-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.22), 0 8px 24px rgba(0, 0, 0, 0.22);
  --ap-shadow-md: 0 20px 50px rgba(0, 0, 0, 0.34);
  --bs-body-bg: #081612;
  --bs-body-color: #edf6f1;
  --bs-secondary-color: #a8c6bc;
  --bs-border-color: #294a40;
  --bs-link-color: #a9d7c7;
  --bs-link-hover-color: #d0eee4;
  --bs-tertiary-bg: #16302a;
  --bs-secondary-bg: #10241f;
}

[data-bs-theme="dark"] body {
  background:
    radial-gradient(circle at 5% 0%, rgba(65, 128, 108, 0.2), transparent 25rem),
    radial-gradient(circle at 95% 14%, rgba(220, 150, 56, 0.09), transparent 22rem),
    repeating-linear-gradient(0deg, rgba(237, 246, 241, 0.012) 0 1px, transparent 1px 5px),
    linear-gradient(rgba(157, 183, 174, 0.018) 1px, transparent 1px),
    linear-gradient(90deg, rgba(157, 183, 174, 0.018) 1px, transparent 1px),
    #081612;
  background-size: auto, auto, auto, 3rem 3rem, 3rem 3rem, auto;
  color: #edf6f1;
}

[data-bs-theme="dark"] .site-header {
  background: rgba(11, 26, 22, 0.92);
  box-shadow: 0 1px 16px rgba(0, 0, 0, 0.3);
}

[data-bs-theme="dark"] .brand-k {
  color: #edf6f1;
}

[data-bs-theme="dark"] .brand,
[data-bs-theme="dark"] .brand-wordmark,
[data-bs-theme="dark"] .topic-title,
[data-bs-theme="dark"] .text-board,
[data-bs-theme="dark"] .stat-value {
  color: #edf6f1 !important;
}

[data-bs-theme="dark"] .text-board-muted,
[data-bs-theme="dark"] .eyebrow,
[data-bs-theme="dark"] .section-title,
[data-bs-theme="dark"] .desktop-nav a,
[data-bs-theme="dark"] .form-text {
  color: #a8c6bc !important;
}

/* .bg-board-soft stayed a light mint in dark mode, so .text-board's
   near-white override sat on a light background instead of a dark one --
   readable in light mode, washed out to near-invisible in dark mode. */
[data-bs-theme="dark"] .bg-board-soft {
  background-color: var(--ap-board-800) !important;
}

[data-bs-theme="dark"] .desktop-nav a:hover,
[data-bs-theme="dark"] .desktop-nav a.active,
[data-bs-theme="dark"] .bottom-nav a.active .nav-icon {
  background: #1b392f;
  color: #edf6f1;
}

[data-bs-theme="dark"] .card,
[data-bs-theme="dark"] .stat,
[data-bs-theme="dark"] .bottom-nav {
  border-color: #294a40;
  background-color: rgba(16, 36, 31, 0.97);
  color: #edf6f1;
}

[data-bs-theme="dark"] a.card:hover {
  border-color: #578778;
  background-color: #16362d;
  box-shadow: 0 14px 32px rgba(0, 0, 0, 0.28);
}

[data-bs-theme="dark"] .home-tile:hover .home-tile-chevron {
  color: #d7ebe4;
}

[data-bs-theme="dark"] .btn-outline-board {
  --bs-btn-color: #d7ebe4;
  --bs-btn-bg: #10241f;
  --bs-btn-border-color: #396256;
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: #1b392f;
  --bs-btn-hover-border-color: #578778;
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: #23463c;
  background: #10241f;
}

[data-bs-theme="dark"] .btn-outline-board:hover,
[data-bs-theme="dark"] .btn-outline-board:focus-visible {
  background: #1b392f;
}

[data-bs-theme="dark"] .form-control,
[data-bs-theme="dark"] .form-select {
  border-color: #396256;
  background-color: #0c1d18;
  color: #edf6f1;
}

[data-bs-theme="dark"] .form-control::placeholder { color: #77988d; }
[data-bs-theme="dark"] .form-control:focus,
[data-bs-theme="dark"] .form-select:focus {
  border-color: #74aa98;
  background-color: #10241f;
  color: #fff;
}

[data-bs-theme="dark"] .page-content h1 > span[aria-hidden="true"] {
  background: linear-gradient(145deg, #16362d, #10241f);
  box-shadow: 0 5px 18px rgba(0, 0, 0, 0.28);
}

[data-bs-theme="dark"] .theme-icon-moon { display: none; }
[data-bs-theme="dark"] .theme-icon-sun { display: block; }
[data-bs-theme="dark"] .theme-toggle {
  background: #16302a;
  color: #f6c872;
}

/* La fotografía sigue ocupando toda la tarjeta. En oscuro se cambia únicamente
   la capa de lectura, no el recorte ni la posición de la ilustración. */
[data-bs-theme="dark"] .topic {
  --topic-ink: #d7ebe4;
  --topic-wash: #10241f;
  --topic-edge: rgba(153, 190, 177, 0.32);
  background: #10241f;
}

[data-bs-theme="dark"] .topic-art {
  background-image:
    linear-gradient(180deg,
      rgba(8, 22, 18, 0.18) 0%,
      rgba(8, 22, 18, 0.55) 48%,
      rgba(8, 22, 18, 0.94) 100%),
    var(--topic-image);
  filter: brightness(0.82) saturate(0.9);
}

[data-bs-theme="dark"] .topic:hover .topic-art,
[data-bs-theme="dark"] .topic:focus-visible .topic-art {
  filter: brightness(0.9) saturate(1);
}

[data-bs-theme="dark"] .topic-cover {
  border: 1px solid rgba(215, 235, 228, 0.24);
  background: rgba(16, 36, 31, 0.82);
  color: #edf6f1;
  backdrop-filter: blur(8px);
}

[data-bs-theme="dark"] .topic-summary,
[data-bs-theme="dark"] .topic-branch,
[data-bs-theme="dark"] .topic-week,
[data-bs-theme="dark"] .topic-action,
[data-bs-theme="dark"] .topic-count {
  color: #c7ded6;
}

[data-bs-theme="dark"] .topic-status {
  background: rgba(8, 22, 18, 0.72);
  color: #d7ebe4;
}

[data-bs-theme="dark"] .topic-status-current { color: #f6c872; }
[data-bs-theme="dark"] .topic-status-done { color: #74dab6; }

[data-bs-theme="dark"] .choice,
[data-bs-theme="dark"] .list-group-item,
[data-bs-theme="dark"] .accordion-item {
  border-color: #294a40;
  background-color: #10241f;
  color: #edf6f1;
}

[data-bs-theme="dark"] .alert-secondary {
  border-color: #396256;
  background: #16302a;
  color: #d7ebe4;
}

/* El HTML de las lecciones trae colores semánticos pensados para papel claro.
   En el tema oscuro se redefine toda la escala de lectura para evitar texto
   verde oscuro sobre el fondo pizarra. */
[data-bs-theme="dark"] .lesson-body {
  color: #cfe2db;
}

[data-bs-theme="dark"] .lesson-body h2,
[data-bs-theme="dark"] .lesson-body strong {
  color: #f1f8f5;
}

[data-bs-theme="dark"] .lesson-body h3,
[data-bs-theme="dark"] .lesson-body a {
  color: #8fd5bd;
}

[data-bs-theme="dark"] .lesson-body code {
  background-color: #18372f;
  color: #e5f2ed;
}

[data-bs-theme="dark"] .lesson-body pre {
  border: 1px solid #31584c;
  background-color: #06120f;
  color: #edf6f1;
}

[data-bs-theme="dark"] .lesson-body blockquote {
  border-left-color: #6ea997;
  background-color: #102a23;
  color: #d7e9e3;
}

[data-bs-theme="dark"] .lesson-body th,
[data-bs-theme="dark"] .lesson-body td {
  border-color: #31584c;
}

[data-bs-theme="dark"] .lesson-body th {
  background-color: #17332b;
  color: #f1f8f5;
}

[data-bs-theme="dark"] .lesson-body details,
[data-bs-theme="dark"] .solution-box {
  border-color: #31584c;
  background-color: #10241f;
  color: #cfe2db;
}

[data-bs-theme="dark"] .lesson-body details > summary,
[data-bs-theme="dark"] .solution-box > summary {
  color: #b9d8cd;
}

[data-bs-theme="dark"] .lesson-body details > summary:hover,
[data-bs-theme="dark"] .solution-box > summary:hover {
  background-color: #18372f;
}

[data-bs-theme="dark"] .lesson-index-list a {
  border-color: #3b6559;
  color: #b9d8cd;
}

[data-bs-theme="dark"] .lesson-index-list a:hover {
  border-color: #73aa98;
  background: #18372f;
  color: #f1f8f5;
}

[data-bs-theme="dark"] .lesson-card {
  border-color: #294a40;
  background: rgba(16, 36, 31, 0.97);
}

[data-bs-theme="dark"] .lesson-card:hover,
[data-bs-theme="dark"] .lesson-card:focus-visible {
  border-color: #578778;
}

[data-bs-theme="dark"] .lesson-card-art {
  background:
    radial-gradient(circle at 30% 20%, rgba(65, 128, 108, 0.18), transparent 55%),
    linear-gradient(165deg, #16362d, #10241f);
}

[data-bs-theme="dark"] .lesson-card-complete .lesson-card-art {
  background:
    radial-gradient(circle at 50% 40%, rgba(11, 155, 119, 0.22), transparent 60%),
    linear-gradient(165deg, #16362d, #10241f);
}

[data-bs-theme="dark"] .lesson-card-current .lesson-card-art {
  background:
    radial-gradient(circle at 50% 40%, rgba(220, 150, 56, 0.24), transparent 60%),
    linear-gradient(165deg, #16362d, #10241f);
}

[data-bs-theme="dark"] .lesson-card-art .lesson-status {
  box-shadow: 0 0 0 5px #10241f, 0 0 0 6px #396256;
}

[data-bs-theme="dark"] .lesson-card-body {
  border-top-color: #294a40;
}

[data-bs-theme="dark"] .lesson-card-title {
  color: #edf6f1;
}

[data-bs-theme="dark"] .lesson-card-meta {
  color: #8fb3a6;
}

[data-bs-theme="dark"] .lesson-reading-title {
  color: #edf6f1;
}

[data-bs-theme="dark"] .lesson-objectives {
  border-color: #294a40;
  background: #142b25;
}

[data-bs-theme="dark"] .lesson-index-inline a {
  border-color: #3b6559;
  color: #b9d8cd;
}

[data-bs-theme="dark"] .lesson-index-inline a:hover,
[data-bs-theme="dark"] .lesson-index-inline a:focus-visible {
  border-color: #73aa98;
  background: #18372f;
  color: #f1f8f5;
}

/* Los enunciados también usan .lesson-body. Sus tarjetas deben pasar a una
   superficie oscura para que la nueva escala tipográfica mantenga contraste. */
[data-bs-theme="dark"] .level-easy {
  --level-ink: #84bbaa;
  --level-wash: #10241f;
}

[data-bs-theme="dark"] .level-medium {
  --level-ink: #a4c9bd;
  --level-wash: #142b25;
}

[data-bs-theme="dark"] .level-hard {
  --level-ink: #c4d9d2;
  --level-wash: #19312a;
}

[data-bs-theme="dark"] .exercise {
  color: #cfe2db;
}

[data-bs-theme="dark"] .choice:has(input:checked) {
  border-color: #629b89;
  background-color: #18372f;
}

[data-bs-theme="dark"] .choice-correct,
[data-bs-theme="dark"] .choice-correct:hover,
[data-bs-theme="dark"] .alternatives:has(input:checked) .is-right {
  border-color: #27a780;
  background: #12382d;
}

[data-bs-theme="dark"] .choice-wrong,
[data-bs-theme="dark"] .choice-wrong:hover,
[data-bs-theme="dark"] .choice:has(input:checked):not(.is-right) {
  border-color: #d2637c;
  background: #3c2029;
}

/* El hover solo se activa donde existe un puntero preciso. Así se percibe con
   claridad en escritorio y no queda pegado después de tocar una opción en el
   celular. Se excluyen respuestas ya marcadas para respetar su significado. */
@media (hover: hover) and (pointer: fine) {
  [data-bs-theme="dark"] .question-grid > li.card,
  [data-bs-theme="dark"] .exercise {
    transition: border-color 150ms ease, background-color 150ms ease,
      box-shadow 150ms ease;
  }

  [data-bs-theme="dark"] .question-grid > li.card:hover,
  [data-bs-theme="dark"] .exercise:hover {
    border-color: #568a7a;
    box-shadow: 0 14px 34px rgba(0, 0, 0, 0.3), 0 0 0 1px rgba(111, 178, 156, 0.16);
  }

  [data-bs-theme="dark"] .alternatives .choice:not(:has(input:checked)):hover,
  [data-bs-theme="dark"] .choice:not(.choice-static):not(:has(input:checked)):hover {
    border-color: #79b6a3;
    background-color: #1b3d33;
    box-shadow: 0 7px 18px rgba(0, 0, 0, 0.24), inset 3px 0 #79b6a3;
    color: #f1f8f5;
    transform: translateY(-1px);
  }

  [data-bs-theme="dark"] .alternatives .choice:not(:has(input:checked)):hover .choice-marker,
  [data-bs-theme="dark"] .choice:not(.choice-static):not(:has(input:checked)):hover .choice-marker {
    border-color: #8bc8b5;
    background: #254b40;
    color: #f1f8f5;
  }
}

.topic-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
}

.topic-branch {
  color: var(--topic-ink);
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* On a tinted card the week number cannot be a tinted pill of its own, so it
   is an outline in the branch colour. */
.topic-week {
  padding: 0.1rem 0.5rem;
  border: 1px solid var(--topic-edge);
  border-radius: 999px;
  color: var(--topic-ink);
  font-size: 0.68rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* Finished weeks: solid paper behind the green so it reads the same on all
   seven washes, and a tick so the state is never colour alone. */
.topic-done {
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  background: var(--ap-surface);
  color: var(--ap-right-700);
  font-size: 0.68rem;
  font-weight: 700;
}

.topic-title {
  margin: 0.35rem 0 0;
  color: var(--ap-board-900);
  font-size: 1rem;
  font-weight: 650;
  line-height: 1.3;
}

.topic-summary {
  display: -webkit-box;
  overflow: hidden;
  margin: 0.35rem 0 0;
  color: color-mix(in srgb, var(--topic-ink) 65%, var(--ap-board-900));
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}

.topic-footer {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-top: auto;
  padding-top: 0.85rem;
}

.topic-status {
  display: inline-flex;
  align-items: center;
  padding: 0.2rem 0.55rem;
  border: 1px solid var(--topic-edge);
  border-radius: 999px;
  background: color-mix(in srgb, var(--ap-surface) 82%, transparent);
  color: var(--topic-ink);
  font-size: 0.7rem;
  font-weight: 750;
}

.topic-status-done {
  border-color: color-mix(in srgb, var(--ap-right-600) 30%, transparent);
  color: var(--ap-right-700);
}

.topic-status-current {
  border-color: color-mix(in srgb, var(--ap-flame-500) 40%, transparent);
  color: var(--ap-flame-700);
}

.topic-action {
  margin-left: auto;
  color: var(--topic-ink);
  font-size: 0.78rem;
  font-weight: 800;
}

/* The bar inherits the branch too, or a green bar on a violet card would read
   as a second, unrelated piece of information. */
.topic .ap-progress {
  --ap-progress-track: color-mix(in srgb, var(--topic-ink) 14%, #fff);
  --ap-progress-fill: var(--topic-ink);
}

.topic-count {
  color: var(--topic-ink);
}

/* The interstitial shown when a week is opened out of order. It wears the
   branch colour of the week being asked for, so it reads as that topic
   answering rather than as an error page. */
.gate {
  max-width: 32rem;
  margin: 0 auto;
  text-align: center;
}

.gate-cover {
  margin: 0 auto 1rem;
  width: 4rem;
  height: 4rem;
}

.gate-cover .topic-glyph {
  width: 2.3rem;
  height: 2.3rem;
}

/* ------------------------------------------------------ reading navigation */
/* A lesson is nine minutes of scrolling. A breadcrumb that only exists at the
   very top is a way back that is not there when the student wants it, which is
   why this sticks under the header instead. */
.reading-bar {
  position: sticky;
  top: var(--ap-header-h);
  z-index: 3;
  display: flex;
  /* .reading-bar is not on a .card, but the same trap applies to any row: name
     the direction rather than inherit it. */
  flex-direction: row;
  align-items: center;
  gap: 0.5rem;
  /* Bleeds into the container's gutter so nothing scrolls past its edges. */
  margin: -0.5rem calc(var(--bs-gutter-x, 1.5rem) * -0.5) 1rem;
  padding: 0.5rem calc(var(--bs-gutter-x, 1.5rem) * 0.5);
  border-bottom: 1px solid var(--ap-line);
  /* Opaque enough to actually hide what slides under it: at 88 % the aside card
     and the problem text read straight through the bar. */
  background: color-mix(in srgb, var(--ap-surface) 97%, transparent);
  backdrop-filter: blur(12px);
  font-size: 0.8rem;
}

.reading-bar-back {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  /* A tap target, not a word: 44px is the smallest thing a thumb hits every
     time, and this is the control the whole bar exists for. */
  min-height: 2.4rem;
  padding-right: 0.5rem;
  color: var(--ap-board-700);
  font-weight: 700;
  text-decoration: none;
}

.reading-bar-back span[aria-hidden] {
  font-size: 1.25rem;
  line-height: 1;
}

.reading-bar-back:hover,
.reading-bar-subject:hover {
  color: var(--ap-board-900);
  text-decoration: underline;
}

.reading-bar-subject {
  margin-left: auto;
  color: var(--ap-board-400);
  text-decoration: none;
}

/* Leaving a quiz costs the answers, so the bar says so instead of letting the
   student find out. Hidden on a narrow screen, where the label alone has to
   carry it — a warning that wraps to three lines gets read by nobody. */
.reading-bar-warning {
  margin-left: auto;
  color: var(--ap-board-400);
  font-size: 0.72rem;
}

@media (max-width: 30em) {
  .reading-bar-warning {
    display: none;
  }
}

/* Two sticky bars deep, so an anchor has to clear both or it lands underneath
   the thing that was supposed to guide it. */
.exercise,
.lesson-body :is(h2, h3) {
  scroll-margin-top: calc(var(--ap-stuck-h) + 0.75rem);
}

/* The end of a lesson: prev, back to the week, next. It used to end in
   nothing, which is precisely where a student asks what comes next. */
.lesson-nav {
  display: grid;
  gap: 0.75rem;
  margin-top: 3rem;
}

@media (min-width: 48em) {
  .lesson-nav {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    align-items: stretch;
  }

  /* With no previous lesson the row would start at the middle column. */
  .lesson-nav > :first-child.lesson-nav-up {
    grid-column: 2;
  }
}

.lesson-nav-link {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.85rem 1rem;
  text-decoration: none;
}

.lesson-nav-label {
  color: var(--ap-board-400);
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}

.lesson-nav-title {
  color: var(--ap-board-900);
  font-weight: 650;
  line-height: 1.3;
}

.lesson-nav-next {
  text-align: right;
}

.lesson-nav-up {
  align-items: center;
  text-align: center;
}

@media (max-width: 47.99em) {
  /* Stacked, the right-aligned "next" reads as a mistake. */
  .lesson-nav-next,
  .lesson-nav-up {
    align-items: flex-start;
    text-align: left;
  }
}

/* ---------------------------------------------------------- lesson layout */
/* Theory owns the page: one full-width reading column, actions after the
   content. The old aside stole focus on desktop; the student came to read. */
.lesson-reading {
  max-width: 56rem;
}

.lesson-reading-header {
  margin-bottom: 1.75rem;
  text-align: center;
}

.lesson-reading-title {
  margin: 0;
  font-size: clamp(1.45rem, 2.4vw, 1.85rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.25;
  color: var(--ap-board-950);
}

.lesson-objectives {
  margin-bottom: 1.5rem;
  padding: 1rem 1.15rem;
  border: 1px solid var(--ap-line);
  border-radius: var(--ap-radius, 1rem);
  background: color-mix(in srgb, var(--ap-board-100) 55%, var(--ap-surface));
}

.lesson-body-wide {
  font-size: clamp(1.0625rem, 0.4vw + 1rem, 1.125rem);
}

.lesson-index-inline {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}

.lesson-index-inline a {
  display: grid;
  min-width: 2rem;
  height: 2rem;
  place-items: center;
  border: 1px solid var(--ap-line-strong);
  border-radius: 0.55rem;
  color: var(--ap-board-700);
  font-size: 0.78rem;
  font-weight: 700;
  text-decoration: none;
}

.lesson-index-inline a:hover,
.lesson-index-inline a:focus-visible {
  border-color: var(--ap-board-400);
  background: var(--ap-board-50);
  color: var(--ap-board-900);
}

.lesson-actions {
  display: grid;
  gap: 1rem;
  margin-top: 2.5rem;
}

.lesson-actions-quiz {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.lesson-actions-quiz .btn {
  flex: 0 0 auto;
}

/* Kept for any leftover markup; reading no longer uses a two-column shell. */
.lesson-layout {
  display: grid;
  gap: 1.5rem;
}

.lesson-main {
  min-width: 0;
}

.lesson-aside {
  display: grid;
  gap: 1rem;
  align-content: start;
}

/* A link that leaves the site opens in its own tab, so it says so: a student
   who taps it and finds themselves somewhere else should have been told. */
.lesson-body a[target="_blank"]::after {
  content: " ↗";
  font-size: 0.85em;
}

.lesson-index-list {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0.5rem;
}

.lesson-index-list a {
  display: flex;
  align-items: center;
  min-height: 2.75rem;
  gap: 0.55rem;
  padding: 0.55rem 0.75rem;
  border: 1px solid var(--ap-line-strong);
  border-radius: 0.7rem;
  color: var(--ap-board-700);
  font-size: 0.84rem;
  font-weight: 700;
  text-decoration: none;
  font-variant-numeric: tabular-nums;
  transition: border-color 150ms ease, background-color 150ms ease,
    color 150ms ease, transform 150ms ease, box-shadow 150ms ease;
}

.lesson-index-number {
  margin-left: auto;
  font-weight: 800;
}

.lesson-index-arrow {
  color: var(--ap-board-400);
}

.lesson-index-list a:hover {
  border-color: var(--ap-board-500);
  background: var(--ap-board-50);
}

/* En el celular, las claves forman una lista táctil. En escritorio recuperan
   la retícula compacta de una hoja de respuestas de admisión: filas regulares
   y cinco posiciones fáciles de explorar de izquierda a derecha. */
@media (min-width: 62em) {
  .lesson-index-list {
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: 0.45rem;
  }

  .lesson-index-list a {
    display: grid;
    min-width: 0;
    min-height: 2.55rem;
    padding: 0.4rem;
    place-items: center;
    border-radius: 0.6rem;
  }

  .lesson-index-label,
  .lesson-index-arrow {
    display: none;
  }

  .lesson-index-number {
    margin-left: 0;
  }
}

@media (hover: hover) and (pointer: fine) {
  .lesson-index-list a:hover {
    transform: translateY(-1px);
    box-shadow: 0 5px 12px rgba(12, 33, 27, 0.08);
  }
}

/* ------------------------------------------------------------- exercises */
.exercise-list {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0.85rem;
}

/* Cada enunciado conserva el ancho de lectura de una hoja de examen. La
   cuadrícula se reserva para las alternativas, que es donde un postulante
   necesita comparar claves rápidamente. */
.question-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0.85rem;
}

.question-grid > li {
  min-width: 0;
  margin-bottom: 0 !important;
}

.exercise {
  padding: 1rem;
  border: 1px solid var(--ap-line);
  border-radius: var(--ap-radius);
  background: rgba(255, 253, 247, 0.96);
  box-shadow: var(--ap-shadow-sm);
}

/* Difficulty is a ramp, not three categories, so it is one hue in three
   weights. Green/amber/coral are already spoken for: in this app they mean
   right, the one action, and wrong — and a hard problem is none of those.
   The tokens hang off the level class itself, so a card and a filter chip
   pick up the same weight. */
.level-easy,
.level-medium,
.level-hard {
  --level-ink: var(--ap-board-500);
  --level-wash: var(--ap-board-100);
}

.level-easy {
  --level-ink: var(--ap-board-400);
  --level-wash: var(--ap-board-50);
}

.level-medium {
  --level-ink: var(--ap-board-600);
  --level-wash: var(--ap-board-100);
}

.level-hard {
  --level-ink: var(--ap-board-800);
  --level-wash: #d7e5df;
}

/* The level colours the whole card, not a stripe down its edge: a 3px rule is
   a claim that the card has a colour rather than a card that has one. The wash
   steps are close together on purpose — difficulty should be readable at a
   glance and still let eight cards in a column look like one list. */
.exercise {
  border-color: color-mix(in srgb, var(--level-ink) 28%, transparent);
  background: var(--level-wash);
}

/* Provenance is not difficulty, so it is not on the same ramp: amber, the
   colour this app already uses for "esto importa", and it reads before the
   level because it is the first thing a student wants to know. */
.exam-chip {
  display: inline-flex;
  align-items: center;
  margin-left: auto;
  padding: 0.2rem 0.55rem;
  border: 1px solid rgba(220, 150, 56, 0.35);
  border-radius: 999px;
  background: var(--ap-flame-100);
  color: var(--ap-flame-700);
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.04em;
}

/* When both are present the level stops pushing itself right. */
.exam-chip + .level-chip {
  margin-left: 0.35rem;
}

.level-chip {
  display: inline-flex;
  align-items: baseline;
  gap: 0.4rem;
  margin-left: auto;
  padding: 0.2rem 0.5rem;
  border-radius: 999px;
  background: var(--level-wash);
  color: var(--level-ink);
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.04em;
}

.level-time {
  font-weight: 650;
  letter-spacing: 0;
  opacity: 0.85;
  font-variant-numeric: tabular-nums;
}

.exercise-number {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  margin-bottom: 0.5rem;
  color: var(--ap-board-500);
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.exercise-source {
  margin-left: auto;
  color: var(--ap-board-400);
  font-size: 0.7rem;
  font-weight: 650;
  letter-spacing: 0;
  text-transform: none;
}

/* Figures are drawn on a light ground and sized by their own aspect ratio. */
.exercise-figure {
  display: block;
  width: 100%;
  max-width: 22rem;
  height: auto;
  margin: 0.9rem auto;
}

.exercise .solution-box {
  margin-top: 0.9rem;
}

.exercise .lesson-body {
  font-size: 1rem;
}

/* ------------------------------------------------------- figure studio */
.studio {
  display: grid;
  gap: 1rem;
}

@media (min-width: 62em) {
  .studio {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: start;
  }

  /* The drawing follows the editing: on a long spec the preview stays put. */
  .studio-canvas {
    position: sticky;
    top: 5rem;
  }

  /* The lesson editor inverts this: the form is short, the rendered theory
     can run for pages, so the form is what should stay put while the long
     preview scrolls -- not the other way around. */
  .studio-form-sticky {
    position: sticky;
    top: 5rem;
  }
}

.studio-figure {
  display: grid;
  place-items: center;
  padding: 0.5rem;
  border: 1px dashed var(--ap-line-strong);
  border-radius: var(--ap-radius);
  background: #f8f5ec;
}

.studio-figure svg {
  width: 100%;
  height: auto;
}

.studio-form textarea {
  font-size: 0.82rem;
  line-height: 1.5;
}

/* ----------------------------------------------------- exercise editor */
.editor-block {
  border: 0;
  margin: 0;
  padding: 0;
}

.editor-legend {
  display: block;
  width: 100%;
  margin-bottom: 0.65rem;
  padding-bottom: 0.35rem;
  border-bottom: 1px solid var(--ap-line);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ap-board-400);
}

.editor-md {
  font-family: ui-monospace, "Cascadia Code", "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.84rem;
  line-height: 1.55;
}

.editor-choices {
  display: grid;
  gap: 0.5rem;
}

.editor-choice {
  padding: 0.55rem 0.65rem;
  border: 1px solid var(--ap-line);
  border-radius: var(--ap-radius);
  background: var(--ap-surface);
}

.editor-choice.is-correct {
  border-color: color-mix(in srgb, var(--ap-flame-500) 45%, var(--ap-line));
  background: color-mix(in srgb, var(--ap-flame-100) 70%, var(--ap-surface));
}

.editor-choice-letter {
  display: grid;
  place-items: center;
  flex: 0 0 1.6rem;
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 999px;
  background: var(--ap-board-50);
  color: var(--ap-board-500);
  font-size: 0.72rem;
  font-weight: 700;
}

.editor-layer {
  border: 1px solid var(--ap-line);
  border-radius: var(--ap-radius);
  padding: 0.55rem 0.75rem;
  background: var(--ap-board-50);
}

.editor-layer summary {
  cursor: pointer;
  font-weight: 600;
  color: var(--ap-board-900);
}

.editor-preview-choices {
  padding-left: 1.15rem;
}

.editor-preview-choices li.is-correct {
  font-weight: 600;
  color: var(--ap-flame-700);
}

/* --------------------------------------------------------------- doubts */
.doubt-cta {
  display: flex;
  align-items: center;
  gap: 0.85rem;
}

.doubt-cta-icon {
  display: grid;
  width: 2.65rem;
  height: 2.65rem;
  flex: 0 0 auto;
  place-items: center;
  border-radius: 0.85rem;
  background: var(--ap-flame-100);
  font-size: 1.25rem;
}

.doubt-list {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}

/* The answer is set apart from the question: two voices, one card. */
.doubt-answer {
  margin-top: 0.9rem;
  padding: 0.85rem 1rem;
  border-left: 3px solid var(--ap-board-500);
  border-radius: 0 var(--ap-radius) var(--ap-radius) 0;
  background: var(--ap-board-50);
}

.doubt-answer-label {
  margin-bottom: 0.35rem;
  color: var(--ap-board-500);
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

/* -------------------------------------------------------- floating guide */
/* Sits clear of the bottom navigation on a phone, and of nothing on a desktop.
   Never covers the text it is talking about: the panel opens upwards. */
.tutor {
  position: fixed;
  right: 1rem;
  bottom: calc(4.75rem + env(safe-area-inset-bottom));
  z-index: 1030;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.6rem;
}

@media (min-width: 36em) {
  .tutor {
    bottom: 1.25rem;
  }
}

.tutor-toggle {
  display: grid;
  width: 3.25rem;
  height: 3.25rem;
  place-items: center;
  order: 2;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 50%;
  background: linear-gradient(145deg, var(--ap-board-600), var(--ap-board-800));
  box-shadow: 0 10px 26px rgba(12, 33, 27, 0.3);
  cursor: pointer;
}

.tutor-icon {
  font-size: 1.35rem;
  line-height: 1;
}

.tutor-toggle:hover {
  background: linear-gradient(145deg, var(--ap-board-500), var(--ap-board-700));
}

/* One quiet pulse until it has been opened once, then never again. */
.tutor-unseen .tutor-toggle::after {
  position: absolute;
  width: 3.25rem;
  height: 3.25rem;
  border: 2px solid var(--ap-flame-500);
  border-radius: 50%;
  content: "";
}

@media (prefers-reduced-motion: no-preference) {
  .tutor-unseen .tutor-toggle::after {
    animation: tutor-pulse 2.4s ease-out infinite;
  }

  @keyframes tutor-pulse {
    0% { transform: scale(1); opacity: 0.9; }
    70% { transform: scale(1.45); opacity: 0; }
    100% { opacity: 0; }
  }
}

.tutor-panel {
  order: 1;
  width: min(19rem, calc(100vw - 2rem));
  padding: 0.9rem 1rem 0.8rem;
  border: 1px solid var(--ap-line-strong);
  border-radius: var(--ap-radius);
  background: var(--ap-surface);
  box-shadow: 0 18px 45px rgba(12, 33, 27, 0.22);
}

.tutor-eyebrow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.4rem;
  color: var(--ap-board-400);
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.tutor-count {
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
}

.tutor-text {
  color: var(--ap-board-900);
  font-size: 0.92rem;
  line-height: 1.5;
}

.tutor-text > p:last-child {
  margin-bottom: 0;
}

.tutor-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-top: 0.85rem;
}

.tutor-close {
  border: 0;
  background: none;
  color: var(--ap-board-400);
  font-size: 0.8rem;
  font-weight: 650;
  cursor: pointer;
}

.tutor-close:hover {
  color: var(--ap-board-700);
}

/* ---------------------------------------------------------- alternatives */
/* Exam-shaped alternatives with a self-check that needs no JavaScript: the
   verdict is pure CSS off :has(), which is also why this is practice only —
   the graded quiz keeps its answers on the server. */
.alternatives {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0.4rem;
  margin: 0.9rem 0 0;
  padding: 0;
  border: 0;
}

/* Móvil: lista vertical y objetivos táctiles amplios. Escritorio: dos
   columnas como una hoja de admisión, sin encoger fórmulas ni enunciados. */
.answer-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0.5rem;
}

@media (min-width: 48em) {
  .answer-grid,
  .alternatives {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .alternatives-note {
    grid-column: 1 / -1;
  }
}

.alternatives .choice-text {
  flex: 1 1 auto;
  min-width: 0;
}

.alternatives .choice-text > p:last-child {
  margin-bottom: 0;
}

.alternatives-note {
  margin: 0.5rem 0 0;
  color: var(--ap-board-400);
  font-size: 0.74rem;
}

/* Nothing is revealed until the student commits to one. */
.alternatives:has(input:checked) .alternatives-note {
  display: none;
}

.alternatives:has(input:checked) .is-right {
  border-color: var(--ap-right-600);
  background: var(--ap-right-100);
}

.alternatives:has(input:checked) .is-right .choice-marker {
  border-color: var(--ap-right-600);
  background: var(--ap-right-600);
  color: #fff;
}

.choice:has(input:checked):not(.is-right) {
  border-color: var(--ap-review-600);
  background: var(--ap-review-100);
}

.choice:has(input:checked):not(.is-right) .choice-marker {
  border-color: var(--ap-review-600);
  background: var(--ap-review-600);
  color: #fff;
}

.choice-verdict {
  flex: 0 0 auto;
  align-self: center;
  font-size: 0.72rem;
  font-weight: 750;
}

/* Colour is never the only signal. */
.alternatives:has(input:checked) .is-right .choice-verdict::after {
  content: "correcta";
  color: var(--ap-right-700);
}

.choice:has(input:checked):not(.is-right) .choice-verdict::after {
  content: "la tuya";
  color: var(--ap-review-700);
}

.choice:has(input:focus-visible) {
  outline: 3px solid var(--ap-flame-500);
  outline-offset: 2px;
}

/* Each layer of the reveal is set in one step further, so the depth is visible
   before the student taps: a hint is not the same commitment as the answer. */
.reveal-hint > summary {
  color: var(--ap-board-600);
}

/* Each level would otherwise be inset by the parent's padding, and three
   levels eat a third of the width of a small phone. Pulled back so the layers
   read as a stack, not as a set of boxes inside boxes. */
.reveal-approach,
.reveal-solution {
  margin-inline: -0.6rem;
}

.reveal-solution > summary {
  color: var(--ap-flame-700);
}

/* The twin: same method, different numbers, no solution. */
.twin {
  margin: 0 1rem 1rem;
  padding: 0.9rem 1rem;
  border: 1px solid rgba(220, 150, 56, 0.35);
  border-left: 3px solid var(--ap-flame-500);
  border-radius: var(--ap-radius);
  background: rgba(249, 238, 220, 0.55);
}

.twin-label {
  margin-bottom: 0.4rem;
  color: var(--ap-flame-700);
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.twin-note {
  margin-top: 0.5rem;
  color: var(--ap-board-400);
  font-size: 0.76rem;
}

/* ------------------------------------------------------------- the chart */
/* One series, so one hue: identity is not in play, only magnitude. Today is
   the same green several steps darker — endpoint emphasis, not a second
   category. */
.chart-svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.chart-bar {
  fill: var(--ap-board-400);
}

.chart-bar-today {
  fill: var(--ap-board-800);
}

/* Reference and axis stay recessive: neither is data. */
.chart-rule {
  stroke: var(--ap-flame-500);
  stroke-width: 1;
  stroke-dasharray: 4 4;
  opacity: 0.75;
}

.chart-rule-label {
  fill: var(--ap-flame-700);
  font-size: 9px;
  font-weight: 700;
}

.chart-axis {
  stroke: var(--ap-line-strong);
  stroke-width: 1;
}

/* Values wear text ink, never the series colour. */
.chart-value {
  fill: var(--ap-board-900);
  font-size: 11px;
  font-weight: 800;
  text-anchor: middle;
}

.chart-caption {
  display: flex;
  justify-content: space-between;
  margin-top: 0.35rem;
  color: var(--ap-board-400);
  font-size: 0.7rem;
  font-weight: 650;
}

/* ------------------------------------------------------- training clock */
.trainer {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 0.7rem;
  margin-bottom: 1rem;
  padding: 0.6rem 0.85rem;
}

.trainer-label {
  display: flex;
  flex-direction: column;
  color: var(--ap-board-400);
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.trainer-target {
  letter-spacing: 0;
  text-transform: none;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
}

.trainer-time {
  margin-left: auto;
  color: var(--ap-board-800);
  font-size: 1.35rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

.trainer-running .trainer-time {
  color: var(--ap-board-600);
}

/* Past the target is a signal to ask for a hint, not a mark against anyone,
   so it is amber and never coral. */
.trainer-over .trainer-time {
  color: var(--ap-flame-700);
}

.trainer-reset {
  border: 0;
  background: none;
  color: var(--ap-board-400);
  font-size: 0.74rem;
  font-weight: 650;
  cursor: pointer;
}

.trainer-reset:hover {
  color: var(--ap-board-700);
}

.practice-chip-level {
  border-color: var(--level-ink, var(--ap-line-strong));
  color: var(--level-ink, var(--ap-board-700));
}

.practice-chip-level.practice-chip-on {
  background: var(--level-ink);
  border-color: var(--level-ink);
  color: #fff;
}

/* --------------------------------------------------------- practice weeks */
.practice-weeks {
  display: flex;
  gap: 0.4rem;
  overflow-x: auto;
  padding-bottom: 0.35rem;
  /* The row scrolls; the page never does. */
  scrollbar-width: thin;
}

.practice-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  flex: 0 0 auto;
  min-height: 2.5rem;
  padding: 0.4rem 0.8rem;
  border: 1px solid var(--ap-line-strong);
  border-radius: 999px;
  background: rgba(255, 253, 247, 0.96);
  color: var(--ap-board-700);
  font-size: 0.82rem;
  font-weight: 650;
  text-decoration: none;
  white-space: nowrap;
}

.practice-chip:hover {
  border-color: var(--ap-board-400);
  color: var(--ap-board-800);
}

.practice-chip-on {
  border-color: var(--ap-board-700);
  background: var(--ap-board-700);
  color: var(--ap-chalk, #f7f5ef);
}

.practice-chip-count {
  padding: 0.05rem 0.4rem;
  border-radius: 999px;
  background: var(--ap-board-100);
  color: var(--ap-board-700);
  font-size: 0.72rem;
  font-variant-numeric: tabular-nums;
}

.practice-chip-on .practice-chip-count {
  background: rgba(255, 255, 255, 0.22);
  color: #fff;
}

/* ---------------------------------------------------------- to review now */
.objective-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.obj-chip {
  border: 1px solid rgba(212, 76, 105, 0.2);
  border-radius: 0.7rem;
  padding: 0.4rem 0.65rem;
  background: var(--ap-review-100);
  color: var(--ap-review-700);
  font-size: 0.76rem;
  font-weight: 650;
  line-height: 1.35;
}

.auth-shell {
  max-width: 27rem;
  margin-inline: auto;
  padding-top: 1.5rem;
}

.auth-shell-wide { max-width: 47rem; }

.auth-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.5rem;
}

.auth-symbol {
  display: grid;
  width: 3.6rem;
  height: 3.6rem;
  margin-inline: auto;
  place-items: center;
  border-radius: 1.1rem;
  background: linear-gradient(145deg, var(--ap-board-500), var(--ap-board-800));
  box-shadow: 0 14px 30px rgba(34, 83, 69, 0.25);
  color: #fff;
  font-size: 1.5rem;
  font-weight: 850;
}

.auth-card {
  padding: clamp(1.25rem, 4vw, 2rem);
  border-top: 3px solid var(--ap-board-500);
  box-shadow: 0 20px 45px rgba(12, 33, 27, 0.1);
}

.auth-back-link {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  min-height: 2.5rem;
  padding: 0.55rem 0.8rem;
  border: 1px solid var(--ap-line-strong);
  border-radius: 0.75rem;
  background: color-mix(in srgb, var(--ap-surface) 88%, transparent);
  color: var(--ap-board-600);
  font-size: 0.82rem;
  font-weight: 700;
  text-decoration: none;
}

.auth-back-link:hover,
.auth-back-link:focus-visible {
  border-color: var(--ap-board-400);
  background: var(--ap-board-100);
  color: var(--ap-board-800);
  text-decoration: none;
}

.auth-field {
  margin-bottom: 1rem;
}

.password-field {
  position: relative;
}

.password-field .form-control {
  padding-right: 2.75rem;
}

.password-toggle {
  position: absolute;
  top: 50%;
  right: 0.35rem;
  transform: translateY(-50%);
  border: none;
  background: transparent;
  padding: 0.35rem 0.5rem;
  line-height: 1;
  font-size: 1.05rem;
  color: var(--ap-board-500);
  cursor: pointer;
}

.password-toggle:hover,
.password-toggle:focus-visible {
  color: var(--ap-board-800);
}

/* Bootstrap's .stretched-link overlay sits at z-index 1 over the whole row;
   a secondary icon action (edit, add) needs its own stacking context to stay
   clickable above it instead of being swallowed by the stretched anchor. */
.icon-link-above {
  position: relative;
  z-index: 2;
}

/* The row itself has no visible affordance otherwise -- only its title text
   looks like a link, so the rest of the row reads as dead space. */
.lesson-row:hover,
.lesson-row:focus-within {
  background-color: rgba(127, 127, 127, 0.08);
}

.auth-field-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0 1rem;
}

.auth-form-section + .auth-form-section {
  margin-top: 1.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--ap-line);
}

.auth-section-heading {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  margin-bottom: 1.15rem;
}

.auth-section-heading > span {
  display: grid;
  width: 2rem;
  height: 2rem;
  flex: 0 0 auto;
  place-items: center;
  border-radius: 0.65rem;
  background: var(--ap-board-100);
  color: var(--ap-board-700);
  font-size: 0.78rem;
  font-weight: 850;
}

.auth-section-heading h2 {
  margin: 0;
  color: var(--ap-board-900);
  font-size: 1rem;
  font-weight: 800;
}

.auth-section-heading p {
  margin: 0.15rem 0 0;
  color: var(--ap-board-500);
  font-size: 0.75rem;
}

.auth-school-fields[hidden] { display: none !important; }

.auth-context-note {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  margin-bottom: 1rem;
  padding: 0.7rem 0.8rem;
  border-radius: 0.75rem;
  background: var(--ap-board-50);
  color: var(--ap-board-700);
  font-size: 0.75rem;
}

.auth-context-note span {
  font-size: 1rem;
  font-weight: 800;
}

.auth-context-note p { margin: 0; }

.auth-submit-note {
  margin: 0.65rem 0 0;
  color: var(--ap-board-400);
  font-size: 0.68rem;
  text-align: center;
}

.form-control,
.form-select {
  border-width: 1.5px;
  border-radius: 0.75rem;
  background-color: #fff;
}

.form-text {
  font-size: 0.76rem;
}

[data-bs-theme="dark"] .auth-shell .form-label,
[data-bs-theme="dark"] .auth-section-heading h2 {
  color: #edf6f1;
}

[data-bs-theme="dark"] .auth-back-link {
  border-color: #396256;
  background: #10241f;
  color: #d7ebe4;
}

[data-bs-theme="dark"] .auth-back-link:hover,
[data-bs-theme="dark"] .auth-back-link:focus-visible {
  border-color: #74aa98;
  background: #1b392f;
  color: #fff;
}

[data-bs-theme="dark"] .auth-section-heading > span,
[data-bs-theme="dark"] .auth-context-note {
  background: #18372f;
  color: #cfe2db;
}

[data-bs-theme="dark"] .auth-section-heading p,
[data-bs-theme="dark"] .auth-submit-note {
  color: #a8c6bc;
}

.choice {
  border-width: 1.5px;
  border-color: var(--ap-board-200);
  border-radius: 0.9rem;
  box-shadow: 0 1px 2px rgba(12, 33, 27, 0.03);
}

.choice-static {
  cursor: default;
}

.choice:hover {
  box-shadow: 0 6px 16px rgba(12, 33, 27, 0.07);
  transform: translateY(-1px);
}

.choice-static:hover {
  transform: none;
}

.result-score {
  margin-bottom: 0.25rem;
  font-size: clamp(3rem, 12vw, 4.25rem);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.06em;
  text-shadow: 0 8px 28px rgba(0, 0, 0, 0.16);
}

.result-score span {
  font-size: 0.52em;
}

.solution-box > summary {
  font-size: 0.84rem;
}

.solution-content {
  padding: 0 1rem 1rem;
  font-size: 0.95rem;
}

.bottom-nav {
  box-shadow: 0 -8px 26px rgba(12, 33, 27, 0.09);
}

.bottom-nav a {
  position: relative;
  min-height: 4rem;
}

.bottom-nav a.active::before {
  position: absolute;
  top: 0;
  width: 1.8rem;
  height: 3px;
  border-radius: 0 0 999px 999px;
  background: var(--ap-board-500);
  content: "";
}

.nav-icon {
  display: grid;
  width: 2rem;
  height: 2rem;
  place-items: center;
  border-radius: 0.65rem;
  transition: background-color 140ms ease, transform 140ms ease;
}

.bottom-nav a.active .nav-icon {
  background: var(--ap-board-100);
  transform: translateY(-1px);
}

.lesson-body {
  max-width: 72ch;
}

/* Reading page: theory uses the full shell; exercises keep the 72ch measure. */
.lesson-body-wide {
  max-width: none;
}

.lesson-body h2 {
  position: relative;
  padding-top: 0.35rem;
  padding-left: 0.9rem;
}

.lesson-body h2::before {
  position: absolute;
  top: 0.25rem;
  bottom: -0.1rem;
  left: 0;
  width: 3px;
  border-radius: 999px;
  background: linear-gradient(var(--ap-board-500), var(--ap-flame-500));
  content: "";
}

.lesson-body h3 {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.lesson-body h3::before {
  width: 0.55rem;
  height: 0.55rem;
  border: 2px solid var(--ap-board-400);
  border-radius: 50%;
  content: "";
}

.lesson-body blockquote {
  border-radius: 0 0.75rem 0.75rem 0;
}

/* -------------------------------------------------------------- profile */
/* The account page: one identity hero, a four-stat grid, then the goal
   facts. Kept narrower than the course shell so it reads as a card, not a
   dashboard with empty margins. */
.profile-page {
  max-width: 34rem;
}

.profile-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1.25rem;
  padding: 1.75rem 1.35rem 1.5rem;
  text-align: center;
}

@media (min-width: 30em) {
  .profile-hero {
    flex-direction: row;
    text-align: left;
    padding: 1.5rem 1.5rem;
  }
}

.profile-avatar {
  display: grid;
  width: 4.25rem;
  height: 4.25rem;
  flex: 0 0 auto;
  place-items: center;
  border: 3px solid rgba(255, 255, 255, 0.28);
  border-radius: 1.35rem;
  background:
    radial-gradient(circle at 30% 25%, rgba(255, 255, 255, 0.22), transparent 55%),
    rgba(255, 255, 255, 0.12);
  color: #fff;
  font-size: 1.65rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.18);
}

.profile-identity {
  min-width: 0;
}

.profile-name {
  margin: 0;
  color: #fff;
  font-size: clamp(1.2rem, 2.5vw, 1.45rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.25;
}

.profile-role {
  margin-top: 0.25rem;
  color: rgba(247, 245, 239, 0.78);
  font-size: 0.9rem;
}

.profile-stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.75rem;
  margin-bottom: 1.25rem;
}

.profile-stat {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.15rem;
  padding: 1rem 1rem 0.95rem;
  border: 1px solid var(--ap-line);
  border-radius: var(--ap-radius);
  background: var(--ap-surface);
  box-shadow: var(--ap-shadow-sm);
}

.profile-stat-flame {
  border-color: color-mix(in srgb, var(--ap-flame-500) 28%, var(--ap-line));
  background:
    radial-gradient(circle at 100% 0%, color-mix(in srgb, var(--ap-flame-500) 12%, transparent), transparent 55%),
    var(--ap-surface);
}

.profile-stat-icon {
  margin-bottom: 0.35rem;
  font-size: 1.05rem;
  line-height: 1;
}

.profile-stat-value {
  color: var(--ap-board-900);
  font-size: clamp(1.45rem, 3.5vw, 1.75rem);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.03em;
  line-height: 1.1;
}

.profile-stat-label {
  color: var(--ap-board-400);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.profile-panel {
  margin-bottom: 1.25rem;
  padding: 1.15rem 1.2rem 0.85rem;
}

.profile-facts {
  display: grid;
  gap: 0;
}

.profile-fact {
  display: grid;
  gap: 0.15rem;
  padding: 0.85rem 0;
  border-top: 1px solid var(--ap-line);
}

.profile-fact:first-child {
  border-top: 0;
  padding-top: 0.15rem;
}

.profile-fact dt {
  color: var(--ap-board-400);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.profile-fact dd {
  margin: 0;
  color: var(--ap-board-900);
  font-size: 0.98rem;
  font-weight: 650;
  line-height: 1.35;
  overflow-wrap: anywhere;
}

.profile-actions {
  margin-bottom: 0.5rem;
}

.profile-logout {
  margin-top: 0.25rem;
}

[data-bs-theme="dark"] .profile-stat {
  border-color: #294a40;
  background: rgba(16, 36, 31, 0.97);
}

[data-bs-theme="dark"] .profile-stat-flame {
  border-color: rgba(220, 150, 56, 0.35);
  background:
    radial-gradient(circle at 100% 0%, rgba(220, 150, 56, 0.14), transparent 55%),
    rgba(16, 36, 31, 0.97);
}

[data-bs-theme="dark"] .profile-stat-value,
[data-bs-theme="dark"] .profile-fact dd {
  color: #edf6f1;
}

[data-bs-theme="dark"] .profile-stat-label,
[data-bs-theme="dark"] .profile-fact dt {
  color: #8fb3a6;
}

[data-bs-theme="dark"] .profile-fact {
  border-top-color: #294a40;
}

@media (min-width: 768px) {
  .page-content {
    padding-top: 2.5rem;
  }

  .card-board {
    padding: 1.75rem !important;
  }

  .auth-shell {
    padding-top: 3rem;
  }

  .auth-field-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .profile-hero.card-board {
    padding: 1.5rem 1.5rem !important;
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    transition-duration: 0.01ms !important;
  }
}

/* An alternative on a problem whose answer nobody has marked yet.
   It stays readable and stops behaving like a button: there is nothing to
   click, because the page cannot say whether the pick was right. */
.choice-unkeyed {
  cursor: default;
}

.choice-unkeyed:hover {
  border-color: var(--bs-border-color);
  background: inherit;
}
