/* ═══════════════════════════════════════════════════
   glyph-gallery.css — /glyphs/all
   Every BASE64 character rendered as a static kakuro miniature.
   Plain CSS (not Tailwind): the app's Tailwind bundle is purged, so classes
   that appear nowhere else would not survive the build.
   ═══════════════════════════════════════════════════ */

:root {
    --gg-cell: 19px;          /* one grid square */
    --gg-line: #c7ccd3;
    /* Light gray BEHIND the glyph. The play cells are white, so on a white card the character's
       silhouette had nothing to read against — the gray is what makes the shape pop. */
    --gg-mat:  #dde2e9;
    --gg-clue: #37474f;
    --gg-ink:  #111827;
}

* { box-sizing: border-box; }

body {
    margin: 0;
    padding: 0 0 3rem;
    background: #eef1f4;
    color: var(--gg-ink);
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

.gg-top { max-width: 1500px; margin: 0 auto; padding: 1.5rem 1rem 0.5rem; }
.gg-top h1 { margin: 0; font-size: 1.4rem; font-weight: 700; }
.gg-top h1 b { color: #7c3aed; }
.gg-sub { margin: 0.35rem 0 0; color: #6b7280; font-size: 0.9rem; max-width: 70ch; }

.gg-section { max-width: 1500px; margin: 0 auto; padding: 1.25rem 1rem 0; }
.gg-head {
    margin: 0 0 0.8rem;
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: #9ca3af;
}

/* Digits + punctuation: a single wrapping row — there are only a handful. */
.gg-row { display: flex; flex-wrap: wrap; gap: 0.9rem; }

/* Letters: FOUR columns of Aa, Bb, Cc … Zz, each pair stacked so a column stays
   one puzzle wide (a side-by-side pair would push the page past ~2300px). */
.gg-cols {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 1rem;
    align-items: start;
}
.gg-pair {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    padding: 0.7rem 0.5rem 0.9rem;
    background: var(--gg-mat);
    border: 1px solid #cdd4dc;
    border-radius: 12px;
}
.gg-pair-label {
    font-size: 1.05rem;
    font-weight: 700;
    letter-spacing: 0.02em;
}

.gg-item { display: flex; flex-direction: column; align-items: center; gap: .15rem; }

/* Admin edit link — deliberately quiet: it sits under every card, so at full strength 65 of them
   would compete with the puzzles themselves. */
.gg-edit {
    font-size: .68rem;
    color: #9ca3af;
    text-decoration: none;
    border-bottom: 1px dotted transparent;
}
.gg-edit:hover { color: #7c3aed; border-bottom-color: #7c3aed; }

.gg-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.3rem;
    padding: 0.5rem;
    border-radius: 10px;
    text-decoration: none;
    color: inherit;
    background: var(--gg-mat);
    border: 1px solid #cdd4dc;
}
/* Inside a pair the card drops its own frame — the .gg-pair box is the frame. */
.gg-pair .gg-card { border: none; background: none; padding: 0.15rem; }
.gg-card:hover { outline: 2px solid #7c3aed; outline-offset: 1px; }
.gg-card-label { font-size: 0.8rem; font-weight: 700; color: #64748b; }

.gg-grid { border-collapse: collapse; table-layout: fixed; }
.gg-grid td {
    width: var(--gg-cell);
    height: var(--gg-cell);
    padding: 0;
}
/* A blank is the margin around/inside the glyph — it carries no border, so the
   character's silhouette is what the eye picks out. */
.gg-blank { background: transparent; }
.gg-play  { background: #fff; border: 1px solid var(--gg-line); }
/* Clue cell: the diagonal splits the run-below sum (lower left) from the
   run-right sum (upper right), as in a printed kakuro. */
.gg-clue {
    position: relative;
    background: var(--gg-clue);
    background-image: linear-gradient(to bottom right,
        transparent calc(50% - 0.5px), rgba(255,255,255,0.45) 50%,
        transparent calc(50% + 0.5px));
    border: 1px solid var(--gg-clue);
}
.gg-clue span {
    position: absolute;
    font-size: 7px;
    line-height: 1;
    font-weight: 700;
    color: #fff;
    font-variant-numeric: tabular-nums;
}
.gg-clue .gg-r { top: 1px;    right: 1px; }   /* sum of the run to the RIGHT */
.gg-clue .gg-c { bottom: 1px; left: 1px; }    /* sum of the run BELOW */

.gg-empty { max-width: 1500px; margin: 2rem auto; padding: 0 1rem; color: #6b7280; }
.gg-empty code { background: #fff; padding: 0.15rem 0.4rem; border-radius: 5px; }

.gg-foot {
    max-width: 1500px;
    margin: 2rem auto 0;
    padding: 1rem;
    color: #6b7280;
    font-size: 0.85rem;
}
.gg-foot a { color: #7c3aed; }

@media (max-width: 1200px) { .gg-cols { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 900px)  { .gg-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 600px)  {
    .gg-cols { grid-template-columns: minmax(0, 1fr); }
    :root { --gg-cell: 16px; }
}

/* ─── States gallery (/states/puzzle/all) ─────────────────────────
   A state runs up to 30 columns where a glyph is ~12, so the cells shrink and the
   columns are sized by content rather than pinned to four. */
body.gg-states { --gg-cell: 11px; }
.gg-cols-states {
    grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
    align-items: start;
}
.gg-cols-states .gg-pair { padding: 0.6rem 0.5rem 0.7rem; }
.gg-abbr {
    margin-left: 0.35rem;
    padding: 0.05rem 0.35rem;
    border-radius: 5px;
    background: #cdd4dc;
    color: #475569;
    font-size: 0.7rem;
    letter-spacing: 0.04em;
}
.gg-meta {
    font-size: 0.7rem;
    font-weight: 600;
    color: #64748b;
    font-variant-numeric: tabular-nums;
}
/* Named, not hidden: the clamped states are the ones whose size is NOT to scale. */
.gg-clamp {
    display: inline-block;
    margin-left: 0.3rem;
    padding: 0.05rem 0.35rem;
    border-radius: 5px;
    background: #fde68a;
    color: #92400e;
    font-size: 0.65rem;
}
/* The label slot is empty for states (the pair header names them) — don't reserve space. */
.gg-cols-states .gg-card-label:empty { display: none; }

/* Clue cells INSIDE the shape sit lighter than the ones ringing it. The interior lattice is
   structural (a solid state can't be solved without it), but at the boundary tone it reads as
   holes punched in the state and the silhouette disappears. */
.gg-clue.is-inner {
    background-color: #8296a5;
    border-color: #8296a5;
}
.gg-clue.is-inner span { color: #f8fafc; }

/* ─── Cells over an outline backdrop ──────────────────────────────
   With the state's true outline behind the grid, the cells must be SEMI-TRANSPARENT or they
   simply hide it. The backdrop then carries the shape and the cells read as the puzzle laid on
   top — which is also why the interior clue tone can stay light. */
body.gg-states .gg-play        { background: rgba(255,255,255,0.62); }
body.gg-states .gg-clue        { background-color: rgba(55,71,79,0.72); border-color: transparent; }
body.gg-states .gg-clue.is-inner {
    background-color: rgba(130,150,165,0.45);
    border-color: transparent;
}
body.gg-states .gg-clue.is-inner span { color: #1f2d3a; }

/* ── Pre-rendered grid image ──────────────────────────────────────────────
   The card's grid as a static PNG instead of a table of <td>s (see
   scripts/shape-thumbs.py). The image is transparent, so the outline artwork set as this
   element's background-image still shows through underneath, exactly as it did behind the table.

   ⚠️ `height:auto` is the point. The table version was `table-layout:fixed`, which squashed a wide
   grid's columns while holding the rows at full cell height — 115 of /mapskuro/world's 570 cards
   rendered near a 0.47 ratio. An image keeps the ratio the file was drawn at. */
.gg-grid-img {
    display: block;
    width: 100%;
    height: auto;
    /* ⚠️ NO `image-rendering: pixelated`. Cards downscale these — Mexico's large grid is drawn at
       436px and shown at 281 (0.645x) — and nearest-neighbour at a non-integer ratio drops whole
       pixel rows, so a 12px cell lands as 7px or 8px depending where it falls and the grid visibly
       has cells of different sizes. The table version could not do this: the browser distributed
       DOM boxes evenly. Smooth interpolation averages instead, which is what a 1.6x asset scaled
       down wants anyway. */
}
