/* The board's own look: the viewport, the plane, the grid, the tiles, the marks,
   the open-edge squares. Shared by the game page and any page that shows a saved
   board (shared games, a board page), so a board looks like a board everywhere.
   Colour comes from the page: --accent, --accent-ink, --bad are expected on :root,
   with fallbacks here so an unstyled page still renders sanely.

   ONE COPY, FOR EVERY GAME (README, "One shared/"). Klondike and relay kept
   hand-synced forks of this file; everything they actually agreed on is here, and each
   game's own board.css now holds only what is its own -- klondike's hint glow, relay's
   seat marks and its closed-board curtain. A page links this one first, then its game's:
       <link rel="stylesheet" href="/shared/board.css">
       <link rel="stylesheet" href="board.css">
   Order matters only where a game overrides a rule here, which today none of them do. */

.boardview { position: relative; overflow: hidden; --cell: 56px; }
.boardview .plane {
  position: absolute; left: 0; top: 0; width: 0; height: 0; transform-origin: 0 0;
}
/* The dots are white on the game's dark table. A page that frames a board on a LIGHT
   ground (shared-games.html) must set --grid-dot to something dark, or the grid
   disappears -- the dot colour and the frame colour move together, and neither works
   alone. */
.boardview .grid {
  position: absolute; pointer-events: none;
  background-image: radial-gradient(circle, var(--grid-dot, rgba(255,255,255,.085)) 1.4px, transparent 1.6px);
  background-size: var(--cell) var(--cell);
  background-position: calc(var(--cell) / -2) calc(var(--cell) / -2);
}
.boardview .ghost {
  position: absolute; width: var(--cell); height: var(--cell);
  border-radius: 10px; box-sizing: border-box;
  border: 2px dashed rgba(242, 201, 76, .55);
  background: rgba(242, 201, 76, .07);
  display: none; pointer-events: none;
}
/* Over a letter, when the word can open up and take the tile. */
.boardview .ghost.insert {
  border-style: solid;
  border-color: rgba(242, 201, 76, .9);
  background: rgba(242, 201, 76, .22);
}

