/* Grid XI — the board, the slot row, the keyboard and full time.
 *
 * PORTED FROM gridxi-demo-v2.html, the standalone prototype the owner iterated
 * nine times. What it settled is not obvious and is worth keeping deliberately:
 *
 *   - the guess is typed INTO THE ENTRY, and the marks land on those cells. v1
 *     had a box below the board and the feedback somewhere else again, so the
 *     player had to hold the mapping between the two in their head.
 *   - the slot row under the board is the SAME state at a readable size, never
 *     a second copy of it. On a phone a 16-wide grid puts a mark in about
 *     twenty pixels; the row is where it can actually be read.
 *   - the keyboard is PER ENTRY. A letter greyed out by one answer says nothing
 *     about a different word, and colouring it globally told the player a
 *     letter was dead in a name it was not in.
 *
 * This game defines no .xic- rule and restates no token: the bar, the drawer,
 * the footer and the palette are shared/xi-chrome.css and shared/xi-tokens.css,
 * and the gates check that they stay that way.
 *
 * The colours below that are NOT tokens are the three marks — correct, present
 * and absent. They are the game's own vocabulary rather than the family's, and
 * --present and --dead are declared here for that reason.
 */
:root{ --present:#B8860B; --dead:#AAB3A8; }
:root[data-theme="dark"], :root:not([data-theme="light"]){ }
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){ --present:#C79A2E; --dead:#6E7A6D; }
}
:root[data-theme="dark"]{ --present:#C79A2E; --dead:#6E7A6D; }

/* The page's own column. The chrome owns the bar and the footer; this is the
   width the board is read at, and the same 760px the prototype settled on. */
/* THE BODY'S MARGIN, RESET LIKE EVERY GAME'S. A page that leaves it sits in
   a gutter the other five do not have; aligned_test asks all six the same
   question. The rest of the shell — the bar, the footer, .sr-only — is the
   shared layer's and is not restated here. */
/* THE FAMILY'S FACE, SAID OUT LOUD. This was `body{margin:0}` and nothing
   else, so every element that did not name a font inherited the USER AGENT's
   default — Times New Roman — while the headings, which do name var(--disp),
   came out in Barlow Condensed. The page read half condensed sans and half
   serif and nothing in the tree said why: the fonts load here, and every
   fallback chain in xi-tokens.css ends in sans-serif, so there was no failure
   to find. The cascade simply never asked.
   Measured on the live site 17 Sep 2026: getComputedStyle(document.body)
   returned "Times New Roman" for hilo, grid, whoami and ballpark, and
   "Public Sans" for the other six. aligned_test now refuses a game whose
   stylesheet does not set it, so the eleventh cannot arrive in serif. */
body{margin:0;font-family:var(--body)}
.gd-wrap{max-width:760px; margin:0 auto; padding:14px 12px 40px}

.gd-kicker{font-family:var(--disp); font-size:13px; letter-spacing:.14em;
  text-transform:uppercase; color:var(--ink-soft); margin:0}
.gd-title{font-family:var(--disp); font-weight:700; font-size:23px;
  letter-spacing:.02em; margin:2px 0 0}
.gd-sub{color:var(--ink-soft); font-size:14px; margin:4px 0 0}


.gd-ident{background:var(--card); border:1px solid var(--line); border-radius:var(--radius);
  padding:12px 14px; margin-bottom:12px}
.gd-ident .kind{font-family:var(--disp); font-size:13px; letter-spacing:.14em;
  text-transform:uppercase; color:var(--ink-soft)}
.gd-ident .title{font-family:var(--disp); font-weight:700; font-size:23px; letter-spacing:.02em}
.gd-ident .title.hidden{color:var(--ink-faint)}
.gd-hintrow{display:flex; gap:8px; margin-top:10px; flex-wrap:wrap}

.gd-budget{display:flex; align-items:center; gap:12px; margin-bottom:12px}
.gd-bar{flex:1; height:9px; background:var(--tint); border-radius:99px; overflow:hidden}
.gd-bar i{display:block; height:100%; background:var(--pitch); transition:width .25s ease}
.gd-bar.low i{background:var(--danger)}
.gd-count{font-family:var(--disp); font-weight:700; font-size:21px; min-width:78px; text-align:right}
.gd-count small{font-weight:500; color:var(--ink-faint); font-size:14px}

/* ---------- the board ---------- */
/* The family's top bar stands in for the kicker and the turns strip
   (shared/xi-matchbar.css); the title under it is the board's one clue. */
#gdKicker,.gd-budget{display:none}
.gd-boardwrap{overflow-x:auto; -webkit-overflow-scrolling:touch; margin-bottom:14px}
/* THE CROSSWORD'S BOARD (the owner, 25 Sep 2026: "look more like the
   crossword I.e. background, similar layout, boxes"). The pitch and the
   squares are shared/xi-board.css -- joined squares on the turf, the answer
   you are in tinted and the square you are typing in ringed -- and this game
   sets only their size and paints its own marks over them. */
.gd-pitch{position:relative; padding:8px; border-radius:var(--r-lg); width:max-content; margin:0 auto}
.gd-board{position:relative; z-index:1; display:grid; gap:0; width:max-content}
.gd-cell{width:var(--cs); height:var(--cs); box-sizing:border-box}
.gd-cell.on{font-size:calc(var(--cs)*.58); user-select:none}
.gd-cell .num{font-size:calc(var(--cs)*.26); line-height:1.1}
/* Once every entry's marks stay on the board, a tint alone cannot show which
   entry is selected — most of its cells are coloured. A ring survives any
   background underneath it. */
.gd-cell.ring{box-shadow:inset 0 0 0 2px rgba(255,255,255,.75)}
/* WHERE ONE WORD ENDS AND THE NEXT BEGINS.
   LEWISSKELLY is eleven letters and nothing on the grid said the name is
   Lewis-Skelly. The server sends the letter offsets where a new word starts and
   the divider sits on the LEADING edge of that cell: the left edge going
   across, the top edge going down.
   A PSEUDO-ELEMENT, NOT A BORDER AND NOT A SHADOW. A border would change the
   cell's size against the fixed --cs grid, and box-shadow is already spoken for
   twice above — .ring and .cursor both use it, so a selected cell with a break
   would lose one of the two to whichever rule won. An overlay stacks with both
   and costs the layout nothing.
   A crossing cell can carry both classes; each draws on its own entry's edge,
   so neither is wrong. Under the number badge deliberately: .n is the entry's
   label and must stay legible over it. */
.gd-cell.on.brk-l::after,
.gd-cell.on.brk-t::after{content:""; position:absolute; background:var(--ink);
  opacity:.55; border-radius:1px; pointer-events:none}
.gd-cell.on.brk-l::after{left:-1px; top:12%; bottom:12%; width:2px}
.gd-cell.on.brk-t::after{top:-1px; left:12%; right:12%; height:2px}
/* Both edges on one cell needs two boxes, and ::after is one. The left edge
   takes ::after above and the top edge takes ::before here, so a cell that
   breaks in both directions draws both. */
.gd-cell.on.brk-l.brk-t::before{content:""; position:absolute; top:-1px;
  left:12%; right:12%; height:2px; background:var(--ink); opacity:.55;
  border-radius:1px; pointer-events:none}
.gd-cell.on.brk-l.brk-t::after{left:-1px; top:12%; bottom:12%; width:2px;
  height:auto; right:auto}

/* letters the player has typed but not yet submitted */
.gd-cell.typed{color:var(--ink-soft)}
/* the marks */
.gd-cell.c{background:var(--pitch); color:#fff}
.gd-cell.p{background:var(--present); color:#fff}
.gd-cell.a{background:var(--dead); color:#fff}
.gd-cell.c .n,.gd-cell.p .n,.gd-cell.a .n{color:rgba(255,255,255,.85)}
/* proved, and permanent */
.gd-cell.conf{background:var(--pitch); color:#fff}
.gd-cell.conf .n{color:rgba(255,255,255,.85)}
/* A marked square in the answer you are in keeps its mark and shows the
   cursor as the ring alone. */
.gd-cell.active.c,.gd-cell.active.p,.gd-cell.active.a,.gd-cell.active.conf{border-right-color:transparent; border-bottom-color:transparent}

/* ---------- the slot row ---------- */
.gd-slots{display:flex; flex-wrap:wrap; gap:5px; justify-content:center;
  padding:12px; background:var(--card); border:1px solid var(--line);
  border-radius:var(--radius); margin-bottom:6px; min-height:66px; align-items:center}
.gd-slot{width:34px; height:34px; text-align:center; font-family:var(--disp); font-weight:700;
  font-size:25px; line-height:34px; border-bottom:3px solid var(--ink-faint);
  color:var(--ink); border-radius:2px 2px 0 0}
.gd-slot.empty{color:var(--ink-faint)}
/* A new word starts here: a wider gap in the answer row, as the board's
   divider is a rule between two squares. */
.gd-slot.brk{margin-left:12px}
.gd-slot.typed{color:var(--ink-soft)}
.gd-slot.cursor{border-bottom-color:var(--pitch)}
.gd-slot.c{background:var(--pitch); color:#fff; border-bottom-color:var(--pitch-deep)}
.gd-slot.p{background:var(--present); color:#fff; border-bottom-color:#8A6508}
.gd-slot.a{background:var(--dead); color:#fff; border-bottom-color:#8D958B}
.gd-slot.conf{background:var(--pitch); color:#fff; border-bottom-color:var(--pitch-deep)}
.gd-lbl{font-family:var(--disp); font-size:13px; letter-spacing:.14em;
  text-transform:uppercase; color:var(--ink-faint); text-align:center; margin:0 0 6px}
/* Ten letters must sit on one line. Wrapped, the slot row stops reading as a
   single answer and starts reading as two. */
@media (max-width:430px){
  .gd-slots{gap:3px; padding:10px 6px}
  .gd-slot{width:28px; height:30px; font-size:21px; line-height:30px}
}

/* the hidden field exists only to raise a keyboard on touch */
#field{position:absolute; opacity:0; pointer-events:none; height:1px; width:1px}

.gd-keys{display:flex; gap:8px; margin-bottom:6px}
/* THIS GAME'S buttons, not the site's. As a bare `button` it reached the
   shared bar's "Sign in", which read SIGN IN here and Sign in on every other
   game (26 Sep 2026). :where() keeps it at a bare element's weight, so every
   class rule -- the family keyboard's .osk-key among them -- still wins. */
:where(button:not([class*="xic-"])){font-family:var(--disp); font-weight:600; font-size:16px; letter-spacing:.04em;
  text-transform:uppercase; min-height:var(--tap); padding:0 16px;
  border-radius:var(--radius); border:1px solid var(--pitch);
  background:var(--pitch); color:#fff; cursor:pointer}
button.gd-ghost{background:var(--card); color:var(--ink); border-color:var(--line)}
button:disabled{opacity:.4; cursor:default}
button:focus-visible,.gd-cell.on:focus-visible,.gd-chip:focus-visible{outline:2px solid var(--pitch); outline-offset:2px}
.gd-keys button{flex:1}
.gd-msg{min-height:20px; font-size:13.5px; color:var(--ink-soft); margin-bottom:12px}
.gd-msg.warn{color:var(--danger)}

.gd-entries{display:flex; flex-wrap:wrap; gap:6px; margin-bottom:14px}
.gd-chip{font-family:var(--disp); font-weight:600; font-size:15px; letter-spacing:.03em;
  padding:6px 10px; border-radius:99px; border:1px solid var(--line);
  background:var(--card); color:var(--ink-soft); cursor:pointer; min-height:34px}
.gd-chip.sel{border-color:var(--pitch); color:var(--ink); background:#EFF4EF}
.gd-chip.done{background:var(--pitch); border-color:var(--pitch); color:#fff}

.gd-hist .g{display:flex; gap:2px; margin-bottom:3px}
.gd-hist .g b{width:26px; height:26px; display:flex; align-items:center; justify-content:center;
  font-family:var(--disp); font-weight:700; font-size:15px; border-radius:3px;
  border:1px solid var(--line); background:var(--card); color:var(--ink)}
.gd-hist .g b.c{background:var(--pitch); border-color:var(--pitch); color:#fff}
.gd-hist .g b.p{background:var(--present); border-color:var(--present); color:#fff}
.gd-hist .g b.a{background:var(--dead); border-color:var(--dead); color:#fff}
.gd-lbl{font-family:var(--disp); font-size:13px; letter-spacing:.14em; text-transform:uppercase;
  color:var(--ink-faint); margin:0 0 6px}
.gd-hist{margin-bottom:14px}
.gd-hlbl{font-family:var(--disp); font-size:13px; letter-spacing:.14em; text-transform:uppercase;
  color:var(--ink-faint); margin:0 0 6px}

/* ---------- the keyboard, one per entry ----------
   Evidence is scoped to the answer it was gathered against. A letter that is
   not in SCHMEICHEL says nothing whatever about BLOMQVIST, so each entry
   carries its own keyboard and the marks reset when you move. */
/* THE FAMILY'S KEYBOARD (shared/xi-keys.css), drawn on every device here,
   not only on touch: its keys carry this game's marks, which a physical
   keyboard cannot show. In the page's flow, not pinned to the foot. */
.gd-kbd.osk{display:block; position:static; border-top:0; background:none; padding:0; margin-bottom:16px}
.gd-kbd .osk-key.c{background:var(--pitch); border-color:var(--pitch); color:#fff}
.gd-kbd .osk-key.p{background:var(--present); border-color:var(--present); color:#fff}
.gd-kbd .osk-key.a{background:var(--dead); border-color:var(--dead); color:#fff; opacity:.75}
.gd-kbd .osk-key:disabled{opacity:.4; cursor:default}
/* NO PADDING ON A KEY. This page's own button rule above gives every button
   16px either side, and the family's keys never say otherwise because no
   other game styles bare buttons. At 31px wide the padding outgrew the key:
   the letters overlapped their neighbours and ENTER read ENT (the owner's
   iPad, 30 Sep 2026). */
.gd-kbd .osk-key{padding:0}
/* A letter proved absent cannot be pressed (game.js); it stays grey, not faded
   to nothing, so the evidence is still on the keys. */
.gd-kbd .osk-key.a:disabled{opacity:.55}
.gd-kbd{display:flex; flex-direction:column; gap:6px; margin-bottom:16px}
.gd-krow{display:flex; gap:5px; justify-content:center}
.gd-k{flex:1 1 0; min-width:0; height:50px; border-radius:6px;
  border:1px solid var(--line); background:var(--card); color:var(--ink);
  font-family:var(--disp); font-weight:700; font-size:18px; letter-spacing:.02em;
  text-transform:uppercase; cursor:pointer; padding:0;
  display:flex; align-items:center; justify-content:center}
/* Del and Guess sit on the bottom row with seven letters between them, so they
   get a share of the row rather than a fixed width — at 390px a fixed one
   pushes the last key off the screen. */
.gd-k.wide{flex:1.45 1 0; font-size:13px; letter-spacing:.04em}
.gd-k.c{background:var(--pitch); border-color:var(--pitch); color:#fff}
.gd-k.p{background:var(--present); border-color:var(--present); color:#fff}
.gd-k.a{background:var(--dead); border-color:var(--dead); color:#fff; opacity:.75}
.gd-k:disabled{opacity:.4; cursor:default}
.gd-k.go{background:var(--pitch); border-color:var(--pitch); color:#fff}
@media (max-width:430px){ .gd-k{height:46px; font-size:17px} }
/* At 360px the bottom row — Del, seven letters, Guess — still overran. The
   gaps and the two labels are what give; the 44px tap floor does not. */
@media (max-width:380px){
  .gd-krow{gap:3px}
  .gd-k{font-size:16px}
  .gd-k.wide{flex:1.3 1 0; font-size:11px; letter-spacing:0}
}

/* FULL TIME is the family's panel (shared/xi-fulltime.css); this is only its
   place under the board, and the way back to the grid on a board replayed. */
.gd-ft{margin-bottom:14px}
.gd-replay{text-align:center; margin:8px 0 0}

/* ---- THE LOCKED SCREEN ----------------------------------------------------
   The owner's ruling, 24 Sep 2026: while playing, the page is the screen and
   nothing scrolls, at every size, with the elements scaling up. This page IS
   the play screen, so it is locked once a board is up (game.js), and unlocked
   when the squares would be under 18px or the parts cannot fit.

   On a phone, one column: the title, the turns, the board in the height that
   is left (its squares sized from that box, in game.js), the answer row and
   the keys. The entry chips, the guess history and the rules step aside --
   the board is the way to pick an entry. From 900px the board fills the left
   and everything else is a column on the right, the history scrolling in
   itself. Full time takes the answer row's and the keys' place, as a panel
   that scrolls in itself; the board stays. */
body.locked{height:100vh;height:100dvh;overflow:hidden;display:flex;flex-direction:column}
body.locked>*{flex:none}
body.locked>footer{display:none}
body.locked>main.gd-wrap{flex:1 1 auto;min-height:0;width:100%;max-width:1180px;box-sizing:border-box;
  margin:0 auto;padding:6px 10px 8px;display:flex;flex-direction:column}
body.locked .gd-wrap>*{flex:none;margin-bottom:6px}
/* The title is the whole clue, so it is kept whole -- smaller, not cut. The
   turns are one line: "turns left" wrapped under the count and took 67px. */
body.locked .gd-ident{padding:4px 10px}
body.locked .gd-sub{display:none}
body.locked .gd-kicker{font-size:11px}
body.locked .gd-title{font-size:17px;line-height:1.2}
body.locked .gd-budget{margin-bottom:6px;gap:10px}
body.locked .gd-count{font-size:16px;min-width:0;white-space:nowrap}
body.locked .gd-count small{font-size:12px}
body.locked .gd-boardwrap{flex:1 1 auto;min-height:0;overflow:hidden;display:flex;align-items:center;justify-content:center}
/* The square's border inside its size, so sixteen squares of --cs are sixteen
   times --cs wide and the board is exactly what game.js sized it to. */
body.locked .gd-cell{box-sizing:border-box}
body.locked .gd-lbl,body.locked .gd-entries,body.locked .how{display:none}
/* EVERY ATTEMPT AT THE ENTRY IN HAND, on every screen (the owner, 30 Sep
   2026). In one column it sits between the answer row and the keys, a few
   rows tall and scrolling in itself, so it costs the board a fixed strip and
   never pushes the keys off the screen. It is empty until a guess is made. */
body.locked .gd-hist{display:flex;flex-direction:column;align-items:center;max-height:15vh;overflow:auto;margin-bottom:6px}
body.locked .gd-hist:empty{display:none}
body.locked .gd-wrap>.gd-entries,body.locked .gd-wrap>.gd-hist{order:1}
body.locked .gd-wrap>.gd-kbd,body.locked .gd-wrap>.gd-msg{order:2}
body.locked .gd-slots{min-height:0;padding:8px 6px}
body.locked .gd-kbd{margin-bottom:4px}
body.locked .gd-k{height:clamp(40px,5.2vh,56px)}
body.locked .gd-msg{margin-bottom:0;min-height:18px}
/* Full Time is the family's sheet over the board (data-xft-host); the keys
   and the answer row go while it is up, so the finished board has the room. */
body.locked .gd-wrap:has(#gdFullTime:not([hidden])) :is(.gd-slots,.gd-kbd,.gd-msg){display:none}

/* A TABLET UPRIGHT IS ONE COLUMN, NOT TWO. The two-column layout below was
   chosen by width alone, so a 13-inch iPad upright (1024 wide) got a board in
   a 606px column floating in the middle of the screen and a 380px column of
   keys that ran off the right edge (the owner, 30 Sep 2026: "Grid layout is
   not fit for purpose"). Upright, the board takes the full width and the
   entries come back above the keys: there is height enough for them. */
@media (min-width:700px) and (orientation:portrait){
  body.locked .gd-wrap>.gd-entries{display:flex;justify-content:center}
  body.locked .gd-hist{max-height:18vh}
  body.locked .gd-hist .g b{width:30px;height:30px;font-size:17px}
}

/* A DESK IS ONE COLUMN TOO: the board, and under it the answer row, the
   entries and the keys (the owner, 3 Oct 2026: "the clues and buttons to the
   right, it should be under the board"). The two-column layout below is for a
   phone on its side, which has width and no height. Narrower than the page,
   so a monitor's keys are a keyboard's size rather than a banner.
   ONLY WHERE THERE IS THE HEIGHT FOR IT: stacked, the title, answer row,
   keys and entries take about 560px, and the board gets what is left. At
   960px tall that is 24px squares; at 900 it was 20px against 36px in two
   columns, and at 768 it was 14px and the page had to scroll. Below 960 a
   desk keeps the two columns, and the play screen stays still. */
@media (min-width:900px) and (orientation:landscape) and (pointer:fine) and (min-height:960px){
  body.locked>main.gd-wrap{max-width:900px}
  body.locked .gd-wrap>.gd-entries{display:flex;justify-content:center;flex-wrap:wrap}
  body.locked .gd-hist{max-height:14vh}
}

@media (min-width:900px) and (orientation:landscape) and (pointer:coarse),
       (min-width:900px) and (orientation:landscape) and (pointer:fine) and (max-height:959.98px){
  body.locked>main.gd-wrap{display:grid;grid-template-columns:minmax(0,1fr) 380px;
    grid-template-rows:repeat(11,auto) minmax(0,1fr);column-gap:18px}
  /* THE BOARD LEVEL WITH THE COLUMN BESIDE IT, not floated down its middle:
     the wrap spans every row of the grid and centred the board in all of
     them, which on a desk monitor left a hundred pixels of nothing above the
     board and its top well below the title opposite (the owner, 3 Oct 2026:
     "Grid is still not fixed visually"). */
  body.locked .gd-boardwrap{grid-column:1;grid-row:2 / -1;margin:0;align-items:flex-start}
  body.locked .gd-wrap>:not(.gd-boardwrap){grid-column:2}
  /* The family's top bar across the top of both columns, as on every game. */
  body.locked .gd-wrap>#xiBar{grid-column:1 / -1;grid-row:1}
  body.locked .gd-entries{display:flex}
  body.locked .gd-hist{display:block;max-height:30vh;overflow:auto}
}
/* A TABLET ON ITS SIDE: THE CROSSWORD'S SHAPE. The board on the left with the
   answer row under it, the title, the entries and the attempts on the right,
   and the family's keyboard across the whole foot of the screen at tablet
   size -- the owner's rulings on the crossword's keys (26 Sep 2026, "far too
   small on iPad") applied here too. It was a 380px column, which made keys
   31px wide on a 13-inch screen. A phone on its side is not a tablet (under
   700 tall) and keeps the column above, which leaves the board the height,
   and so does a desk (a fine pointer): it has a real keyboard, and a drawn
   one across the foot would take the board's height for keys it never uses. */
@media (min-width:900px) and (min-height:700px) and (orientation:landscape) and (pointer:coarse){
  body.locked>main.gd-wrap{max-width:1400px;grid-template-columns:minmax(0,1fr) clamp(300px,28vw,420px);
    grid-template-rows:auto repeat(6,auto) minmax(0,1fr) auto auto}
  /* A tablet keeps the board centred over its answer row, as approved: only
     a desk's two columns needed the board brought up level. */
  body.locked .gd-boardwrap{grid-row:2 / 9;margin:0;align-items:center}
  body.locked .gd-wrap>.gd-slots{grid-column:1;grid-row:9}
  body.locked .gd-wrap>.gd-kbd{grid-column:1 / -1;grid-row:10;margin:4px 0 0}
  body.locked .gd-hist{align-items:flex-start;max-height:34vh}
  body.locked .gd-hist .g b{width:30px;height:30px;font-size:17px}
}
/* HOW TO PLAY OVER A LOCKED BOARD, as in every locked game: the bar's link
   opens it as a panel the height of the screen, "Back to the game" closes it. */
.how-back{display:none}
body.locked #how:target{display:block!important;position:fixed;inset:0;z-index:60;margin:0;max-width:none;
  overflow:auto;overscroll-behavior:contain;background:var(--paper);padding:14px 16px 40px;box-sizing:border-box}
body.locked #how:target .how-back{display:inline-flex;align-items:center;min-height:var(--tap,44px);padding:0 16px;
  margin:0 0 10px;border:1px solid var(--line);border-radius:999px;background:var(--card);color:var(--ink);
  font-family:var(--disp);font-weight:700;letter-spacing:.08em;text-transform:uppercase;text-decoration:none}
