/* Self-hosted. No third-party font request from any page — see build.py HEAD. */
@font-face{font-family:"Baloo 2";src:url(/fonts/baloo2-800.woff2) format("woff2");
  font-weight:500 800;font-style:normal;font-display:swap}
@font-face{font-family:"Nunito Sans";src:url(/fonts/nunitosans-400.woff2) format("woff2");
  font-weight:400 700;font-style:normal;font-display:swap}

/* Happen Labs — happenlabs.com
   Design system v2 (A2 "toybox"). Tokens mirror the published system;
   change them there first, then here. */

:root{
  /* colour */
  --paper:#FFFDF7; --raised:#FFFFFF;
  --ink:#2A2438; --muted:#6B6480; --rule:#E4DFD2; --focus:#3A6EA8;
  --game-ink:#2A2438;
  /* Game colours are sampled from each title's app icon, so the site matches
     the store. Each game declares its own text colour: a saturated brand colour
     cannot be assumed to take dark text. CI asserts each pair clears 4.5:1. */
  --moodoku:#009CFC;  --moodoku-ink:#2A2438;   /* 5.1:1 */
  --jigsawed:#CC009C; --jigsawed-ink:#FFFFFF;  /* 5.2:1 */
  --held-a:#A98EE0;   --held-a-ink:#2A2438;    /* 5.5:1 */
  --held-b:#86CC57;   --held-b-ink:#2A2438;    /* 7.9:1 */
  --vpd:#7DAEFF;      --vpd-ink:#2A2438;       /* 6.7:1 */
  --deuces:#FF9EC4;   --deuces-ink:#2A2438;    /* 7.8:1 */
  /* spacing */
  --s1:4px; --s2:8px; --s3:16px; --s4:24px; --s5:40px; --s6:64px;
  /* shape */
  --r-card:22px; --r-control:11px; --r-pill:999px;
  /* type */
  --display:"Baloo 2", system-ui, -apple-system, sans-serif;
  --body:"Nunito Sans", system-ui, -apple-system, "Segoe UI", sans-serif;

  box-sizing:border-box;
  padding-top:env(safe-area-inset-top,0px);
  padding-bottom:env(safe-area-inset-bottom,0px);
}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --paper:#211D2B; --raised:#2B2638; --ink:#F6F2EA;
    --muted:#A79FBC; --rule:#3A3348; --focus:#9CC0EA;
  }
}
:root[data-theme="dark"]{
  --paper:#211D2B; --raised:#2B2638; --ink:#F6F2EA;
  --muted:#A79FBC; --rule:#3A3348; --focus:#9CC0EA;
}

*,*::before,*::after{box-sizing:inherit}
html{scroll-padding-top:env(safe-area-inset-top,0px); -webkit-text-size-adjust:100%}
body{margin:0; background:var(--paper); color:var(--ink);
  font-family:var(--body); font-size:16px; line-height:26px}
a{color:inherit}
a:focus-visible,summary:focus-visible{outline:3px solid var(--focus); outline-offset:3px}
img{max-width:100%; height:auto}
.wrap{max-width:1180px; margin:0 auto; padding:0 var(--s5)}

/* ---------- header ---------- */
.top{display:flex; align-items:center; justify-content:space-between;
  gap:var(--s4); padding:var(--s4) 0 var(--s5); flex-wrap:wrap}
.mark{font-family:var(--display); font-weight:800; font-size:26px;
  letter-spacing:-0.01em; text-decoration:none}
nav{display:flex; align-items:center; gap:var(--s4); font-weight:600; font-size:15px}
nav > a{text-decoration:none; color:var(--muted)}
nav > a:hover, nav > a[aria-current]{color:var(--ink)}
details.menu{position:relative}
details.menu summary{list-style:none; cursor:pointer; color:var(--muted); font-weight:600}
details.menu summary::-webkit-details-marker{display:none}
details.menu summary::after{content:" \25BE"}
details.menu[open] summary{color:var(--ink)}
details.menu ul{position:absolute; right:0; top:calc(100% + 10px); margin:0; padding:var(--s2);
  list-style:none; background:var(--raised); border:3px solid var(--ink);
  border-radius:var(--r-card); box-shadow:5px 5px 0 var(--ink); min-width:240px; z-index:20}
details.menu li a{display:block; padding:var(--s2) var(--s3);
  border-radius:var(--r-control); color:var(--ink); text-decoration:none}
details.menu li a:hover{background:var(--gold)}
details.menu .grouplabel{padding:var(--s2) var(--s3) var(--s1); font-size:11px; font-weight:700;
  letter-spacing:.07em; text-transform:uppercase; color:var(--muted)}
details.menu hr{border:none; border-top:2px solid var(--rule); margin:var(--s2) var(--s3)}

