/* Lab board (founder 2026-10-12, mockup 22-night-leads): a dark newspaper mosaic. Flat tiles, 1px lines, Newsreader
   titles, IBM Plex Mono data; no gradients, shadows or hero blocks. Every rule is scoped to this page. */
.lab-board{max-width:1440px;padding:16px 32px 0}
.lab-board :focus-visible{outline:1px solid var(--fg);outline-offset:2px}
.board-mast{display:flex;align-items:flex-end;justify-content:space-between;gap:12px;padding-bottom:12px;border-bottom:1px solid var(--line)}
.board-mast h1{font-family:var(--serif);margin-inline:0}
.mast-side{text-align:right;font:12px/1.4 var(--mono);color:var(--muted)}
.mast-links{display:flex;justify-content:flex-end;gap:16px;font-size:12.5px}
.mast-links a{display:inline-flex;align-items:center;min-height:32px;color:var(--muted)}.mast-links a:hover{color:var(--fg)}
.mast-links .mast-ranked,.mast-links .board-resume{color:var(--red)}
.board-mast{position:relative}.mast-account{display:inline-flex;align-items:center;min-height:28px;margin-bottom:4px;padding:0 9px;border:1px solid var(--muted);border-radius:3px;color:var(--fg);font-size:12.5px;white-space:nowrap}.mast-account:hover{background:var(--tile2)}.mast-account[hidden]{display:none}
.board-count{margin:2px 0 0;color:var(--fg)}
.board-bars{border-bottom:1px solid var(--line);margin-bottom:14px}
.board-bar{display:flex;align-items:center;gap:2px;padding:6px 0;font:12.5px var(--mono)}.board-bar+.board-bar{border-top:1px solid var(--line)}
.bar-label{flex:none;min-width:86px;padding-right:8px;color:var(--muted);font-size:10.5px;letter-spacing:.1em;text-transform:uppercase}
.bar-options{display:flex;align-items:center;gap:2px;min-width:0;overflow-x:auto;scrollbar-width:none;min-height:32px}
/* Paint before data (docs/design/frontend-performance.md): until the board settles, an empty grid keeps a screen of room so
   the footer does not jump when the cards arrive; the filter rows keep their button height (min-height above). */
html[data-page-loading=true] .lab-grid:empty{min-height:calc(100vh - 200px)}
.board-bar>.bar-options:first-of-type{flex:1}
.bar-option,.bar-reset{flex:none;min-height:32px;padding:5px 7px;border:0;border-radius:3px;background:none;color:var(--soft);font:12.5px var(--mono);white-space:nowrap}
.bar-option:hover,.bar-reset:hover{color:var(--fg)}
.bar-option[aria-pressed=true]{color:var(--fg);background:var(--tile2)}
.bar-option[data-empty=true]{opacity:.4}
.bar-count{margin-left:4px;color:var(--muted);font-size:11px}
#lab-difficulty{flex:none;margin-right:auto}
.bar-search{flex:none;margin-left:8px}
.bar-search input{width:170px;height:30px;padding:5px 10px;background:var(--tile2);border:1px solid var(--muted);border-radius:3px;color:var(--fg);font:12.5px var(--mono)}
.bar-search input::placeholder{color:var(--muted)}.bar-search input:focus{border-color:var(--fg);background:var(--hover);outline:none}
#board-error{font:13px var(--mono);color:var(--red)}
.lab-grid{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));grid-auto-rows:minmax(148px,auto);grid-auto-flow:dense;gap:8px;overflow-x:clip}
.lab-contract{position:relative;min-width:0;display:flex;flex-direction:column;padding:14px 16px;background:var(--surface);border:1px solid var(--line);color:var(--fg);transition:border-color .15s}
a.lab-contract:hover{border-color:var(--muted)}
.lab-contract.xl{grid-column:span 3;grid-row:span 2;padding:20px 22px;background:var(--tile2)}
.lab-contract.wide{grid-column:span 2}.lab-contract.tall{grid-row:span 2}
.card-kicker{display:flex;flex-wrap:wrap;justify-content:space-between;gap:2px 8px;font:11px var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--red)}
/* The category is never cut: when it and the tier do not fit on one line, the tier moves to the next. */
.card-discipline{white-space:nowrap}
.card-marks{flex:none;display:flex;gap:10px;margin-left:auto;letter-spacing:.06em}
.card-tag{color:var(--muted)}
.lab-contract[data-lead=own] .card-tag,.lab-contract[data-progress=attempted] .card-tag{color:var(--amber)}
.lab-contract[data-lead=new] .card-tag{color:var(--mint)}
.card-tier{color:var(--muted)}.card-tier::before{content:"";display:inline-block;width:6px;height:6px;margin:0 5px 1px 0;border-radius:50%;background:currentColor}
.card-tier[data-tier=Apprentice]{color:var(--mint)}.card-tier[data-tier=Adept]{color:var(--amber)}
.card-tier[data-tier=Expert]{color:var(--orange)}.card-tier[data-tier=Mastery]{color:var(--violet)}
/* Whole titles: the tile grows with its title (rows are minmax(148px,auto)); the title never shrinks under the meta row. */
.lab-contract h2{flex:none;font:500 17.5px/1.15 var(--serif);margin:6px 0 0;text-wrap:balance}
.lab-contract.xl h2{font-size:36px;line-height:1.05;margin-top:12px}
.lab-contract.wide h2{font-size:22px}
.lab-contract.tall h2{font-size:21px}
.card-description{display:none;margin:12px 0 0;max-width:60ch;color:var(--soft);font-size:15px;line-height:1.45}
.lab-contract.xl .card-description{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;overflow:hidden}
.card-foot{margin-top:auto;padding-top:10px;display:flex;justify-content:space-between;align-items:flex-end;gap:10px;font:11px/1.5 var(--mono);color:var(--muted)}
.card-facts{display:flex;flex-wrap:wrap;gap:0 4px;min-width:0}
.card-flags{display:contents}.card-flags>span::before{content:"· ";color:var(--dim)}
.contract-new{color:var(--mint)}.contract-resolved{color:var(--solved)}.contract-attempts{color:var(--amber)}
.lab-contract:not(.xl,.wide) .card-ready{display:none}
.card-xp{flex:none;white-space:nowrap}.card-xp b{margin-right:5px;font:500 18px/1 var(--serif);color:var(--fg)}
.lab-contract.xl .card-foot{font-size:12px}.lab-contract.xl .card-xp b{font-size:30px}
/* Solved (founder 2026-10-15): the tile is muted (mockup 4: solid border, content at .4) and a mint SOLVED ribbon crosses the
   top-right corner (mockup 1), sized so it clears the subject and title: the tier mark steps in 20px (24px on phones) and
   drops its dot (already dim here, so it carries no tier colour) to give the subject back that room, the band stays in the
   corner. The title keeps 4.5:1 against the tile (full colour at .55). The tile stays a link (replay). */
