/* ------------------------------------------------------------------
   Shelf & Table - shared stylesheet
   One file for the whole site. No build step. Edit here, not per page.

   Palette and type are the collection page's: card room green, sand text,
   brass accent, Archivo / IBM Plex Sans / IBM Plex Mono. The shelf at
   /shelves/chris is generated by build-public.py and carries its own copy
   of these tokens, so the two must stay in step by hand. If you change a
   colour here, change it in the private collection source too.
------------------------------------------------------------------ */

:root {
  /* Card room green. A felt table is literally green, so the ground explains
     itself, and it puts distance between this and every other dark navy site. */
  --felt:      #13241D;
  --felt-deep: #081310;
  --felt-hi:   #1D3529;
  --sand:      #EFE8D8;
  --sand-dim:  #CEC5AE;
  --ink:       #07110D;
  --chip:      #5E9E8E;
  --brass:     #C98A3F;
  --sage:      #7A8F81;
  /* the table top, lit from the near edge. Kept as tokens rather than baked
     into the gradient so the whole palette can be swapped in one place. */
  --table-hi:  #1D3529;
  --table-lo:  #081310;

  /* the shelf board, lit along its front edge. Warm grey, not cool: a cool
     grey plank reads blue against green. */
  --board-hi:  #A8AC9C;
  --board-mid: #7E866F;
  --board-lo:  #4F5749;
  --board-off-hi: #48524A;   /* an empty shelf, unlit */
  --board-off-lo: #2F3830;

  /* everything that sits under or behind: shadows, sunken inputs */
  --well:      7, 17, 13;

  --line:      rgba(239,232,216,.15);
  --line-hi:   rgba(239,232,216,.28);
  /* dashed outlines have to carry further than a solid hairline to read */
  --line-dash: rgba(239,232,216,.38);

  /* spine fills. Mid-tones, all legible with ink text on top. */
  --spine-brass: #C9793F;
  --spine-chip:  #5B8FB9;
  --spine-moss:  #6E9E7F;
  --spine-gold:  #C9A227;
  --spine-plum:  #9E6E8E;

  --gap: 16px;
  --rail-h: 8px;
}

* { box-sizing: border-box; }

/* the gradient is viewport-fixed, so anything it does not paint has to be
   dark already or a long page flashes white past the fold */
html { -webkit-text-size-adjust: 100%; background: var(--felt-deep); }

body {
  margin: 0;
  padding: 0 0 64px;
  background:
    radial-gradient(120% 80% at 50% -10%, var(--felt-hi) 0%, var(--felt) 42%, var(--felt-deep) 100%);
  background-attachment: fixed;
  color: var(--sand);
  font-family: "IBM Plex Sans", system-ui, sans-serif;
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

.wrap {
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 clamp(20px, 3vw, 56px);
}

/* ---------- masthead ---------- */

.masthead { padding: 52px 0 26px; }
.masthead--sub { padding-bottom: 20px; }

/* The landing masthead is centred; every other page keeps its left edge,
   because those pages open with a breadcrumb bar and a centred title above a
   left-aligned crumb trail reads as a mistake. :not() rather than a second
   class so the markup does not have to know. */
.masthead:not(.masthead--sub) { text-align: center; }
.masthead:not(.masthead--sub) .standfirst { margin-left: auto; margin-right: auto; }

.wordmark {
  font-family: "Archivo", system-ui, sans-serif;
  font-weight: 800;
  font-size: clamp(30px, 6vw, 66px);
  line-height: 1.02;
  letter-spacing: -0.035em;
  margin: 0;
  color: var(--sand);
  text-transform: uppercase;
}

.wordmark a { color: inherit; text-decoration: none; }

.wordmark .amp {
  font-family: "IBM Plex Mono", monospace;
  font-weight: 400;
  font-size: 0.46em;
  vertical-align: 0.28em;
  margin: 0 0.14em;
  color: var(--brass);
}

.standfirst {
  margin: 18px 0 0;
  max-width: 42ch;
  font-size: clamp(1rem, 2vw, 1.15rem);
  color: var(--sand-dim);
}

.standfirst--wide { max-width: 56ch; }

/* ---------- breadcrumb ---------- */

.topbar {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  padding-top: 28px;
}

.crumbs {
  font-family: "IBM Plex Mono", monospace;
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--sage);
  margin: 0;
}

