@charset "UTF-8";
/* ==========================================================================
   Bible Games — the card-grid layout  (shared/grid.css)
   --------------------------------------------------------------------------
   Every game on this site that says "turn two cards over and see whether they
   go together" wears this file. The Ten Commandments and Bible Books Memory
   are the first two.

   WHY THIS IS SHARED, AND WHY IT IS NOT quiz.css

   Shared.md §5 asks: could a page reasonably want it different? Two memory
   grids do not reasonably want a different card, a different flip or a
   different way of marking a matched pair — and written twice they would drift.
   But a card grid and a four-choice quiz plainly DO differ, which is why this
   is its own file and not an option on that one. The handoff note for this
   rebuild said so in as many words: do not force the memory games into the
   quiz layer.

   What they share with the quiz is the shell (shell.css) and the answer panel
   in it — the verdict, the explanation and the verse. Every game on this site
   says those same three things, so they live in shell.css and both layers use
   them.

   --------------------------------------------------------------------------
   HOW A PAGE LOADS IT

     <link rel="stylesheet" href="/biblegames/shared/theme.css?v=...">
     <link rel="stylesheet" href="/biblegames/shared/shell.css?v=...">
     <link rel="stylesheet" href="/biblegames/shared/grid.css?v=...">
     <link rel="stylesheet" href="styles.css?v=...">

   shell.css is REQUIRED and comes first. This file assumes .app, .stage,
   .topbar, .hud, .feedback and .overlay already exist.

   --------------------------------------------------------------------------
   THE TWO RULES THIS FILE MUST NOT BREAK

   1. THE PAGE MUST NOT SCROLL. Twenty cards have to fit a phone screen, which
      is why a card face carries a SHORT label and the full verse goes in the
      panel underneath. A card is not a place to print a commandment.

   2. THE TWO KINDS OF CARD ARE NOT TOLD APART BY COLOUR ALONE. A face-down
      card says what kind it is in a word — "Number", "Book" — as well as by
      its tint. Knowing which half of the pack you are looking at halves the
      search and makes the game achievable for a young child; doing it with
      colour only would take that away from about one boy in twelve.

   --------------------------------------------------------------------------
   Contents
     1. Tokens
     2. The board
     3. A card
     4. The panel under the board
     5. Responsive
     6. Reduced motion, forced colours, more contrast, print
   ========================================================================== */

/* -------------------------------------------------------------------------- */
/* 1. Tokens                                                                  */
/* -------------------------------------------------------------------------- */