/* ---------- headings & prose ---------- */
h1{font-family:var(--display); font-weight:800; font-size:clamp(36px,5.2vw,52px);
  line-height:1.08; margin:0 0 var(--s4); letter-spacing:-0.015em}
h2{font-family:var(--display); font-weight:700; font-size:24px; margin:0 0 var(--s4)}
h3{font-family:var(--display); font-weight:700; font-size:19px; margin:var(--s4) 0 var(--s1)}
.hero{max-width:54ch; padding-bottom:var(--s6)}
.hero p{margin:0 0 var(--s3); font-size:19px; line-height:30px}
.hero p:last-child{margin-bottom:0; color:var(--muted)}
.body{max-width:64ch}
.body p{margin:0 0 var(--s3)}
.body p:last-child{margin-bottom:0}
.lede{font-size:19px; line-height:30px; font-weight:600}
.note{font-size:13px; color:var(--muted); font-style:italic}
main section{padding-bottom:var(--s6)}
ul.plain{max-width:64ch; padding-left:var(--s4); margin:0 0 var(--s3)}
ul.plain li{margin-bottom:var(--s2)}
dl{margin:0; max-width:64ch}
dt{font-family:var(--display); font-weight:700; font-size:19px; margin:var(--s4) 0 var(--s1)}
dt:first-of-type{margin-top:0}
dd{margin:0; color:var(--muted)}

/* ---------- cards ---------- */
.games{display:grid; grid-template-columns:1fr 1fr; gap:var(--s4);
  list-style:none; margin:0 0 var(--s6); padding:0}
.card{display:flex; flex-direction:column; background:var(--raised);
  border:3px solid var(--ink); border-radius:var(--r-card);
  box-shadow:6px 6px 0 var(--ink); overflow:hidden;
  transition:transform 110ms ease, box-shadow 110ms ease}
.card:hover{transform:translate(-2px,-2px); box-shadow:9px 9px 0 var(--ink)}
.card.held{border-color:var(--rule); box-shadow:6px 6px 0 var(--rule)}
.card.held:hover{transform:none; box-shadow:6px 6px 0 var(--rule)}
/* odd count -> first card spans both columns */
.card:first-child:nth-last-child(odd){grid-column:span 2}
/* aspect-ratio, not a fixed height: with a fixed height the card art
   stretched to 4.83:1 in single-column at the 820px breakpoint while
   being 2.86:1 on desktop, so art could not be sourced to one ratio. */
.art{aspect-ratio:5/2; border-bottom:3px solid var(--ink); position:relative;
  display:flex; align-items:center; justify-content:center}
.art img{width:132px; height:132px; border-radius:26px; position:relative;
  box-shadow:0 3px 0 rgba(42,36,56,.28)}