.crumbs a { color: var(--sand-dim); text-decoration: none; border-bottom: 1px solid var(--line); }
.crumbs a:hover { color: var(--sand); border-color: var(--sand-dim); }
.crumbs .sep { padding: 0 0.5rem; opacity: 0.45; }

.page-title {
  font-family: "Archivo", system-ui, sans-serif;
  font-weight: 800;
  font-size: clamp(28px, 5.2vw, 58px);
  line-height: 1.04;
  letter-spacing: -0.035em;
  text-transform: uppercase;
  margin: 22px 0 0;
}

/* ---------- section furniture ---------- */

.section { padding-bottom: clamp(40px, 6vw, 72px); }

.section-head {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  border-top: 1px solid var(--line);
  padding-top: 14px;
  margin-bottom: 28px;
  flex-wrap: wrap;
}

.section-head h2 {
  font-family: "Archivo", system-ui, sans-serif;
  font-weight: 800;
  font-size: clamp(20px, 3.2vw, 30px);
  letter-spacing: -0.025em;
  text-transform: uppercase;
  margin: 0;
}

.section-head h2 a { color: inherit; text-decoration: none; }
.section-head h2 a:hover { color: var(--brass); }

.section-head .gloss {
  font-family: "IBM Plex Mono", monospace;
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--sage);
}

.prose { max-width: 62ch; color: var(--sand-dim); }
.prose h2 {
  font-family: "Archivo", system-ui, sans-serif;
  font-weight: 600;
  font-size: 18px;
  letter-spacing: -0.01em;
  color: var(--sand);
  margin: 32px 0 8px;
}
.prose p { margin: 0 0 14px; }
.prose a { color: var(--sand); text-decoration-color: var(--line-hi); text-underline-offset: 3px; }
.prose a:hover { color: var(--brass); }

/* ---------- the split: tables left, shelves right ---------- */

.split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(28px, 4vw, 56px);
  align-items: start;
}

@media (max-width: 900px) {
  .split { grid-template-columns: minmax(0, 1fr); gap: 40px; }
}

.col { min-width: 0; }

/* ---------- a shelf: a board with a row of spines standing on it ---------- */

.shelves { display: grid; grid-template-columns: minmax(0, 1fr); gap: 26px; }

.shelfunit {
  display: block;
  min-width: 0;
  text-decoration: none;
  color: inherit;
  transition: transform .18s ease;
}

.shelfunit:hover, .shelfunit:focus-visible { transform: translateY(-3px); }
.shelfunit:focus-visible { outline: 2px solid var(--brass); outline-offset: 6px; }

/* one board of a shelving unit: boxes on top, plank underneath */
.shelf-row + .shelf-row { margin-top: 14px; }

.books {
  display: flex;
  min-width: 0;
  align-items: flex-end;
  gap: 3px;
  height: 112px;
  padding: 0 10px;
}

/* a box standing on its edge. Thick, because game boxes are. */
.box {
  position: relative;
  flex: 0 1 auto;
  min-width: 6px;
  align-self: flex-end;
  height: var(--h, 80%);
  width: var(--w, 24px);
  background: var(--c, var(--brass));
  border-radius: 2px 2px 0 0;
  box-shadow: inset -3px 0 0 rgba(var(--well), .30),
              inset 0 0 0 1px rgba(var(--well), .22),
              inset 0 3px 0 rgba(255,255,255,.10);
}

/* the printed band across a box side, which is what separates a game box
   from a paperback at a glance */
.box::after {
  content: "";
  position: absolute;
  left: 0; right: 3px;
  top: 34%;
  height: 15%;
  background: rgba(255,255,255,.15);
  border-top: 1px solid rgba(var(--well), .18);
  border-bottom: 1px solid rgba(var(--well), .18);
}

.box.lean { transform-origin: bottom right; transform: rotate(7deg); }

/* boxes lying flat, stacked. The other half of every real game shelf. */
.stack {
  display: flex;
  flex-direction: column-reverse;
  gap: 2px;
  flex: 0 1 auto;
  min-width: 10px;
  width: var(--w, 56px);
  align-self: flex-end;
}

.stack i {
  display: block;
  height: 15px;
  border-radius: 2px;
  background: var(--c, var(--brass));
  box-shadow: inset 0 1px 0 rgba(255,255,255,.16),
              inset 0 -2px 0 rgba(var(--well), .30),
              inset 0 0 0 1px rgba(var(--well), .20);
}