:root {
  /* How many cards across. A game sets this on .grid from its own styles.css
     or inline; the responsive block below overrides it on small screens. */
  --grid-cols: 5;
  --grid-gap: 6px;

  /* The two halves of the pack. Deliberately close in brightness — the tint is
     a convenience, not the signal. The word on the card back is the signal. */
  --card-a: linear-gradient(160deg, #3a2a6e, #221650);
  --card-b: linear-gradient(160deg, #2a3a6e, #161f4a);
  --card-face: linear-gradient(160deg, #f6efdd, #e6dcc2);
}

/* -------------------------------------------------------------------------- */
/* 2. The board                                                               */
/* -------------------------------------------------------------------------- */

.grid {
  display: grid;
  grid-template-columns: repeat(var(--grid-cols), 1fr);
  /*
   * The rows share whatever height .stage has, rather than each taking only
   * what a card needs.
   *
   * Without this the board came out as a block of small cards floating in the
   * middle of a tall phone screen with a third of the page empty above and
   * below it. Bigger cards are also easier to hit, which on a game aimed at
   * children is not a cosmetic argument.
   *
   * The floor is .card's min-height. Where there is genuinely not enough room
   * for that — the sub-300px zoom case — the shell has already let the page
   * scroll, so the cards stay a fingertip tall instead of being crushed.
   */
  grid-auto-rows: 1fr;
  gap: var(--grid-gap);
  width: 100%;
  height: 100%;
  max-width: 40rem;
  margin: auto;
  /* The board is inside .stage, which is the one flexible row. min-height: 0
     lets it shrink rather than pushing the panel off the bottom. */
  min-height: 0;
}

/* -------------------------------------------------------------------------- */
/* 3. A card                                                                  */
/* -------------------------------------------------------------------------- */

.card {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  /* 44px is what a fingertip needs, and it is a FLOOR, not a size: the rows
     share the board's height, so a card is normally taller than this. */
  min-height: 44px;
  padding: 4px 5px;
  border: 1px solid var(--panel-edge);
  border-radius: 10px;
  background: var(--card-a);
  color: var(--text);
  font-family: var(--font-ui);
  font-size: clamp(0.56rem, 2.1vw, 0.8rem);
  line-height: 1.2;
  text-align: center;
  cursor: pointer;
  overflow: hidden;
  -webkit-tap-highlight-color: transparent;
  transition: transform var(--dur) ease, border-color var(--dur) ease,
              background var(--dur) ease;
}

.card--a { background: var(--card-a); }
.card--b { background: var(--card-b); }

/*
 * The word on the back of a face-down card.
 *
 * This is the accessibility rule at the top of the file made concrete: a child
 * who cannot use the tint can still read "Number" or "Book" and know which
 * half of the pack they are looking at. It disappears when the card turns over,
 * because the face then says what it is.
 */
.card__kind {
  font-size: 0.9em;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.card__face {
  display: none;
  overflow-wrap: break-word;
  word-break: break-word;
  hyphens: auto;
  color: #241703;
  font-weight: 700;
}

/* ---- face up ------------------------------------------------------------ */

.card.is-up,
.card.is-matched {
  background: var(--card-face);
  border-color: var(--gold-2);
}

.card.is-up .card__kind,
.card.is-matched .card__kind { display: none; }

.card.is-up .card__face,
.card.is-matched .card__face { display: block; }

/*
 * Keep the top-right corner clear for the tick or the cross.
 *
 * The badge is positioned, so it does not push text aside: on a small phone a
 * two-line label ("No graven image") ran its first line straight underneath the
 * cross. A float of the same size reserves the corner in the text flow, so only
 * the FIRST line gives up the space and the rest of the label is untouched.
 *
 * It is on every face-up card, not just a matched or missed one, so that the
 * words do not shift the moment a pair is judged.
 */
.card.is-up .card__face::before,
.card.is-matched .card__face::before {
  content: "";
  float: right;
  /*
   * 1rem, and it is MEASURED. In rem, NOT em, because the badge is 0.9rem
   * whatever the card's font is — the numbers side of the Ten Commandments
   * sets its face to 2rem, and an em here made the reserved corner taller
   * than the whole card.
   *
   * 1rem is also the LARGEST it can be. On a short, wide card (about 102x42
   * at 768x500) a bigger corner pushes "Honour your parents" onto a third
   * line, which the card then clips. Both games, six viewports, every label
   * plus a full-length synthetic one were measured to settle on this.
   */
  width: 1rem;
  height: 1rem;
}

/*
 * A matched pair.
 *
 * A ring AND a tick, never a colour on its own. It also stops being a target:
 * pointer-events off, so a stray tap on a finished pair cannot count as a move.
 */
.card.is-matched {
  border-color: var(--right);
  box-shadow: 0 0 0 2px var(--right);
  cursor: default;
  pointer-events: none;
}

.card.is-matched::after {
  content: "✓";
  position: absolute;
  top: 1px;
  right: 4px;
  font-size: 0.9rem;
  /* A tight box, so the corner the words give up is the corner the badge
     actually uses. At the default line-height it was 17px tall against a 14px
     glyph, and the 3px of nothing underneath is where a label ran into it. */
  line-height: 1;
  font-weight: 800;
  color: #1b6b3f;
}

/* A pair that did not go together, in the moment before they turn back. */
.card.is-miss {
  border-color: var(--wrong);
  box-shadow: 0 0 0 2px var(--wrong);
}

.card.is-miss::after {
  content: "✗";
  position: absolute;
  top: 1px;
  right: 4px;
  font-size: 0.9rem;
  line-height: 1;          /* see the tick, above */
  font-weight: 800;
  color: #8a2b0e;
}

/* -------------------------------------------------------------------------- */
/* 4. The panel under the board                                               */
/* -------------------------------------------------------------------------- */

/*
 * .feedback itself is styled in shell.css. What a GRID adds is where it sits:
 * its own row beneath the board rather than inside .stage, and a fixed height
 * so that filling it does not shove the board upwards and move every card a
 * child is trying to remember the position of.
 *
 * That last point is the whole reason it is a row and not part of the stage.
 * In a memory game, the cards moving is not a cosmetic problem — it destroys
 * the thing the player is holding in their head.
 */
/*
 * Tall enough to hold the whole thing without scrolling.
 *
 * A matched pair prints four things — the verdict, the explanation, the verse
 * and its reference — which is six or seven lines. At 6.4em it held about
 * four, and the VERSE was the part that fell off the bottom: the panel
 * scrolled, so nothing looked broken, and the scripture was simply not read.
 * That is the one thing on the page that must never be the part that is cut.
 *
 * The board gives up the height rather than the panel, because grid.css rows
 * are 1fr and shrink to fit. A card has a 44px floor under it, which is a
 * fingertip, so the board can afford this and the verse cannot.
 */
.gridnote {
  flex: 0 0 auto;
  height: 9.4em;
  overflow-y: auto;
  padding: 7px 12px;
}

.gridnote .feedback__why { font-size: 0.86rem; }
.gridnote .feedback__verse { font-size: 0.86rem; }
.gridnote .feedback__scripture { margin-top: 7px; padding: 6px 10px 5px; }

/* The resting line, before anything has been matched. */
.gridnote.is-idle {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-dim);
}

/* -------------------------------------------------------------------------- */
/* 5. Responsive                                                              */
/* -------------------------------------------------------------------------- */

@media (hover: hover) {
  .card:not(.is-matched):hover {
    border-color: rgba(255, 214, 130, 0.8);
    transform: translateY(-2px);
  }
}

/* Small phones: fewer columns, so a card is wide enough for a short label. */
@media (max-width: 420px) {
  :root {
    --grid-cols: 4;
    --grid-gap: 5px;
  }

  .card { min-height: 40px; }

  .gridnote { height: 10.2em; padding: 6px 9px; }
}

/*
 * Phone landscape. Height is what there is least of, so the board goes wide
 * and flat and the panel gives up two of its lines.
 */
@media (max-height: 460px) and (orientation: landscape) {
  :root { --grid-cols: 7; }

  .card {
    min-height: 34px;
    font-size: clamp(0.5rem, 1.6vh, 0.68rem);
  }

  /* Landscape has no height to give. The panel keeps its own scrollbar here
     and the player scrolls it, which is the honest trade at 460px tall. */
  .gridnote { height: 4.6em; }
}

/*
 * Below 300px the shell stops being a fixed-height column and the page scrolls
 * (Standards.md §5). The panel gives up its fixed height at the same moment,
 * or the verse is still cropped inside a box on a page that can now grow.
 */
@media (max-height: 299px) {
  .gridnote {
    height: auto;
    min-height: 9.4em;
    overflow-y: visible;
  }
}

/* -------------------------------------------------------------------------- */
/* 6. Reduced motion, forced colours, more contrast, print                    */
/* -------------------------------------------------------------------------- */

/* The blanket "kill every transition" rule is in theme.css. The cards also lift
   by TRANSFORM on hover, and a transform with no duration still jumps. */
@media (prefers-reduced-motion: reduce) {
  .card:not(.is-matched):hover { transform: none; }
}

/*
 * Windows High Contrast. The system throws the palette away, which would make
 * the two halves of the pack identical and a matched pair indistinguishable
 * from an unmatched one. The tick and the cross survive — they are generated
 * text — and these bring the edges back.
 */
@media (forced-colors: active) {
  .card { border: 1px solid CanvasText; }

  .card.is-matched { outline: 3px solid Highlight; outline-offset: -3px; }
  .card.is-miss    { outline: 3px dotted CanvasText; outline-offset: -3px; }

  .card.is-matched::after,
  .card.is-miss::after { color: CanvasText; }

  .gridnote { border: 1px solid CanvasText; }
}

@media (prefers-contrast: more) {
  .card__kind { color: var(--text); }
}

@media print {
  .grid { display: none !important; }
}
