* { box-sizing: border-box; }

body {
  margin: 0;
  min-height: 100vh;
  background: var(--mg-bg);
  color: var(--mg-text);
  font-family: var(--mg-font);
  transition: background 0.4s ease, color 0.4s ease;
  position: relative;
  overflow-x: hidden;
}

/* ambient scanline overlay */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 999;
  background: repeating-linear-gradient(
    to bottom,
    var(--mg-scanline, rgba(255, 255, 255, 0.02)) 0px,
    var(--mg-scanline, rgba(255, 255, 255, 0.02)) 1px,
    transparent 1px,
    transparent 3px
  );
}

.mg-page {
  max-width: 1080px;
  margin: 0 auto;
  padding: 3rem 1.5rem 5rem;
}

.mg-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: 1.5rem;
  border-bottom: 1px solid var(--mg-border);
  padding-bottom: 1.5rem;
  margin-bottom: 3rem;
}

.mg-header h1 {
  margin: 0;
  font-size: 1.6rem;
  letter-spacing: 0.35em;
  color: var(--mg-accent);
  text-shadow: 0 0 12px var(--mg-accent-glow);
}

.mg-header p {
  margin: 0.4rem 0 0;
  color: var(--mg-text-dim);
  font-size: 0.85rem;
  letter-spacing: 0.05em;
}

.mg-theme-toggle {
  display: flex;
  gap: 0.5rem;
}

.mg-theme-toggle button {
  background: transparent;
  border: 1px solid var(--mg-border);
  color: var(--mg-text-dim);
  font-family: var(--mg-font);
  font-size: 0.75rem;
  letter-spacing: 0.15em;
  padding: 0.5rem 0.9rem;
  cursor: pointer;
  transition: all 0.2s ease;
}

.mg-theme-toggle button:hover {
  color: var(--mg-accent);
  border-color: var(--mg-accent);
}

.mg-theme-toggle button.is-active {
  color: var(--mg-on-accent, var(--mg-bg));
  background: var(--mg-accent);
  border-color: var(--mg-accent);
}

/* Filter strip. Sticks to the top so the categories stay reachable as the
   library grows — with the grid at one column on mobile, every module added
   pushes everything below it down by a full row, and compositions living at
   the end of a flat scroll became unreachable fast (measured: 3.8 screens at
   16 modules, ~10.7 at 48). Filtering, not scrolling, is how you get to them. */
.mg-filter {
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: -3rem 0 2rem;
  padding: 1rem 0;
  background: var(--mg-bg);
  border-bottom: 1px solid var(--mg-border);
}

.mg-filter button {
  display: inline-flex;
  align-items: baseline;
  gap: 0.45rem;
  background: transparent;
  border: 1px solid var(--mg-border);
  color: var(--mg-text-dim);
  font-family: var(--mg-font);
  font-size: 0.75rem;
  letter-spacing: 0.15em;
  padding: 0.5rem 0.9rem;
  cursor: pointer;
  transition: color 0.2s ease, border-color 0.2s ease, background 0.2s ease;
}

.mg-filter button:hover {
  color: var(--mg-accent);
  border-color: var(--mg-accent);
}

.mg-filter button[aria-pressed='true'] {
  color: var(--mg-on-accent, var(--mg-bg));
  background: var(--mg-accent);
  border-color: var(--mg-accent);
}

.mg-filter__count {
  font-size: 0.65rem;
  opacity: 0.7;
  letter-spacing: 0.05em;
}

.mg-filter__note {
  margin: -1rem 0 2rem;
  font-size: 0.7rem;
  line-height: 1.6;
  color: var(--mg-text-dim);
  letter-spacing: 0.05em;
  max-width: 52ch;
}

.mg-filter__note[hidden] {
  display: none;
}

/* Showcase: a dense grid of live modules, side by side, so you can actually
   see how they read packed together — the whole point of "micro" graphics.
   auto-fit + minmax naturally settles at ~4 columns on desktop widths and
   collapses to a single column on mobile, with no separate breakpoint needed. */
.mg-showcase {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1.5rem;
}

/* A composition packs several modules into one frame, so it needs more width
   than a single-primitive module. .mg-page is capped at 1080px, so the only
   way to give it room is to take more columns — the grid can't get wider.
   `1 / -1` rather than `span 2` deliberately: span 2 in the one-column mobile
   grid would force an implicit second column and overflow the page, whereas
   1 / -1 is "every column there is" and stays correct at any column count.
   The frame is then capped so it gains real width without stretching to the
   full 1080px, which would leave it sparse. No media query either way.

   380px is set by the headline: it is the widest natural element, and at this
   cap it fills the frame with a comfortable margin. Below ~360px it runs at
   the edge; above ~440px the space-between rows open up a dead gap up the
   middle. Rows can't be tightened instead — .mg-module__row is shared with all
   16 modules, and modules are atomic. */
.mg-tile[data-cat='composition'] {
  grid-column: 1 / -1;
}

.mg-tile[data-cat='composition'] .mg-frame,
.mg-tile[data-cat='composition'] .mg-tile__details {
  width: 100%;
  max-width: 380px;
}

/* Hidden by the filter, rather than by [hidden], so the rule can't be beaten
   by .mg-tile's own display:flex the way .mg-tile__details[hidden] once was. */
.mg-tile.is-filtered-out {
  display: none;
}

/* .mg-tile is gallery-only chrome: it wraps a live .mg-frame module and,
   on click/Enter/Space, reveals title + description + copy button beneath
   it. The module itself never changes — only this wrapper is interactive. */
.mg-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  padding: 1.5rem 0.5rem;
  cursor: pointer;
}

.mg-tile:focus-visible {
  outline: 1px dashed var(--mg-accent);
  outline-offset: 6px;
}

.mg-tile__details {
  width: 100%;
  max-width: 230px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.6rem;
  text-align: left;
}

.mg-tile__details[hidden] {
  display: none;
}

.mg-tile__title {
  font-size: 0.7rem;
  letter-spacing: 0.2em;
  color: var(--mg-text-dim);
  text-transform: uppercase;
}

.mg-tile__desc {
  margin: 0;
  font-size: 0.68rem;
  color: var(--mg-text-dim);
  line-height: 1.6;
}

.mg-copy-btn {
  align-self: flex-start;
  background: transparent;
  border: 1px solid var(--mg-border);
  color: var(--mg-accent);
  font-family: var(--mg-font);
  font-size: 0.7rem;
  letter-spacing: 0.15em;
  padding: 0.45rem 0.8rem;
  cursor: pointer;
  transition: all 0.2s ease;
}

.mg-copy-btn:hover {
  background: var(--mg-accent);
  color: var(--mg-on-accent, var(--mg-bg));
}

.mg-toast {
  position: fixed;
  bottom: 1.5rem;
  left: 50%;
  transform: translateX(-50%) translateY(20px);
  background: var(--mg-accent);
  color: var(--mg-on-accent, var(--mg-bg));
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  padding: 0.6rem 1.2rem;
  opacity: 0;
  pointer-events: none;
  transition: all 0.25s ease;
  z-index: 1000;
}

.mg-toast.is-visible {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

.mg-footer {
  margin-top: 4rem;
  font-size: 0.7rem;
  color: var(--mg-text-dim);
  letter-spacing: 0.05em;
  border-top: 1px solid var(--mg-border);
  padding-top: 1.25rem;
}