.board {
  height: 9px;
  border-radius: 2px;
  background: linear-gradient(180deg, var(--board-hi) 0%, var(--board-mid) 55%, var(--board-lo) 100%);
  box-shadow: 0 8px 18px -10px rgba(0,0,0,.95);
}

/* the front edge of the board, so it reads as a plank rather than a line */
.board-edge {
  height: 4px;
  margin: 0 3px;
  border-radius: 0 0 2px 2px;
  background: rgba(var(--well), .55);
}

.plate {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  padding-top: 12px;
}

.plate-name {
  font-family: "Archivo", system-ui, sans-serif;
  font-weight: 800;
  font-size: 19px;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  color: var(--sand);
}

.shelfunit:hover .plate-name { color: var(--brass); }

.plate-count {
  font-family: "IBM Plex Mono", monospace;
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--sage);
}

/* an empty shelf: the board is there, nothing is on it */
.shelfunit.is-open .books {
  height: 76px;
  border: 1px dashed var(--line-dash);
  border-bottom: 0;
  border-radius: 3px 3px 0 0;
}

.shelfunit.is-open .board { background: linear-gradient(180deg, var(--board-off-hi) 0%, var(--board-off-lo) 100%); }
.shelfunit.is-open .plate-name { color: var(--sage); font-weight: 600; }
.shelfunit.is-open:hover .plate-name { color: var(--sand-dim); }

/* The invitation, set inside the empty shelf it is inviting someone onto.
   Same voice as .rail-note, which it replaced: mono, small, quiet. The inner
   <span> is the call to action; it cannot be an <a> because the whole unit
   already is one. */
.shelf-invite {
  font-family: "IBM Plex Mono", monospace;
  font-size: 11px;
  letter-spacing: 0.1em;
  line-height: 1.7;
  color: var(--sage);
  margin: 12px 0 0;
  max-width: 44ch;
}

.shelf-invite span { color: var(--sand-dim); border-bottom: 1px solid var(--line); }
.shelfunit:hover .shelf-invite span { color: var(--brass); border-color: var(--brass); }

.rail-note {
  font-family: "IBM Plex Mono", monospace;
  font-size: 11px;
  letter-spacing: 0.1em;
  line-height: 1.7;
  color: var(--sage);
  margin: 18px 0 0;
}

.rail-note a { color: var(--sand-dim); text-decoration: none; border-bottom: 1px solid var(--line); }
.rail-note a:hover { color: var(--brass); border-color: var(--brass); }

/* ---------- a table: seen from above, four seats around it ---------- */

.tables { display: grid; grid-template-columns: minmax(0, 1fr); gap: 34px; }

.tableunit { display: grid; gap: 18px; }

.tabletop {
  position: relative;
  width: 100%;
  /* a table drawn much bigger than this stops reading as a table and starts
     reading as a background */
  max-width: 520px;
  aspect-ratio: 1;
  container-type: inline-size;
  /* rotating a full-size seat box grows its bounding rect past the square,
     which pushes the page sideways. Nothing visible sits out there, so clip. */
  overflow: hidden;
}

/* One seat box per person, each the full square, each rotated a quarter turn.
   The person is drawn at the top of that box, so rotating the box walks them
   round to the middle of the next edge, still facing the table.

   Not translate: a percentage translate resolves against the element's own
   size, not the container, so the seats would barely leave the middle. */
.seat {
  position: absolute;
  inset: 0;
  transform: rotate(var(--a));
  pointer-events: none;
}

/* shoulders behind, head on top: an overhead person in two shapes */
.seat::before,
.seat::after {
  content: "";
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  background: var(--sage);
}

/* shoulders sit behind, away from the table */
.seat::before {
  width: 20%;
  height: 9%;
  top: 5.5%;
  border-radius: 46% 46% 28% 28%;
  opacity: .38;
}

/* the head is nearer the table, and lighter, so it reads as a head */
.seat::after {
  width: 10.5%;
  aspect-ratio: 1;
  top: 8.5%;
  border-radius: 50%;
  background: var(--sand-dim);
}

.surface {
  position: absolute;
  inset: 22%;
  border-radius: 10px;
  background:
    radial-gradient(120% 100% at 50% 22%, var(--table-hi) 0%, var(--felt) 58%, var(--table-lo) 100%);
  box-shadow: inset 0 0 0 1px var(--line-hi),
              inset 0 0 40px rgba(0,0,0,.55),
              0 18px 34px -18px rgba(0,0,0,1);
  display: grid;
  place-items: center;
  padding: 9%;
  text-align: center;
}