/* ---- open edges, lit one at a time when the score is tapped ---- */
.boardview .edges { position: absolute; left: 0; top: 0; pointer-events: none; }
.boardview .edge {
  position: absolute; width: var(--cell); height: var(--cell);
  box-sizing: border-box; border-radius: 10px;
  border: 2px solid rgba(242, 201, 76, .7);
  background: rgba(242, 201, 76, .12);
  display: flex; align-items: center; justify-content: center;
  font: 700 17px/1 system-ui, sans-serif; color: var(--accent, #f2c94c);
  opacity: 0;
}

/* ---- peer marks, where a co-op board's other hands are holding ----
   A remote player who lifts a tile off the shared board leaves an empty cell that
   is theirs for the moment, and this layer paints that cell in their colour so the
   owner watches a hand at work instead of a tile that blinked out. The colour is
   the player's own, handed in per mark as --mark (set inline in boardview.js), so
   nothing here fixes a hue -- one rule dresses every player. Like .edges it is a
   full-plane overlay that never eats a board tap, and each mark is a cell-sized
   box placed by the inline left/top, sitting on an empty cell under the tiles. The
   wash is faint and the border soft so a live board stays readable, and a slow
   breath of opacity says the cell is held right now rather than merely coloured. */
.boardview .peers { position: absolute; left: 0; top: 0; pointer-events: none; }
.boardview .peer-mark {
  position: absolute; width: var(--cell); height: var(--cell);
  box-sizing: border-box; border-radius: 10px; pointer-events: none;
  border: 2px dashed var(--mark, #7c5cd6);
  background: color-mix(in srgb, var(--mark, #7c5cd6) 18%, transparent);
  display: flex; align-items: flex-start; justify-content: flex-end;
  padding: 3px 4px;
  font: 700 12px/1 system-ui, sans-serif; color: var(--mark, #7c5cd6);
  animation: peer-breathe 1.5s ease-in-out infinite;
}
/* A held cell breathes -- a gentle rise and fall of opacity, not a flash -- so it
   reads as an active hand without pulling the eye off the player's own board. */
@keyframes peer-breathe {
  0%, 100% { opacity: .55; }
  50%      { opacity: 1; }
}

/* A hand's name chip in the co-op bar pulses a soft ring in that person's colour (--chip) while
   they are holding a tile -- board or tray. This is the "they are working right now" signal that
   works even for a tile lifted from the tray, which has no board cell to light. */
.coop-chip.holding { animation: coop-hold 1.25s ease-in-out infinite; }
@keyframes coop-hold {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--chip, #888) 60%, transparent); }
  70%  { box-shadow: 0 0 0 6px color-mix(in srgb, var(--chip, #888) 0%, transparent); }
  100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--chip, #888) 0%, transparent); }
}

/* A tray slot a peer is holding a tile from. It sits in the tray flow at the tile's shared slot
   (applyCoop keeps the id order), the same width feel as a tile, named in the peer's colour
   (--chip) and breathing like a board mark, so the slot stays put and says who took it until the
   tile comes back down. pointer-events off so it never eats a tap in the tray. */
.rack-hold {
  align-self: center; box-sizing: border-box; pointer-events: none;
  min-height: 46px; display: inline-flex; align-items: center; justify-content: center;
  padding: 0 11px; border-radius: 10px; white-space: nowrap;
  border: 2px dashed var(--chip, #888);
  background: color-mix(in srgb, var(--chip, #888) 20%, transparent);
  color: var(--chip, #888); font: 700 12.5px/1 system-ui, sans-serif;
  animation: peer-breathe 1.5s ease-in-out infinite;
}

/* ---- the tile ---- */
.tile {
  --t: 50px;
  position: relative;
  width: var(--t); height: var(--t);
  border-radius: calc(var(--t) * .17);
  box-sizing: border-box;
  display: flex; align-items: center; justify-content: center;
  background:
    radial-gradient(130% 100% at 28% 18%, #ffffff 0%, #fbf8f0 40%, #ece5d3 100%);
  box-shadow:
    inset 0 2px 1.5px rgba(255, 255, 255, .95),
    inset 1.5px 0 1.5px rgba(255, 255, 255, .5),
    inset 0 -3px 4px rgba(150, 133, 96, .38),
    inset -2px 0 3px rgba(150, 133, 96, .16),
    0 1px 2px rgba(0, 0, 0, .45),
    0 3px 7px rgba(0, 0, 0, .3);
  font: 700 calc(var(--t) * .56)/1 Georgia, 'Times New Roman', serif;
  color: #2e2517;
  text-shadow: 0 1px 0 rgba(255, 255, 255, .55);
  touch-action: none; cursor: grab;
}
.boardview .plane .tile { --t: 52px; position: absolute; left: 2px; top: 2px; }

.tile.lift {
  cursor: grabbing;
  box-shadow:
    inset 0 2px 1.5px rgba(255, 255, 255, .95),
    inset 0 -3px 4px rgba(150, 133, 96, .38),
    0 10px 14px rgba(0, 0, 0, .45),
    0 22px 40px rgba(0, 0, 0, .35);
}
/* .binbound: the held tile is over the dump bin. It shares the red of .bad
   because the message is the same colour of warning -- let go and this tile is
   gone -- and it is the one thing always visible above the finger. */
.tile.bad, .tile.binbound { color: var(--bad, #e05252); text-shadow: 0 1px 0 rgba(255,255,255,.4); }
.tile.bad::after, .tile.binbound::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit;
  box-shadow: inset 0 0 0 2.5px rgba(224, 82, 82, .8);
}
.tile.stray::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit;
  box-shadow: inset 0 0 0 2.5px rgba(242, 201, 76, .8);
}
/* ---- a whole connected cluster, grabbed by a long press to move as one ----
   The set rides up together like a single lifted tile, ringed so the player can see
   exactly which tiles will travel. .nodrop is where they cannot land -- a cell already
   taken by a tile outside the set -- and it wears the same red as a held tile over the bin. */
.tile.grouplift {
  cursor: grabbing;
  box-shadow:
    inset 0 2px 1.5px rgba(255, 255, 255, .95),
    inset 0 -3px 4px rgba(150, 133, 96, .38),
    0 8px 12px rgba(0, 0, 0, .4),
    0 18px 34px rgba(0, 0, 0, .32);
}
.tile.grouplift::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit;
  box-shadow: inset 0 0 0 2.5px rgba(70, 130, 200, .85);
}
.tile.grouplift.nodrop::after {
  box-shadow: inset 0 0 0 2.5px rgba(224, 82, 82, .85);
}
/* ---- the rack, while a board is being replayed ----
   A viewer has no rack of their own, and the game's is styled by #rack on the game page
   -- an id, so it cannot be borrowed. This is the same row of tiles, keyed by class like
   everything else in here, for any page that watches a board get built. Nothing in it is
   draggable: it is a picture of a hand, not a hand. */
.replayrack {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: 6px; min-height: 46px; margin: 10px 0 0; padding: 8px 6px;
  border-radius: 12px;
  background: rgba(0, 0, 0, .05);
  border: 1px solid var(--rule, rgba(0, 0, 0, .12));
}
.replayrack .tile { --t: 40px; cursor: default; }
.replayrack .tile.lift { transform: translateY(-6px) scale(1.08); }

/* ---- a helper's tile, in a co-op board's replay ----
   A co-op board is built by more than one hand. As the replay plays, a tile a HELPER placed
   (any actor other than the owner) wears a quiet violet corner-ring and a faint violet wash,
   so the owner can see whose contribution is whose. Violet is nobody else's mark here -- red
   is bad, blue is a group lift, yellow is a stray/edge, green is a re-admitted word -- so it
   reads as its own thing in both the game's dark room and the light shared-games page (the
   tile face is cream on both grounds). Uses ::before, which no other tile rule touches, so it
   never fights the ::after ring of a bad/good/stray tile. Present only on a replay's own
   tiles: a finished board is redrawn from plain cells, which never carry this class. */
.tile.helped {
  background:
    radial-gradient(130% 100% at 28% 18%, #ffffff 0%, #f6f1fb 40%, #e3d6f0 100%);
}
.tile.helped::before {
  content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  box-shadow: inset 0 0 0 2.5px rgba(124, 92, 214, .75);
}

/* ---- whose tile this is: the seat mark ----
   Co-op's question above is owner-or-helper, so one violet answers it. The other question is
   WHICH OF US, and the answer is that person's own colour, handed in as --seat rather than
   written here -- a seventh player needs no stylesheet change. Uses ::before like .helped, for
   the same reason: it never fights a bad/good/stray tile's ::after ring.

   Two pages draw it, which is why it is here rather than in relay's own sheet where it started.
   Relay's replay marks each tile with the seat that placed it (replay-ui.js onPlace, --seat from
   colorForSeat). The shared-games shelf marks a board's owner-name tiles with that member's
   `strong` tint (boardpage.js ownerMark). Same ring, same meaning, one rule. */
.tile.seatmark::before {
  content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  box-shadow: inset 0 0 0 2.5px var(--seat, transparent);
  background: color-mix(in srgb, var(--seat, transparent) 13%, transparent);
}

/* ---- a word spelled out in tiles, small ----
   A label made of the real thing. The shared-games shelf says whose board a card is by spelling
   the owner's name in tiles wearing the seat ring above.

   It is HERE and not on that page because the tile artwork is here. A second copy of that
   gradient and its six shadows, written out again at a smaller size, is precisely the drift
   this file exists to prevent -- so only --t changes and nothing else is restated. Not a board
   and not draggable: a picture of a word, the way .replayrack is a picture of a hand. */
.tileword { display: inline-flex; align-items: center; gap: 2px; vertical-align: middle; }
/* 16px, chosen against the widest thing the marker ever spells: "unclaimed" is nine tiles, and
   at 18 those nine plus a name wrapped the date onto a second line in the two-column layout,
   where a card is NARROWER than on a phone. */
.tileword .tile { --t: 16px; cursor: default; }

/* A word this board was failed on that a challenge has since let back in. Green is
   a badge, not a correction: the board failed, and the dictionary was wrong. */
.tile.good { color: #2f7a3f; text-shadow: 0 1px 0 rgba(255,255,255,.4); }
.tile.good::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit;
  box-shadow: inset 0 0 0 2.5px rgba(63, 154, 63, .85);
}

/* The Done button on the PRE-OUT Peel board: hidden outright until the board is out-ready
   (bunch empty, one connected piece, every tile down). A Peel goes out once, there is no early
   stop, so a Done that cannot go out does nothing -- and a button that does nothing should not
   be shown. main.js's updateStatus adds this class only on the pre-out Peel board; the best
   board and the timed game never carry it. (Board chrome lives on the page, but this is the one
   stylesheet the two of them share.) */
#done.preout-hidden { display: none; }

/* ---- the curtain: a board that is not yours to touch ----
   Relay shuts the board when it is not your open turn -- another seat's turn, your own before you
   have pressed Start, or a manual pause. One Wrong Word has no turns and shuts it for two other
   reasons: the game has not started, or you have handed your board on and the next one has not
   arrived. Two pages draw this mark, so it is not one game's mark (see README, "One shared/") --
   and what they draw is identical apart from which child stays visible, which is exactly the kind
   of difference a selector should not be forked over.

   WHY IT SHUTS AT ALL, in relay's words: stopping the clock has to cost you the ability to look at
   the board, or the clock means nothing -- and stated as a rule nobody reads it, so the board
   states it by shutting. The curtain is opaque and blocks pointer events, so a paused player can
   neither study nor move. Enforcement is honour-system by design (RELAY.md): a determined cheater
   can open devtools, and that is explicitly fine for a game between friends.

   `data-curtain` is the child that STAYS. Both games have one -- relay's turn indicator carries
   "Start my turn", One Wrong Word's banner carries the way back to the end screen -- and relay
   learned the hard way why it must: hiding the whole subtree left the curtain telling the player
   to press a button the curtain itself had made invisible. It sits above the curtain (z-index 40
   against 20) and keeps its pointer events, so the one control that opens the board is the one
   control the curtain never covers. The attribute is its own and not `data-control` (which means
   "do not start a pan on me", a different question), so neither can be changed for the other's
   reasons. The message is `data-shut`, set by the game. */
#board.curtain > *:not([data-curtain]) { visibility: hidden; }
#board.curtain { position: relative; pointer-events: none; }
#board.curtain > [data-curtain] { pointer-events: auto; }
#board.curtain::after {
  content: attr(data-shut);
  position: absolute; inset: 0; z-index: 20; visibility: visible;
  display: flex; align-items: center; justify-content: center;
  /* Room for a sentence: the messages run from "Ada's turn" to a whole line about handing on. */
  padding: 0 28px; box-sizing: border-box; text-align: center;
  background: rgba(12, 16, 22, .97); color: #9aa4b2;
  font: 15px/1.5 system-ui, sans-serif; letter-spacing: .02em;
}


/* ---- picking a board out of a grid of them ----
   A board is a picture; a timestamp is not. Two surfaces ask somebody to choose one of their
   finished boards and both show the letters as they were left rather than a list of dates: the
   home page's start form, where a host picks the one board a match plays forward, and One Wrong
   Word's lobby, where every seat picks their own. Different questions, one grid of cards.

   WHAT IS SHARED IS THE LAYOUT, and it is shared because getting it wrong is what keeps
   happening -- see the two notes below, both of which were found on one page and then re-typed
   onto the other. Colour and density are NOT shared: one grid is a light card on the home page's
   own palette and the other is a dark chip in a lobby. Those come in through the variables, and
   a page that sets none of them still renders as a plain light card.

   The card markup either page builds is the same three parts: .thumb (a real board, drawn by
   boardview.js), .who, .facts. `.word` is the full-width line the grid falls back to when there
   is nothing to offer. */
.boardpicker {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--pick-min, 184px), 1fr));
  gap: var(--pick-gap, 10px);
  max-height: var(--pick-max, 44vh); overflow-y: auto; padding: 3px;
  /* Rows measured from what is in them, packed at the top. Left to itself the grid shares the
     scroller's height between the rows and a squeezed card clips its own text away -- the
     scrollbar is what should absorb a fourth board. max-content, not auto: the thumb takes its
     height from its width, which a row sized any other way resolves too late and lays the next
     row over this one. */
  grid-auto-rows: max-content; align-content: start;
}
.boardpicker .pickbrd {
  /* Block, not flex: the thumb is sized by ratio, and a flex column resolves that against the
     card's height and squeezes the text out of view. */
  display: block; width: 100%; text-align: left; cursor: pointer;
  padding: 0; overflow: hidden; border-radius: var(--pick-radius, 12px); font: inherit;
  background: var(--pick-bg, #fff); color: var(--pick-ink, #3a3733);
  border: 1.5px solid var(--pick-edge, #e6e3de);
  box-shadow: var(--pick-shadow, none);
}
/* NO BACKGROUND AND NO --grid-dot ON .thumb. Both are the board look's to set (paintLook,
   shared/looks.js, and the .boardlook rules above), and a rule of this specificity would flatten
   every treatment back to a plain square -- which is the bug the home page's picker had before
   paintLook existed. Sized by ratio and capped: the ratio gives a board big enough to recognise
   where two cards sit side by side, and the cap stops a single full-width card on a phone from
   eating the screen and hiding the fact that there are more boards under it. */
.boardpicker .thumb {
  width: 100%; aspect-ratio: 5 / 4; max-height: var(--pick-thumb, 190px); pointer-events: none;
  border-bottom: 1px solid var(--pick-edge, #e6e3de);
}
.boardpicker .who {
  margin: 8px 10px 0; font: 700 14px/1.25 system-ui, sans-serif;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.boardpicker .facts {
  margin: 2px 10px 9px; font: 12.5px/1.45 system-ui, sans-serif; color: var(--pick-dim, #837e77);
}
.boardpicker .pickbrd.on {
  border-color: var(--pick-on, #f2c94c);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--pick-on, #f2c94c) 26%, transparent);
}
.boardpicker .pickbrd.on .who::after { content: ' ✓'; color: var(--pick-on, #f2c94c); }
.boardpicker .word {
  grid-column: 1 / -1; color: var(--pick-dim, #837e77); font-size: 14px; padding: 4px 1px;
}


/* ---- the look a person's boards wear ----
   The frame of a board on the shelf, in history, on a board's own page and in the start
   dialog's picker. Seven treatments, chosen and rated by the user; the list, the reasoning
   and the drawing colours are in /shared/looks.js, and paintLook() is what puts these
   classes on an element.

   WHAT EACH RULE MAY USE, and nothing else: --look-bg, --look-edge and --look-strong, set
   inline per element out of that member's tint. No hue is written here, exactly as the seat
   mark writes none -- a sixteenth colour needs no stylesheet change, and every look is drawn
   in whatever shade its owner claimed. The two dark treatments (Night, Slate) are the
   exception and say so at their rule: their GROUND is fixed ink, and the member's colour is
   the light on it.

   Each look also needs a --grid-dot, which paintLook sets inline rather than here: it is the
   one value that has to survive whatever the page around it says. site.css names the coupling
   -- "a light frame needs dark dots. Changing one without the other loses the grid."

   TWO CLASSES ON EVERY RULE (.boardlook.look-x) so these beat the single-class rule the
   owning page writes for the same element -- .thumb, .pickbrd .thumb, #boardpanel all set a
   background of their own, and this sheet is linked first. */
.boardlook {
  background: var(--look-bg);
  border-color: var(--look-edge);
  /* The frame's own depth, which the pages used to set beside their background. It is here now
     for the same reason the background is: a page rule naming either one would sit later in the
     cascade at equal specificity and quietly flatten Night's glow or Card table's stitching. A
     look with a box-shadow of its own replaces this; the three flat ones keep it. */
  box-shadow: var(--inset-shadow, inset 0 2px 6px rgba(0, 0, 0, .10));
}
/* No colour claimed and no look picked: the page's own plain frame, which is what paintFrame
   has always drawn for such a member. Not a colour -- the absence of one. --inset and
   --inset-edge are the frame variables site.css already defines for every out-of-game page.
   (Wash needs no rule of its own: the two lines above ARE the wash.) */
.boardlook.look-unclaimed {
  background: var(--inset, #e8e5e0);
  border-color: var(--inset-edge, #d5d1cb);
}

/* Card table -- deep green felt. The one look whose ground is not the member's shade: a card
   table is a card table. Their colour is the stitching, a hairline inside the edge, and the
   felt is a soft two-way weave rather than flat paint. */
.boardlook.look-table {
  background:
    repeating-linear-gradient(45deg, rgba(255,255,255,.022) 0 2px, transparent 2px 4px),
    repeating-linear-gradient(-45deg, rgba(0,0,0,.03) 0 2px, transparent 2px 4px),
    radial-gradient(120% 90% at 50% 0%, #2c6a4a 0%, #235640 55%, #1b4433 100%);
  border-color: #143528;
  /* The stitching: a bright hairline of the member's shade set in from the edge, with a rail of
     felt outside it. Bright on purpose -- at 70% of a mid-green shade on green felt the stitch was
     there and unreadable, which is a colour that is not doing its job. */
  box-shadow:
    inset 0 0 0 4px #1b4433,
    inset 0 0 0 6px color-mix(in srgb, var(--look-strong) 95%, #fff),
    inset 0 0 30px rgba(0, 0, 0, .4);
}

/* Dusk -- the tint deepening downward, like the light going out of a room. Pale at the top,
   the shade's real colour mixed in at the foot. Still a light frame, so the dots stay dark. */
.boardlook.look-dusk {
  background: linear-gradient(
    to bottom,
    color-mix(in srgb, var(--look-bg) 92%, #fff) 0%,
    var(--look-bg) 38%,
    color-mix(in srgb, var(--look-strong) 34%, var(--look-bg)) 100%);
  border-color: color-mix(in srgb, var(--look-strong) 30%, var(--look-edge));
}

/* Night -- ink, with the shade glowing around the edge of it. The ground is fixed (the tiles
   have to stay cream against something), and the member's colour is the light: a bright ring
   just inside the border and a soft bloom off it. */
.boardlook.look-night {
  background: radial-gradient(130% 100% at 50% 40%, #1b2028 0%, #12161c 70%, #0d1015 100%);
  border-color: color-mix(in srgb, var(--look-strong) 75%, #0d1015);
  /* The glow, and it has to BE a glow: a ring at full strength, then the same colour bled inward
     over a wide, soft spread. The first pass drew both at a third strength and the ink simply ate
     them -- the whole look is the shade lighting the edge of something dark. */
  box-shadow:
    inset 0 0 0 2.5px var(--look-strong),
    inset 0 0 14px 1px color-mix(in srgb, var(--look-strong) 62%, transparent),
    inset 0 0 40px 8px color-mix(in srgb, var(--look-strong) 26%, transparent);
}

/* Linen -- the tint with a woven grain through it. Two sets of hairlines at right angles,
   drawn in the shade's own edge colour so the weave is the same hue as the cloth. */
.boardlook.look-linen {
  background:
    repeating-linear-gradient(0deg,
      color-mix(in srgb, var(--look-edge) 55%, transparent) 0 1px, transparent 1px 4px),
    repeating-linear-gradient(90deg,
      color-mix(in srgb, var(--look-edge) 45%, transparent) 0 1px, transparent 1px 4px),
    var(--look-bg);
  border-color: var(--look-edge);
}

/* Slate -- cool, dark and flat, so the tiles glow off it rather than sitting on it. Fixed
   ground like Night; the member's colour is a low wash into the stone and a quiet edge, not a
   glow -- the difference between the two dark looks is exactly how loud the colour is. */
.boardlook.look-slate {
  background:
    radial-gradient(120% 80% at 50% 0%,
      color-mix(in srgb, var(--look-strong) 16%, #3a4048) 0%, #2b3036 60%, #23272c 100%);
  border-color: #1a1e22;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .07), inset 0 -14px 22px rgba(0, 0, 0, .3);
}

/* Matted -- a gallery mount. A warm neutral board with the picture window ruled twice in the
   member's shade: a hairline, a gap of mount, another hairline. The rules are inset shadows
   rather than borders because the element already has a border of its own to keep. */
.boardlook.look-matted {
  background: linear-gradient(180deg, #f2eee5 0%, #e7e2d7 100%);
  border-color: #d6d0c4;
  /* Two rules in the member's shade, a mount's width apart. Both at full strength: a "double rule"
     drawn faintly is one smudge, and the pair is the entire look. */
  box-shadow:
    inset 0 0 0 6px #f7f4ed,
    inset 0 0 0 8px var(--look-strong),
    inset 0 0 0 11px #f7f4ed,
    inset 0 0 0 12px color-mix(in srgb, var(--look-strong) 55%, #f7f4ed),
    inset 0 0 0 14px #efebe2,
    inset 0 0 10px 14px rgba(0, 0, 0, .05);
}

/* ---- the owner's tile, sitting on the frame ----
   The part of the look the user picked out and loved: a real tile in the corner carrying the
   owner's initial and wearing their colour as a seat ring. It is the same tile artwork and the
   same ring as everywhere else -- .tile.seatmark -- only placed.

   It is drawn on the PREVIEW, where a look is being offered, and not on a real board: the shelf
   card already spells the owner's name in tiles beside the board (boardpage.js ownerMark), and a
   second initial tile laid over the letters of the board itself would be a mark competing with
   the thing it marks. */
.boardlook > .lookmark {
  position: absolute; left: 8px; top: 8px; z-index: 2; pointer-events: none;
}
.boardlook > .lookmark .tile { --t: 26px; cursor: default; }
