/* ============================================================
   modules.css — literal translation of
   library/lib/src/components/modules.dart
   ============================================================
   A course as TOPICS over MODULES, in the component's DRAFT
   state — what you get when no onSelect is passed: nothing
   tappable, no chevrons, and every ring empty, since "what
   can't be picked can't have progress". That is the true state
   here; nothing on a landing page has been practiced.

   Topic head — a full-width soft button's box (36 tall, its lg
   corner, its s4 label inset) carrying the topic's name in
   Muted instead of a button's label, on `accent`. It borrows
   the shape only, which is why the fill is accent and not the
   soft button's muted.

   It HOLDS the top of the scroll view until its own modules run
   out, then travels up as the next one takes over. `sticky`
   inside the topic gives exactly that, and for the same reason:
   the topic is the containing block, so the head can never
   outlive its own rows. It is never dimmed or faded — it moves.

   Module row — ring, name, and the thread down to the next ring.

     ring     12, the ink of a 16px Lucide glyph rather than its
              nominal size, so it reads as one of the icons and
              not a bigger, lighter shape. 2px stroke, track in
              `border`; the foreground arc never shows at 0.
     gap      Spacing.s4, ring to name
     name     H5
     between  Spacing.s8, carried INSIDE the row as padding on
              the name's column, so the thread runs through the
              gap rather than stopping short of it
     thread   1px in `border`, inset s1 top and bottom — equally,
              which is what makes its clearance to the ring above
              and the ring below the same
   ============================================================ */

.topic + .topic { margin-top: var(--space-8); }

.topic-head    { position: sticky; top: 0; z-index: 2;
                 height: 36px; display: flex; align-items: center;
                 padding: 0 var(--space-4);
                 margin-bottom: var(--space-8);
                 border-radius: var(--radius-lg);
                 background: var(--color-accent);
                 font-size: var(--font-size-sm);            /* Muted */
                 color: var(--color-muted-foreground);
                 white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* The band the Dart carries under the head: the one place a scroll view can
   put a fade that its own content paints over. It shows only in the stretch
   between one head leaving and the next arriving, and dissolves the rows
   crossing the top edge rather than leaving them sliced. Deep enough to take
   a whole row — a band one line tall reads as a cut, not a fade.

   Sticky, so it stays on that edge; z-index under the heads and over the rows,
   which is the whole arrangement. The negative margin keeps it out of the flow. */
.modules-fade  { position: sticky; z-index: 1; pointer-events: none;
                 height: var(--space-16); }
.modules-fade--top    { top: 0; margin-bottom: calc(-1 * var(--space-16));
                        background: linear-gradient(to bottom,
                          var(--color-background), transparent); }
/* The trailing edge of a FadeScrollView, at the depth the head's band uses so
   the two ends of the same scroller match. Same arrangement mirrored: last
   child, stuck to the bottom, pulled back out of the flow by its own height. */
.modules-fade--bottom { bottom: 0; margin-top: calc(-1 * var(--space-16));
                        background: linear-gradient(to top,
                          var(--color-background), transparent); }

.modules       { list-style: none; margin: 0; padding: 0;
                 display: flex; flex-direction: column; }

/* The type is set on the row, not the name, so the ring below can size its
   own offset off the name's line without being told how tall that line is. */
.module        { display: flex; align-items: stretch; gap: var(--space-4);
                 font-size: var(--font-size-sm);            /* H5 */
                 font-weight: var(--font-weight-medium);
                 line-height: 1.2; }

.module-mark   { flex: none; width: 12px;
                 display: flex; flex-direction: column; align-items: center; }

/* Centred on the name's first line, the way _onLine does it in the Dart. */
.module-ring   { flex: none; box-sizing: border-box;
                 width: 12px; height: 12px; border-radius: 50%;
                 border: 2px solid var(--color-border);
                 margin-top: calc((1.2em - 12px) / 2); }

/* The thread takes whatever is left of the row beneath the ring — which is
   why the gap between rows has to live on the name's column and not on the
   row itself. Put it on the row and this stops at the content edge. */
.module:not(:last-child) .module-mark::after {
                 content: ''; flex: 1; width: 1px;
                 margin: var(--space-1) 0;
                 background: var(--color-border); }

.module-body   { flex: 1; min-width: 0; }
.module:not(:last-child) .module-body { padding-bottom: var(--space-8); }

/* The Dart centres the head's label on mobile, like a button's own, and starts
   it where the module names do otherwise. */
@media (max-width: 767.98px) {
  .topic-head  { justify-content: center; }
}