.card.held .art{border-bottom-color:var(--rule)}
.art::after{content:""; position:absolute; inset:0; opacity:.16;
  background-image:linear-gradient(to right,#2A2438 1.5px,transparent 1.5px),
                   linear-gradient(to bottom,#2A2438 1.5px,transparent 1.5px);
  background-size:40px 40px}
.cbody{padding:var(--s4); display:flex; flex-direction:column; gap:var(--s2); flex:1}
.chip{align-self:flex-start; background:rgba(42,36,56,.1); color:var(--muted);
  border-radius:var(--r-pill); padding:3px 11px; font-size:11px; font-weight:700;
  letter-spacing:.07em; text-transform:uppercase}
.name{font-family:var(--display); font-weight:800; font-size:30px; line-height:1.1; margin:0}
.name a{text-decoration:none}
.name a:hover{text-decoration:underline; text-underline-offset:4px}
.desc{margin:0; color:var(--muted); flex:1}

/* ---------- badges ---------- */
.badges{display:flex; gap:var(--s2); flex-wrap:wrap; margin-top:var(--s2)}
.badge{display:inline-block; background:var(--ink); color:var(--paper);
  border-radius:var(--r-control); padding:9px 15px; font-size:12px;
  font-weight:700; text-decoration:none; line-height:1.35}
.badge small{display:block; font-size:9px; font-weight:600; opacity:.7; letter-spacing:.04em}
.badge:hover{filter:brightness(1.35)}
.badge.off{background:transparent; color:var(--muted); border:2px dashed var(--rule)}
.badge.lg{padding:12px 22px; font-size:15px}
.badge.lg small{font-size:10px}

/* ---------- game page hero ---------- */
.herocard{color:var(--game-ink); border:3px solid var(--game-ink);
  border-radius:var(--r-card); box-shadow:8px 8px 0 var(--game-ink);
  padding:var(--s6) var(--s5); margin-bottom:var(--s6); position:relative; overflow:hidden}
.herocard::before{content:""; position:absolute; inset:0; opacity:.14; pointer-events:none;
  background-image:linear-gradient(to right,#2A2438 1.5px,transparent 1.5px),
                   linear-gradient(to bottom,#2A2438 1.5px,transparent 1.5px);
  background-size:40px 40px}
.herocard > *{position:relative}
.herocard .chip{display:inline-block; background:rgba(42,36,56,.16);
  color:var(--game-ink); margin-bottom:var(--s3)}
.herocard h1{font-size:clamp(48px,9vw,104px); line-height:.98;
  margin:0 0 var(--s3); letter-spacing:-0.025em}
.herocard .badge{background:#2A2438; color:#FFFDF7}
.tagline{margin:0 0 var(--s5); max-width:32ch; font-size:21px; line-height:31px; font-weight:600}

/* ---------- footer ---------- */
footer{border-top:3px solid var(--rule); padding:var(--s4) 0 var(--s6);
  display:flex; justify-content:space-between; gap:var(--s3); flex-wrap:wrap;
  font-size:14px; color:var(--muted)}
footer a{text-decoration:none; font-weight:600; margin-left:var(--s4)}
footer a:hover{color:var(--ink)}

@media (max-width:820px){
  .wrap{padding:0 var(--s4)}
  .games{grid-template-columns:1fr; max-width:520px; margin-inline:auto}
  .card:first-child:nth-last-child(odd){grid-column:auto}
  .herocard{padding:var(--s5) var(--s4)}
}


/* ---------- legal pages ---------- */
.legal{max-width:44rem}
.legal h2{font-family:var(--display); font-size:20px; margin:var(--s5) 0 var(--s3)}
.legal h2 .num{color:var(--muted); font-weight:500; margin-right:var(--s2)}
.legal h3{font-size:17px; margin:var(--s4) 0 var(--s2)}
.legal p, .legal li{margin:0 0 var(--s3)}
.legal ul, .legal ol{padding-left:var(--s4)}
.legal li{margin-bottom:var(--s2)}
.legal a{font-weight:600}
.stamp{color:var(--muted); font-size:15px; margin:0}
nav.toc{background:var(--raised); border:3px solid var(--ink); border-radius:var(--r-card);
  box-shadow:5px 5px 0 var(--ink); padding:var(--s4); margin:var(--s5) 0}
nav.toc p{font-family:var(--display); font-weight:700; margin:0 0 var(--s2); font-size:17px}
nav.toc ol{margin:0; padding-left:var(--s4); font-size:15px; line-height:1.55}
nav.toc li{margin-bottom:var(--s1)}
.tablewrap{overflow-x:auto; margin:0 0 var(--s4); border:3px solid var(--ink);
  border-radius:var(--r-card)}
.legal table{border-collapse:collapse; width:100%; font-size:15px; min-width:32rem}
.legal th,.legal td{text-align:left; vertical-align:top; padding:var(--s2) var(--s3);
  border-bottom:2px solid var(--rule)}
.legal th{font-weight:700; background:var(--paper)}
.legal tr:last-child td{border-bottom:none}
.callout{border-left:4px solid var(--rule); padding-left:var(--s3); color:var(--muted)}
.notice{border:3px solid var(--ink); border-radius:var(--r-card); background:var(--raised);
  box-shadow:5px 5px 0 var(--ink); padding:var(--s4); margin:0 0 var(--s5)}
.notice p:last-child{margin-bottom:0}
@media print{ .top, nav.toc, footer{display:none} .wrap{max-width:none; padding:0} }

/* Visually hidden, still in the accessibility tree. Used for held cards,
   whose visible name is an em dash and means nothing read aloud. */
.vh{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
    clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}

/* Nav separator. Was <li><hr></li>, which is an empty item in the a11y tree. */
.menu ul li.sep{border-top:1px solid var(--rule);margin-top:var(--s2);padding-top:var(--s2)}

/* A pending badge should read as deliberate, not unfinished. */
.badge.off{background:transparent;color:var(--muted);border:2px dashed var(--rule)}

/* Banner cards: the image fills the art box and replaces the colour field,
   the centred icon and the lattice. The lattice at 16% over flat colour is
   texture; over rendered art it reads as dirt. */
.art.banner img.bannerimg{width:100%;height:100%;object-fit:cover;
  border-radius:0;box-shadow:none;display:block}
.art.banner::after{display:none}

/* Card header: app icon beside the chip and title. */
.chead{display:flex; gap:var(--s3); align-items:center}
.cicon{width:76px; height:76px; border-radius:18px; flex:none; display:block;
  box-shadow:0 3px 0 rgba(42,36,56,.34)}
.cmeta{display:flex; flex-direction:column; gap:var(--s1); min-width:0}