/* the accent edge of the table top */
.surface::before {
  content: "";
  position: absolute;
  inset: -6px;
  border-radius: 13px;
  border: 3px solid var(--accent, var(--brass));
  opacity: .85;
}

.surface-inner { display: grid; gap: 3cqi; justify-items: center; }

.tablename {
  font-family: "Archivo", system-ui, sans-serif;
  font-weight: 800;
  font-size: clamp(12px, 4.3cqi, 19px);
  line-height: 1.06;
  letter-spacing: -0.025em;
  text-transform: uppercase;
  margin: 0;
  color: var(--sand);
  max-width: 11ch;
}

.tablewhere {
  font-family: "IBM Plex Mono", monospace;
  font-size: clamp(8px, 2.1cqi, 10px);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent, var(--brass));
}

.tablenext {
  margin: 0;
  display: grid;
  gap: 1cqi;
  border-top: 1px solid var(--line);
  padding-top: 3cqi;
  max-width: 22ch;
}

.tablenext dt {
  font-family: "IBM Plex Mono", monospace;
  font-size: clamp(7px, 1.9cqi, 9px);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--sage);
}

.tablenext dd {
  margin: 0;
  font-family: "IBM Plex Mono", monospace;
  font-size: clamp(9px, 2.5cqi, 12px);
  line-height: 1.35;
  color: var(--sand);
}

/* an empty table: nobody seated, nothing scheduled */
.tableunit.is-open .surface {
  background: none;
  box-shadow: inset 0 0 0 1px var(--line);
}

.tableunit.is-open .surface::before { border-style: dashed; opacity: .6; }
.tableunit.is-open .tablename { color: var(--sand-dim); }

/* an empty table is an invitation, not the main event */
.tableunit.is-open .tabletop { max-width: 380px; }

.tableunit.is-open .seat::before,
.tableunit.is-open .seat::after {
  background: none;
  border: 1px dashed var(--line-dash);
}

.tableblurb { margin: 0; color: var(--sand-dim); }

/* ---------- shared card furniture, used under a table ---------- */

.panel .table-top {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 14px;
  flex-wrap: wrap;
}

.panel p { margin: 0; color: var(--sand-dim); max-width: 54ch; }

.panel {
  background: var(--felt);
  border-radius: 4px;
  border-left: 8px solid var(--accent, var(--brass));
  padding: clamp(18px, 2.6vw, 26px);
  box-shadow: inset 0 0 0 1px var(--line),
              0 10px 22px -14px rgba(0,0,0,.9);
  display: grid;
  gap: 16px;
}

/* ---------- controls: pills, as on the collection page ---------- */

.actions { display: flex; flex-wrap: wrap; gap: 8px; }

.btn {
  font-family: "IBM Plex Mono", monospace;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 9px 15px;
  border-radius: 999px;
  border: 1px solid var(--line);
  color: var(--sand-dim);
  background: transparent;
  text-decoration: none;
  cursor: pointer;
  transition: .15s;
}

.btn:hover, .btn:focus-visible { border-color: var(--sand-dim); color: var(--sand); }
.btn:focus-visible { outline: 2px solid var(--brass); outline-offset: 3px; }

.btn-solid {
  background: var(--accent, var(--brass));
  border-color: var(--accent, var(--brass));
  color: var(--ink);
  font-weight: 600;
}

.btn-solid:hover, .btn-solid:focus-visible {
  background: var(--sand); border-color: var(--sand); color: var(--ink);
}

/* ---------- signup ---------- */

.signup { display: grid; gap: 10px; }

.signup-label {
  font-family: "IBM Plex Mono", monospace;
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--sage);
}

.signup-row { display: flex; gap: 8px; flex-wrap: wrap; }

.signup input {
  flex: 1 1 200px;
  min-width: 0;
  font-family: "IBM Plex Sans", sans-serif;
  font-size: 15px;
  padding: 10px 14px;
  border-radius: 999px;
  background: rgba(var(--well), .55);
  border: 1px solid var(--line);
  color: var(--sand);
}

.signup input::placeholder { color: var(--sage); }
.signup input:focus-visible { outline: none; border-color: var(--brass); }

.signup-msg {
  font-family: "IBM Plex Mono", monospace;
  font-size: 11px;
  min-height: 1.2em;
  color: var(--brass);
}

