/* ============================================================================
   Decoded — catalogue hub and module viewer
   Loaded after grow.css. Tokens only; no literal colours.
   ============================================================================ */

/* ---------------------------------------------------------- progress bar - */

.progress-bar {
  display: flex;
  align-items: center;
  gap: var(--s4);
  padding: var(--s3) var(--s4);
  margin-bottom: var(--s4);
}
.progress-bar__text { font-size: 13px; color: var(--ink-2); white-space: nowrap; }
.progress-bar__text b { color: var(--ink); font-variant-numeric: tabular-nums; }

.progress-bar__track {
  flex: 1;
  height: 8px;
  background: var(--surface-3);
  border-radius: var(--r-pill);
  overflow: hidden;
}
.progress-bar__fill {
  display: block;
  height: 100%;
  width: 0;
  background: var(--pri-grad);
  border-radius: var(--r-pill);
  transition: width .3s ease;
}

/* -------------------------------------------------------------- toolbar -- */

.toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s4);
  margin-bottom: var(--s5);
}
.toolbar__search { flex: 1 1 260px; margin-bottom: 0; }

.chips { display: flex; flex-wrap: wrap; gap: var(--s2); }

.chip {
  min-height: 36px;
  padding: 0 var(--s4);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  color: var(--ink-2);
  font: inherit;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  transition: background .16s ease, color .16s ease, border-color .16s ease;
}
.chip:hover { background: var(--surface-2); color: var(--ink); }
.chip[aria-pressed="true"] {
  background: var(--pri-soft);
  border-color: var(--pri-line);
  color: var(--pri-ink);
}
/* The count is information, not decoration, so it does not get dimmed.
   opacity:.75 on --ink-2 measured 3.37:1 at 10.8px — under the 4.5:1 floor.
   Inheriting the chip's own colour keeps it readable in both states. */
.chip small { font-weight: 600; font-size: 12px; margin-left: 5px; }

/* ------------------------------------------------------------- catalogue - */

.phase { margin-bottom: var(--s7); }

.phase__head {
  display: flex;
  align-items: baseline;
  gap: var(--s3);
  margin-bottom: var(--s4);
  padding-bottom: var(--s2);
  border-bottom: 1px solid var(--line);
}
.phase__head h2 {
  margin: 0;
  font-size: 19px;
  font-weight: 800;
  letter-spacing: -0.01em;
}
.phase__head span { font-size: 13px; color: var(--ink-3); margin-left: auto; }

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(268px, 1fr));
  gap: var(--s4);
}

.module {
  display: flex;
  flex-direction: column;
  padding: var(--s4);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-1);
  color: var(--ink);
  transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
}
.module:hover {
  text-decoration: none;
  transform: translateY(-2px);
  box-shadow: var(--sh-2);
  border-color: var(--pri-line);
}
.module:focus-visible { box-shadow: var(--focus), var(--sh-2); }

.module__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s2);
  margin-bottom: var(--s3);
}

/* No thumbnails exist yet, and a broken <img> reads worse than no image. The
   ordinal badge doubles as the visual anchor and as "where am I in the track".
   Swap to a real thumbnail later without touching the card layout. */
.module__badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px; height: 36px;
  border-radius: var(--r-sm);
  background: var(--surface-3);
  color: var(--ink-2);
  font-size: 14px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}
.module[data-done="true"] .module__badge {
  background: var(--ok-soft);
  color: var(--ok);
}

.module h3 {
  margin: 0 0 6px;
  font-size: 16px;
  font-weight: 700;
  line-height: 1.35;
  letter-spacing: -0.01em;
}
.module p {
  margin: 0 0 var(--s4);
  font-size: 13px;
  color: var(--ink-2);
  line-height: 1.55;
}

.module__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s2);
  margin-top: auto;
  padding-top: var(--s3);
  border-top: 1px solid var(--line-2);
  font-size: 12px;
  color: var(--ink-3);
  font-weight: 600;
}
.module__open { color: var(--pri-ink); font-weight: 700; }

/* A phase kept in the manifest but with nothing published yet still renders,
   so the roadmap stays visible. */
.phase--empty .grid { display: block; }
.coming-soon {
  padding: var(--s5);
  border: 1px dashed var(--line);
  border-radius: var(--r-lg);
  text-align: center;
  color: var(--ink-3);
  font-size: 13px;
}

/* ============================================================== viewer ==== */

/* The viewer is a full-height app shell: fixed bar, module fills the rest.
   100dvh rather than 100vh so mobile browser chrome collapsing does not leave
   a dead strip under the iframe. */
body.viewer { min-height: 100dvh; display: flex; flex-direction: column; }
body.viewer main { flex: 1; display: flex; flex-direction: column; min-height: 0; }

.viewer-bar {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: var(--s3) var(--s4);
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}

.viewer-bar__title { min-width: 0; margin-right: auto; }
.viewer-bar__title h1 {
  margin: 0;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.viewer-bar__title span {
  display: block;
  font-size: 12px;
  color: var(--ink-3);
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.viewer-bar__nav { display: flex; align-items: center; gap: var(--s2); }

.viewer-stage {
  flex: 1;
  min-height: 0;
  padding: var(--s4);
  background: var(--surface-2);
  /* The stage is itself a flex container: an iframe's percentage height does
     not resolve against a flex item whose own height is `auto`, so the frame
     grows by flex instead of by height:100%. */
  display: flex;
}

/* The modules carry their own dark theme. Rather than fight it, the frame
   presents it as a deliberate canvas — inset, rounded, shadowed — so the
   colour switch reads as "this is the lesson" instead of a styling failure. */
.module-frame {
  flex: 1;
  width: 100%;
  min-height: 0;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--ink);
  box-shadow: var(--sh-2);
  overflow: hidden;
  display: block;
}

@media (max-width: 860px) {
  .viewer-bar__title h1 { font-size: 14px; }
  .viewer-stage { padding: var(--s2); }
  .module-frame { border-radius: var(--r-sm); }
}

@media (max-width: 640px) {
  .toolbar { gap: var(--s3); }
  .grid { grid-template-columns: 1fr; }
  .progress-bar { flex-wrap: wrap; }
  .progress-bar__track { order: 3; flex-basis: 100%; }

  /* Back + title + three controls cannot share one 375px row: the title
     collapsed to 0px wide and the phase line wrapped into a vertical column.
     Two rows instead — identity on top, controls beneath. */
  .viewer-bar { flex-wrap: wrap; padding: var(--s2) var(--s3); gap: var(--s2); }
  .viewer-bar > .btn { order: 1; }
  .viewer-bar__title { order: 2; flex: 1 1 0; min-width: 0; margin-right: 0; }
  .viewer-bar__nav { order: 3; flex: 1 1 100%; justify-content: space-between; }

  /* Label text is redundant next to the arrows at this width; the buttons
     keep their accessible names via aria-label. */
  .viewer-bar .btn span { display: none; }
  .viewer-bar .btn { width: auto; padding: 0 var(--s3); }
}

/* The viewer is a full-height shell; a marketing footer below a 100dvh stage
   would only be reachable by scrolling past the lesson. */
body.viewer .site-foot { display: none; }