.lab-contract[data-progress=cleared]{border-style:solid;color:var(--dim);overflow:hidden}
.lab-contract[data-progress=cleared] :is(.card-kicker,.card-tag,.card-tier,.card-xp b){color:var(--dim)}
.lab-contract[data-progress=cleared]>*{opacity:.4}
.lab-contract[data-progress=cleared] h2{color:var(--fg);opacity:.55}
.lab-contract[data-progress=cleared] .card-marks{margin-right:20px}.lab-contract[data-progress=cleared] .card-tier::before{display:none}
.lab-contract[data-progress=cleared]::after{content:"Solved";position:absolute;top:11px;right:-36px;width:110px;transform:rotate(45deg);padding:3px 0;background:var(--mint);color:var(--on-fill);text-align:center;font:700 10px/1 var(--mono);letter-spacing:.14em;text-transform:uppercase;pointer-events:none}
a.lab-contract[data-progress=cleared]:is(:hover,:focus-visible)>*{opacity:.7}
.lab-contract[data-progress=attempted]{border-left:3px solid var(--amber)}
div.lab-contract{border-style:dotted}
.board-empty{padding:40px;text-align:center;color:var(--muted);font:14px var(--mono)}.board-empty p{margin:0 0 8px}
.board-footer{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-top:22px;padding:8px 0;border-top:1px solid var(--line);color:var(--muted);font:12px var(--mono)}
.board-footer p{margin:0}
@media(max-width:1365px){.lab-grid{grid-template-columns:repeat(4,minmax(0,1fr))}.lab-contract.xl{grid-column:span 2}}
@media(max-width:1100px){.lab-board{padding-inline:24px}}
@media(max-width:1023px){.lab-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.lab-contract.xl,.lab-contract.wide{grid-column:span 2}}
@media(max-width:760px){
  .board-bar{flex-wrap:wrap}.board-bar>.bar-options:first-of-type{flex:1 1 calc(100% - 94px)}
  .bar-search{flex:1 1 100%;margin:6px 0 0}.bar-search input{width:100%;height:40px;font-size:16px}
  #lab-difficulty{margin-right:0;flex:1 1 calc(100% - 94px)}#lab-status{flex:1 1 calc(100% - 94px)}
}
@media(max-width:640px){
  .lab-board-page #site-header nav a{font-size:var(--shell-nav-size)}
  .lab-board{padding:12px 16px 0}.board-mast{flex-wrap:wrap}.mast-side{width:100%;text-align:left}.mast-account{position:absolute;top:0;right:0}.mast-links{justify-content:flex-start}
  /* The late Resume link takes the empty corner beside the title: nothing moves. */
  .mast-links .board-resume{position:absolute;top:0;right:0}
  .lab-grid{grid-template-columns:minmax(0,1fr);grid-auto-rows:auto}
  .lab-contract,.lab-contract.xl,.lab-contract.wide,.lab-contract.tall{grid-column:auto;grid-row:auto;min-height:118px;padding:12px 14px}
  .lab-contract.xl h2{font-size:26px}.lab-contract.wide h2,.lab-contract.tall h2{font-size:19px}
  .card-foot{padding-top:12px}.lab-contract:not(.xl,.wide) .card-ready{display:inline}
  .lab-contract[data-progress=cleared] .card-marks{margin-right:24px}
}
@media(prefers-reduced-motion:reduce){.lab-contract{transition:none}}
/* Prerequisite soft lock (design 10 §3): a locked card lists what to solve first, ✓ solved / ○ unsolved in play order, as text
   inside its link; the card opens the lab like any other. Skipped and guest cards show the same list. */
.lab-contract[data-lock=locked]{border-style:solid}
.card-prereqs{margin-top:10px;font:12px/1.35 var(--mono);color:var(--soft)}
.prereq-head{margin:0 0 2px;color:var(--fg)}
.prereq-list{list-style:none;margin:0;padding:0}
.prereq-item{display:flex;align-items:baseline;gap:6px;min-width:0;padding:1px 0}
.prereq-mark{flex:none;width:1.1em;color:var(--muted)}.prereq-item[data-solved=true] .prereq-mark{color:var(--solved)}
.prereq-title{min-width:0;overflow-wrap:anywhere}
.contract-skipped{color:var(--amber)}