.signup-fine {
  font-family: "IBM Plex Mono", monospace;
  font-size: 10px;
  letter-spacing: 0.04em;
  line-height: 1.6;
  color: var(--sage);
  margin: 0;
  max-width: 52ch;
}

.signup-fine a { color: var(--sage); }
.signup-fine a:hover { color: var(--sand-dim); }

/* the meetup line, for where it sits outside the table rather than on it */
.next {
  display: none;
  gap: 14px;
  align-items: baseline;
  flex-wrap: wrap;
  font-family: "IBM Plex Mono", monospace;
  font-size: 13px;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  padding: 12px 0;
  margin: 0;
}

.next dt {
  color: var(--accent, var(--brass));
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-size: 10px;
  margin: 0;
}

.next dd { margin: 0; color: var(--sand); }

/* ---------- facts strip ---------- */

.facts {
  display: flex;
  flex-wrap: wrap;
  gap: 0;
  margin: 0 0 30px;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.facts > div {
  padding: 14px 24px 14px 0;
  margin-right: 24px;
  border-right: 1px solid var(--line);
  flex: 1 1 auto;
}

.facts > div:last-child { border-right: 0; margin-right: 0; }

.facts dt {
  font-family: "IBM Plex Mono", monospace;
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--sage);
  margin: 0 0 4px;
  order: 2;
}

.facts dd {
  margin: 0 0 2px;
  font-family: "Archivo", system-ui, sans-serif;
  font-weight: 800;
  font-size: 22px;
  letter-spacing: -0.02em;
  line-height: 1.2;
}

.facts > div { display: flex; flex-direction: column; }

/* ---------- schedule ---------- */

.schedule { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--line); }

.schedule li {
  display: flex;
  gap: 18px;
  align-items: baseline;
  flex-wrap: wrap;
  padding: 14px 0;
  border-bottom: 1px solid var(--line);
}

.schedule .when {
  font-family: "IBM Plex Mono", monospace;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--brass);
  flex: 0 0 14rem;
}

.schedule .what { font-weight: 600; color: var(--sand); }
.schedule .note { color: var(--sage); font-size: 14px; width: 100%; }
.schedule .actions { width: 100%; margin-top: 10px; }
.schedule .btn { padding: 7px 12px; font-size: 10px; }

/* the generated Facebook post, on the cross-post panel */
.posttext {
  width: 100%;
  font-family: "IBM Plex Mono", monospace;
  font-size: 12px;
  line-height: 1.6;
  color: var(--sand);
  background: rgba(var(--well), .55);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 14px;
  resize: vertical;
  margin: 0 0 16px;
}

.posttext:focus-visible { outline: none; border-color: var(--brass); }

/* ---------- callout ---------- */

.callout {
  border: 1px dashed var(--line-dash);
  border-radius: 4px;
  padding: clamp(20px, 3vw, 28px);
  max-width: 62ch;
}

.callout h3 {
  font-family: "Archivo", system-ui, sans-serif;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: -0.02em;
  font-size: 17px;
  margin: 0 0 10px;
}

.callout p { margin: 0 0 16px; color: var(--sand-dim); }

/* ---------- footer ---------- */

footer {
  border-top: 1px solid var(--line);
  padding: 20px 0 0;
  display: flex;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  font-family: "IBM Plex Mono", monospace;
  font-size: 10px;
  letter-spacing: 0.16em;
  color: var(--sage);
  text-transform: uppercase;
}

footer a { color: var(--sand-dim); text-decoration: none; border-bottom: 1px solid var(--line); }
footer a:hover { color: var(--sand); border-color: var(--sand-dim); }

footer nav { display: flex; gap: 16px; flex-wrap: wrap; }

/* ---------- narrow screens ---------- */

@media (max-width: 700px) {
  /* a shelf gets shorter, not narrower: the boxes already flex to fit */
  .books { height: 88px; padding: 0 6px; }
  .stack i { height: 12px; }
  .schedule .when { flex: 1 1 100%; }
  .facts > div { border-right: 0; margin-right: 0; flex-basis: 45%; }
}

/* Below this the table drawing is too small to hold its own text, so the
   meetup details come out of the middle and sit underneath it instead. */
@media (max-width: 430px) {
  .tabletop { max-width: 270px; margin: 0 auto; }
  .surface { padding: 9%; }
  .tablenext { display: none; }
  .tableunit .next { display: flex; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}
