@font-face { font-family: 'Libre Caslon Text'; font-style: italic; font-weight: 400; font-display: optional; src: url(fonts/libre-caslon-text-400-italic.da67fedc.woff2) format('woff2'); }
@font-face { font-family: 'Libre Caslon Text'; font-style: normal; font-weight: 400; font-display: optional; src: url(fonts/libre-caslon-text-400.001d520e.woff2) format('woff2'); }
@font-face { font-family: 'Libre Caslon Text'; font-style: normal; font-weight: 700; font-display: optional; src: url(fonts/libre-caslon-text-700.33af9ef1.woff2) format('woff2'); }
@font-face { font-family: 'Schibsted Grotesk'; font-style: normal; font-weight: 400 600; font-display: optional; src: url(fonts/schibsted-grotesk-400.c5e9a990.woff2) format('woff2'); }
@font-face { font-family: 'Spline Sans Mono'; font-style: normal; font-weight: 400 500; font-display: optional; src: url(fonts/spline-sans-mono-400.4ebf124f.woff2) format('woff2'); }
:root {
  --paper:#070c14; --paper2:#0e1826; --ink:#d7e3f2; --ink2:#8fa3bb;
  --mut:#5d7392; --mut2:#45587a; --acc:#7ec8ff;
  --surface:#0a111c; --surface2:#0e1826; --cardsolid:#101a2a;
  --hairline:#141e30; --hairline2:#1b2740; --hairline3:#26395a;
  --green:#7ec8ff; --green2:#b3ddff; --brass:#7ec8ff; --wine:#a06060;
  --line:#1b2740; --card:#0e1726; --ok:var(--ok); --mid:#c9a86a; --bad:#a06060;
  --mono:'Spline Sans Mono', ui-monospace, Menlo, monospace;
  --accdim:rgba(216,176,120,.45); --accfaint:rgba(216,176,120,.24);
  --ghost1:#0c1523; --ghost1l:#16223a; --ghost2:#0e1826; --ghost2l:#1b2a45;
  --btnline:#1e2f4c; --btnlineh:#2f4a75;
}
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) {
  --paper:#070c14; --paper2:#0e1826; --ink:#d7e3f2; --ink2:#8fa3bb;
  --mut:#5d7392; --mut2:#45587a; --acc:#7ec8ff;
  --surface:#0a111c; --surface2:#0e1826; --cardsolid:#101a2a;
  --hairline:#141e30; --hairline2:#1b2740; --hairline3:#26395a;
  --green:#7ec8ff; --green2:#b3ddff; --brass:#7ec8ff; --wine:#a06060;
  --line:#1b2740; --card:#0e1726; --ok:var(--ok); --mid:#c9a86a; --bad:#a06060;
  --mono:'Spline Sans Mono', ui-monospace, Menlo, monospace;
  --accdim:rgba(216,176,120,.45); --accfaint:rgba(216,176,120,.24);
  --ghost1:#0c1523; --ghost1l:#16223a; --ghost2:#0e1826; --ghost2l:#1b2a45;
  --btnline:#1e2f4c; --btnlineh:#2f4a75;
} }
:root[data-theme="dark"] {
  --paper:#070c14; --paper2:#0e1826; --ink:#d7e3f2; --ink2:#8fa3bb;
  --mut:#5d7392; --mut2:#45587a; --acc:#7ec8ff;
  --surface:#0a111c; --surface2:#0e1826; --cardsolid:#101a2a;
  --hairline:#141e30; --hairline2:#1b2740; --hairline3:#26395a;
  --green:#7ec8ff; --green2:#b3ddff; --brass:#7ec8ff; --wine:#a06060;
  --line:#1b2740; --card:#0e1726; --ok:var(--ok); --mid:#c9a86a; --bad:#a06060;
  --mono:'Spline Sans Mono', ui-monospace, Menlo, monospace;
  --accdim:rgba(216,176,120,.45); --accfaint:rgba(216,176,120,.24);
  --ghost1:#0c1523; --ghost1l:#16223a; --ghost2:#0e1826; --ghost2l:#1b2a45;
  --btnline:#1e2f4c; --btnlineh:#2f4a75;
}
* { box-sizing:border-box; }
button, .abtn { font:inherit; background:rgba(255,255,255,.08); color:var(--ink);
  border:1px solid var(--line); border-radius:6px; padding:.4rem .9rem; cursor:pointer;
  transition:transform .05s ease, box-shadow .05s ease, border-color .15s, background .15s, filter .15s; }
button:hover, .abtn:hover { border-color:var(--green); }
.vb { font-family:var(--mono); font-size:.68rem; letter-spacing:.04em;
  color:var(--ink2); }
.vb.game { color:var(--green); }
.vb.check { color:var(--mid); }
body { background:#070c14; color:var(--ink); margin:0;
  font:15.5px/1.62 'Schibsted Grotesk', -apple-system, "Segoe UI", sans-serif; }
.mono { font-family:ui-monospace,"SF Mono",Menlo,Consolas,monospace; font-size:.82em; }
.wrap { max-width:72rem; margin:0 auto; padding:0 1.2rem; }
.col { max-width:44rem; margin:0 auto; }
a { color:var(--green); }
h1,h2,h3,h4 { text-wrap:balance; line-height:1.2; }
.eyebrow { font-family:var(--mono); font-size:.72rem; letter-spacing:.18em;
  text-transform:uppercase; color:var(--brass); margin:0 0 .6rem; }
/* hero */
.hero { display:grid; grid-template-columns:1.1fr .9fr; gap:2.5rem; align-items:center;
  padding:3.5rem 0 2.5rem; border-bottom:1px solid var(--hairline); }
.hero h1 { font-size:clamp(2rem,5vw,3.1rem); margin:.2rem 0 1rem; font-weight:600; }
.hero p.lede { font-size:1.12rem; color:var(--ink); }
@media (max-width:760px) { .hero { grid-template-columns:1fr; } }
/* stat strip */
.strip { display:flex; flex-wrap:wrap; gap:0; border-bottom:1px solid var(--line); }
.strip div { flex:1 1 110px; padding:1rem .8rem; border-right:1px solid var(--line); }
.strip div:last-child { border-right:none; }
.strip .n { font-family:var(--mono); font-size:1.35rem; color:var(--green);
  font-variant-numeric:tabular-nums; display:block; }
.strip .l { font-size:.75rem; letter-spacing:.06em; text-transform:uppercase; color:var(--ink2); }
section { padding:2.6rem 0; border-bottom:1px solid var(--line); }
section h2 { font-size:1.6rem; margin:0 0 1rem; }
blockquote { margin:1.2rem 0; padding:.2rem 0 .2rem 1.1rem; border-left:3px solid var(--brass);
  color:var(--ink2); font-style:italic; }
.src { font-size:.8rem; }
/* gallery */
.gal { display:grid; grid-template-columns:repeat(auto-fill,minmax(272px,1fr)); gap:1.4rem; margin-top:1.6rem; }
.cue { font-style:italic; color:var(--ink2); font-size:.88rem; margin:.2rem 0 .4rem; }
.stats { display:flex; gap:1rem; font-family:var(--mono); font-size:.76rem;
  color:var(--green); margin:.3rem 0; font-variant-numeric:tabular-nums; }
.tag { background:var(--paper2); padding:.1rem .5rem; border-radius:2px; color:var(--ink2); }
.chip { font-family:var(--mono); font-size:.68rem; letter-spacing:.05em;
  padding:.15rem .5rem; border-radius:2px; background:var(--paper2); color:var(--ink2); }
.chip.ok { color:var(--ok); } .chip.mid { color:var(--mid); } .chip.bad { color:var(--bad); }
/* table */
table { border-collapse:collapse; width:100%; font-size:.9rem; background:var(--card); }
th { text-align:left; font-family:var(--mono); font-size:.7rem; letter-spacing:.1em;
  text-transform:uppercase; color:var(--ink2); padding:.6rem .8rem; border-bottom:2px solid var(--line); }
td { padding:.55rem .8rem; border-bottom:1px solid var(--line); vertical-align:top; }
td.num { text-align:right; font-variant-numeric:tabular-nums; }
/* files */
.files { display:grid; gap:.6rem; margin-top:1.2rem; }
.files div { display:grid; grid-template-columns:14rem 1fr; gap:1rem; padding:.6rem 0;
  border-top:1px solid var(--line); }
.files code { font-family:var(--mono); font-size:.82rem; color:var(--green); }
.files span { color:var(--ink2); font-size:.95rem; }
@media (max-width:640px) { .files div { grid-template-columns:1fr; gap:.15rem; } }
footer { padding:2rem 0 3rem; color:var(--ink2); font-size:.85rem; }
/* interactivity */
.more { color:var(--green); margin-left:auto; font-family:var(--mono); }
/* modal */
#ovl { position:fixed; inset:0; background:rgba(4,8,16,.6); display:none;
  z-index:50; overflow-y:auto; padding:3vh 1rem; }
#ovl.open { display:block; }
#dlg { max-width:64rem; margin:0 auto; background:var(--panelbg,#0d1626); border:1px solid var(--panelline,#223453);
  box-shadow:0 18px 48px rgba(2,6,14,.66); }
#dlg header { display:flex; justify-content:space-between; align-items:start; gap:1rem;
  padding:1.2rem 1.4rem .9rem; border-bottom:1px solid var(--line); }
#dlg h3 { margin:.1rem 0 .2rem; font-size:1.25rem; }
#dlg .cue { margin:.15rem 0 0; }
#dlg .dstats { font-family:var(--mono); font-size:.76rem; color:var(--green);
  display:flex; gap:1rem; flex-wrap:wrap; margin-top:.4rem; font-variant-numeric:tabular-nums; }
#xbtn { font:inherit; font-size:1.3rem; line-height:1; background:none; border:1px solid var(--line);
  color:var(--ink2); width:2.2rem; height:2.2rem; cursor:pointer; flex:none; }
#xbtn:hover, #xbtn:focus { color:var(--ink); border-color:var(--green); outline:none; }
#exgrid { display:grid; grid-template-columns:repeat(auto-fill,minmax(232px,1fr)); gap:1.1rem;
  padding:1.2rem 1.4rem 1.4rem; }
.ex { background:var(--card); border:1px solid var(--line); }
.ex .cb-wrap { padding:.6rem .6rem 0; }
.ex .ex-meta { padding:.5rem .7rem .7rem; font-size:.78rem; color:var(--ink2); }
.ex .ex-meta a { float:right; }
.ex .sanline { font-family:var(--mono); font-size:.74rem; min-height:2.1em;
  color:var(--ink); margin-top:.3rem; word-spacing:.15em; }
.ex .hint { color:var(--green); font-size:.72rem; font-family:var(--mono); }
/* client-rendered board */
.cb { border:1px solid var(--line); user-select:none; cursor:pointer; line-height:0; }
.cb svg { display:block; width:100%; height:auto; }
@media (prefers-reduced-motion: no-preference) {
  #dlg { animation:pop .18s ease-out; }
  @keyframes pop { from { transform:translateY(10px); opacity:0; } to { transform:none; opacity:1; } }
}
/* tabs */
#tabs { display:flex; flex-wrap:nowrap; overflow-x:auto; scrollbar-width:none;
  gap:1.1rem; padding:0 1.6rem; background:var(--surface); height:52px;
  -webkit-overflow-scrolling:touch; align-items:center;
  border-bottom:1px solid var(--hairline); }
#tabs::before { content:"Pattern Lab"; font-family:var(--sans); font-weight:600;
  font-size:.95rem; color:var(--ink); letter-spacing:.01em; margin-right:.9rem;
  white-space:nowrap; }
section, .hero, .pos-head { }
.wrap > section, .wrap > header { background:var(--card); border:1px solid var(--line);
  border-radius:8px; margin:1.2rem 0; padding-left:1.4rem; padding-right:1.4rem;
  backdrop-filter:blur(2px); }
.strip { background:var(--card); border:1px solid var(--line); border-radius:8px;
  margin-top:1.2rem; }
footer.wrap { text-shadow:0 1px 3px rgba(0,0,0,.6); }
#tabs::-webkit-scrollbar { display:none; }
#tabs button { flex:none; font-family:var(--sans); font-size:.82rem;
  background:none; border:none; border-bottom:2px solid transparent;
  border-top:2px solid transparent; color:var(--ink2); height:52px;
  padding:0 .1rem; cursor:pointer; letter-spacing:.01em; }
#tabs button.on { color:var(--ink); border-bottom-color:var(--acc); font-weight:500; }
#tabs button:hover:not(.on) { color:var(--ink); }
#loglink { font-family:var(--mono); font-size:.7rem; letter-spacing:.1em;
  color:var(--ink2); opacity:.7; text-decoration:none; align-self:center;
  margin-left:auto; padding:.4rem .2rem; }
#loglink:hover { color:var(--mid); opacity:1; }
#tabs button:hover { color:var(--ink); }
/* positional tab */
.pos-head { padding:2.2rem 0 1.6rem; border-bottom:1px solid var(--hairline); }
.pos-head h1 { font-size:clamp(1.7rem,4vw,2.4rem); margin:.2rem 0 .8rem; font-weight:600; }
.pos-book { padding:1.8rem 0; border-bottom:1px solid var(--line); }
.pos-book h2 { font-size:1.3rem; margin:0 0 .2rem; }
.pos-book .src { color:var(--ink2); margin:0 0 1rem; font-size:.9rem; }
.pg-head { font-family:var(--mono); font-size:.72rem; letter-spacing:.14em;
  text-transform:uppercase; color:var(--brass); margin:1.1rem 0 .3rem; }
.unit { display:grid; grid-template-columns:3.4rem 1fr 7.5rem; gap:.8rem; padding:.45rem .6rem;
  border-bottom:1px solid var(--line); cursor:pointer; align-items:baseline; }
.unit:hover { background:color-mix(in srgb, var(--green) 8%, var(--card)); }
.unit .uid { font-family:var(--mono); color:var(--brass); font-size:.78rem; }
.unit .ct { font-family:var(--mono); font-size:.74rem; color:var(--ink2);
  text-align:right; font-variant-numeric:tabular-nums; }
.unit-list { background:none; border:0; border-radius:0; border-top:1px solid var(--line); }
#exChapters { display:flex; flex-direction:column; gap:.7rem; margin-top:1.6rem; }
details.part2 { background:none; border:0; border-radius:0;
  border-top:1px solid var(--line); }
details.part2:hover { background:var(--hover); }
details.part2 > summary { display:flex; align-items:center; gap:1rem; padding:.8rem 1.05rem;
  cursor:pointer; list-style:none; color:var(--ink); font-size:.95rem; }
details.part2 > summary::-webkit-details-marker { display:none; }
details.part2 > summary::after { content:"❯"; font-size:.78rem; color:var(--ink2); opacity:.55;
  margin-left:auto; transform:rotate(90deg); transition:transform .18s ease; flex:none; }
details.part2[open] > summary::after { transform:rotate(-90deg); }
details.part2[open] > summary { border-bottom:1px solid var(--line); }
details.part2[open] { padding-bottom:.65rem; }
details.part2 > *:not(summary) { margin:.55rem 1.05rem 0; }
.ch-num { font-family:var(--mono); font-size:.8rem; color:var(--mid);
  background:rgba(201,168,106,.08); border:1px solid rgba(201,168,106,.28); border-radius:8px;
  padding:.34rem .5rem; letter-spacing:.04em; flex:none; font-variant-numeric:tabular-nums; }
details.part2.done .ch-num { color:var(--ok); border-color:rgba(216,176,120,.45);
  background:rgba(216,176,120,.10); }
.ch-info { display:flex; flex-direction:column; gap:.14rem; flex:1; min-width:9rem; }
.ch-name { font-weight:600; font-size:1rem; color:var(--ink); }
.ch-sub { font-family:var(--mono); font-size:.66rem; color:var(--ink2);
  letter-spacing:.08em; text-transform:uppercase; }
.ch-prog { display:flex; align-items:center; gap:.55rem; flex:none; }
@media (max-width: 700px) {
  details.part2 > summary { flex-wrap:wrap; row-gap:.6rem; }
  .ch-prog { flex:1 1 100%; order:10; }
}
/* quiz */
#quiz { max-width:min(calc(100vh - 200px), 92vw, 64rem); min-width:min(33rem, 92vw); margin:1.4rem auto; padding:1.6rem 1.6rem 2rem;
  background:var(--card); border:1px solid var(--line); border-radius:8px;
  backdrop-filter:blur(2px); }
#quiz h1 { font-size:clamp(1.5rem,4vw,2rem); margin:.2rem 0 .3rem; font-weight:600; }
#qscore { font-family:var(--mono); font-size:.78rem; color:var(--ink2);
  font-variant-numeric:tabular-nums; }
#qboard { border:1px solid var(--line); margin:1.1rem 0 .3rem; line-height:0; }
#qboard svg { display:block; width:100%; height:auto; }
#qprompt { font-size:.95rem; color:var(--ink2); margin:.5rem 0 .8rem; }
#qopts { display:grid; gap:.5rem; }
#qopts button { text-align:left; padding:.65rem .9rem; font-size:.95rem; line-height:1.35; }
#qopts button:hover:not(:disabled) { border-color:var(--green); }
#qopts button:disabled { cursor:default; opacity:.92; }
button.primary, .abtn.primary {
  background:linear-gradient(180deg, #93c95e, #7cb14a); border:0; color:#fff;
  font-weight:700; letter-spacing:.01em; border-radius:10px;
  box-shadow:0 4px 0 #567f31, 0 6px 12px rgba(0,0,0,.30);
  text-shadow:0 1px 1px rgba(0,0,0,.28); }
button.primary:hover { background:linear-gradient(180deg, #9cd267, #84ba51); }
button.primary:active { transform:translateY(3px);
  box-shadow:0 1px 0 #567f31, 0 2px 5px rgba(0,0,0,.3); }
.solvebtn.primary { box-shadow:0 3px 0 #567f31; border-radius:8px; padding:.3rem .8rem; }
.solvebtn.primary:active { transform:translateY(2px); box-shadow:0 1px 0 #567f31; }
#qopts button.right { border-color:var(--ok); color:var(--ok); font-weight:bold; }
#qopts button.wrong { border-color:var(--bad); color:var(--bad); }
#qreveal { margin-top:1rem; display:none; }
#qreveal.show { display:block; }
#qmeta { font-size:.9rem; margin:.3rem 0 .2rem; }
#qmeta .sanline { font-family:var(--mono); font-size:.78rem; margin:.4rem 0;
  min-height:1.4em; word-spacing:.15em; }
#qmeta .hint { color:var(--green); font-size:.75rem; font-family:var(--mono); }
#qacts { display:flex; flex-wrap:wrap; gap:.4rem; margin-top:.6rem; align-items:center; }
.abtn { font:inherit; background:var(--card); color:var(--fg, var(--ink)); border:1px solid var(--line);
  border-radius:6px; padding:.4rem .9rem; text-decoration:none; }
.abtn:hover { border-color:var(--green); }
.vb { font-family:var(--mono); font-size:.68rem; letter-spacing:.04em;
  color:var(--ink2); }
.vb.game { color:var(--green); }
.vb.check { color:var(--mid); }
/* exercise solver — full-page view */
.solve-top { max-width:76rem; margin:0 auto; padding:1rem 1.4rem 0; }
.solve-top a { color:var(--ink2); text-decoration:none; font-family:var(--mono);
  font-size:.78rem; letter-spacing:.08em; }
.solve-top a:hover { color:var(--green); }
.solve-grid { display:grid;
  grid-template-columns:minmax(280px, calc(100vh - 175px)) minmax(280px, 350px);
  gap:1.6rem; justify-content:center; align-items:start; padding:.9rem 1.4rem 2.5rem; }
#svBoard { line-height:0; touch-action:none; cursor:pointer; }   /* the svg owns the edge */
#svBoard svg { display:block; width:100%; height:auto; }
.solve-side { background:var(--card); border:1px solid var(--line); border-radius:14px;
  padding:1.25rem 1.3rem 1.35rem; backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.07), 0 12px 32px rgba(0,0,0,.28); }
.solve-side h2 { margin:.45rem 0 .8rem; font-size:1.35rem; font-weight:650;
  display:flex; align-items:center; gap:.55rem; }
.side-dot { width:14px; height:14px; border-radius:50%; display:inline-block; flex:none;
  box-shadow:0 0 0 2px rgba(255,255,255,.22), 0 1px 3px rgba(0,0,0,.45); }
.side-dot.sw { background:linear-gradient(145deg, #ffffff, #cfd8dc); }
.side-dot.sb { background:linear-gradient(145deg, #4a4f55, #17191c); }
.sv-bar { height:6px; border-radius:3px; background:rgba(255,255,255,.09); overflow:hidden; }
.sv-bar i { display:block; height:100%; border-radius:3px;
  background:linear-gradient(90deg, #6fa23f, #93c95e); transition:width .35s ease; }
.sv-bar.wide { max-width:340px; margin:.5rem auto 0; }
.sv-chips { display:flex; flex-wrap:wrap; gap:.4rem; margin:0 0 1.05rem; }
.chip { font-family:var(--mono); font-size:.68rem; letter-spacing:.04em;
  color:var(--ink2); background:rgba(255,255,255,.07); border:1px solid var(--line);
  border-radius:999px; padding:.22rem .62rem; white-space:nowrap;
  font-variant-numeric:tabular-nums; }
.chip.ok { color:var(--ok); border-color:rgba(216,176,120,.45); background:rgba(216,176,120,.10); }
.chip.hot { color:#c9a86a; border-color:rgba(201,168,106,.5); background:rgba(201,168,106,.10); }
.sv-btns { display:flex; flex-direction:column; gap:.55rem; }
.sv-sec { display:flex; align-items:center; justify-content:center; gap:.5rem;
  padding:.68rem .9rem; font-size:.92rem; font-weight:600; border-radius:10px;
  background:linear-gradient(180deg, rgba(255,255,255,.11), rgba(255,255,255,.05));
  border:1px solid rgba(255,255,255,.15);
  box-shadow:0 3px 0 rgba(0,0,0,.32), inset 0 1px 0 rgba(255,255,255,.08); }
.sv-sec:hover { border-color:rgba(255,255,255,.32);
  background:linear-gradient(180deg, rgba(255,255,255,.14), rgba(255,255,255,.07)); }
.sv-sec:active { transform:translateY(2px); box-shadow:0 1px 0 rgba(0,0,0,.32); }
.sv-sec svg { flex:none; opacity:.9; }
#svHintBtn { width:100%; }
.sv-nav { display:flex; gap:.55rem; }
.sv-nav #svPrev { flex:0 0 54px; padding:.68rem 0; }
.sv-nav #svNext { flex:1; display:inline-flex; align-items:center; justify-content:center;
  gap:.45rem; padding:.74rem .9rem; font-size:.95rem; }
.sv-ghost { background:none; border:none; box-shadow:none; color:var(--ink2);
  font-family:var(--mono); font-size:.78rem; letter-spacing:.06em;
  padding:.5rem; opacity:.75; align-self:center; }
.sv-ghost:hover { color:var(--bad); opacity:1; border:none; }
@keyframes svpulse {
  0%, 100% { box-shadow:0 4px 0 #567f31, 0 0 0 0 rgba(147,201,94,.55); }
  50% { box-shadow:0 4px 0 #567f31, 0 0 0 10px rgba(147,201,94,0); } }
.pulse { animation:svpulse 1.5s ease-out infinite; }
@media (prefers-reduced-motion: reduce) { .pulse { animation:none; } }
.ex-stats { display:flex; gap:.4rem; justify-content:center; flex-wrap:wrap; }
#vzNav { display:flex; gap:.5rem; justify-content:center; flex-wrap:wrap; padding:1.1rem 1.2rem .2rem; }
#vzNav button { font-family:var(--mono); font-size:.78rem; letter-spacing:.08em;
  padding:.5rem 1rem; border-radius:999px; }
#vzNav button.on { color:#fff; background:linear-gradient(180deg, #93c95e, #7cb14a); border-color:transparent;
  box-shadow:0 3px 0 #567f31; font-weight:700; }
#vztDepth button { font-size:.74rem; padding:.4rem .3rem; }
#vztDepth button.on { border-color:rgba(216,176,120,.65); color:var(--ok);
  background:rgba(216,176,120,.14); }
.vz-cards { display:grid; grid-template-columns:repeat(auto-fit, minmax(300px, 420px));
  gap:1.3rem; justify-content:center; padding:1.2rem 1.4rem 2.5rem; }
.vz-card h2 { margin:.5rem 0 .7rem; }
.vz-card .primary { width:100%; margin-top:.6rem; padding:.65rem; }
.vz-minib { border:1px solid var(--line); line-height:0; touch-action:none; cursor:pointer;
  max-width:340px; margin:.2rem auto .4rem; }
.vz-minib svg { display:block; width:100%; height:auto; }
#vzcPrompt { font-size:2.6rem; text-align:center; font-family:var(--mono);
  letter-spacing:.05em; margin:.6rem 0; min-height:1.2em; }
.vz-freeze { text-align:center; font-family:var(--mono); font-size:.7rem;
  color:var(--mid); letter-spacing:.06em; margin:.5rem 0 0; opacity:.85; }
.vz-line { font-family:var(--mono); font-size:.9rem; line-height:1.9;
  margin:.2rem 0 .7rem; min-height:2.2em; word-spacing:.12em; color:var(--ink); }
.vz-line .mvnew { background:rgba(216,176,120,.18); border-radius:4px; padding:.06rem .3rem; }
.vz-q { font-size:.95rem; font-weight:600; margin:.2rem 0 .55rem; min-height:1.4em; }
.vz-depth { margin:.9rem 0 .3rem; }
.vz-depth .dseg { display:flex; gap:.3rem; margin-top:.4rem; }
.vz-depth .dseg i { flex:1; height:22px; border-radius:5px; background:rgba(255,255,255,.08);
  border:1px solid var(--line); font-size:.62rem; font-family:var(--mono);
  display:flex; align-items:center; justify-content:center; color:var(--ink2); font-style:normal; }
.vz-depth .dseg i.good { background:rgba(216,176,120,.28); border-color:rgba(216,176,120,.5); color:var(--ok); }
.vz-depth .dseg i.mid { background:rgba(201,168,106,.18); border-color:rgba(201,168,106,.4); color:#c9a86a; }
.vz-depth .dlabel { font-family:var(--mono); font-size:.7rem; color:var(--ink2); }
.vz-plist { font-family:var(--mono); font-size:.86rem; line-height:1.9;
  background:rgba(255,255,255,.05); border:1px solid var(--line); border-radius:10px;
  padding:.7rem .9rem; margin:.2rem 0 .7rem; }
.vz-plist b { color:var(--mid); font-weight:600; }
.vz-sci p { color:var(--ink2); font-size:.92rem; line-height:1.65; margin:.7rem 0; }
.st-reveal { font-size:.85rem; color:var(--ink2); line-height:1.55; margin:.2rem 0 .8rem; }
.st-reveal .stg { font-family:var(--mono); font-size:.74rem; color:var(--mid);
  display:block; margin-bottom:.4rem; }
.st-reveal ol { margin:.3rem 0 0 1.1rem; padding:0; }
.st-reveal li { margin:.3rem 0; }
.st-reveal li.hit { color:var(--ok); }
.tq-opts button.plan { font-weight:500; font-size:.85rem; line-height:1.45; }
.aag-grid { display:grid; grid-template-columns:repeat(auto-fill, minmax(270px, 1fr));
  gap:1rem; }
.aag-brd { line-height:0; border:1px solid var(--line); cursor:pointer; }
.aag-brd svg { display:block; width:100%; height:auto; }
.stlib-row { display:flex; align-items:center; gap:.8rem; padding:.45rem .2rem;
  border-bottom:1px solid rgba(255,255,255,.06); flex-wrap:wrap; }
.stlib-row:last-child { border-bottom:none; }
.stlib-elo { font-family:var(--mono); font-size:.7rem; color:var(--mid);
  flex:none; width:3.2em; }
.stlib-names { flex:1; min-width:12rem; font-size:.92rem; }
.stlib-names small { color:var(--ink2); font-family:var(--mono); font-size:.7rem; }
.stlib-acts { display:flex; gap:.4rem; flex:none; }
.stlib-acts a, .stlib-acts button { font-size:.74rem; padding:.28rem .6rem; }
.stlib-dl { margin-left:auto; }
.stpat-grid { display:grid; grid-template-columns:repeat(auto-fill, minmax(270px, 1fr));
  gap:1rem; margin-top:1rem; }
.stpat { background:var(--card); border:1px solid var(--line); border-radius:12px;
  padding:.9rem .95rem 1rem; display:flex; flex-direction:column; gap:.5rem; }
.stpat .brd { line-height:0; border:1px solid var(--line); }
.stpat .brd svg { display:block; width:100%; height:auto; }
.stpat h3 { margin:0; font-size:1rem; display:flex; align-items:center; gap:.45rem; }
.stpat .why { font-size:.82rem; color:var(--ink2); line-height:1.5; margin:0; }
.stpat .strike { font-family:var(--mono); font-size:.7rem; color:var(--mid); }
.stpat .exrow { display:flex; align-items:center; gap:.45rem; font-size:.76rem;
  color:var(--ink2); flex-wrap:wrap; }
.stpat .exrow a, .stpat .exrow button { font-size:.68rem; padding:.2rem .5rem; }
.stpat .chipline { display:flex; gap:.35rem; flex-wrap:wrap; }
.vz-sci b { color:var(--ink); }
.vz-depth .dbig { font-size:1.05rem; font-weight:700; color:var(--ok); }
@media (max-width: 700px) { #vzcPrompt { font-size:2rem; } }
.tq-opts { display:flex; flex-direction:column; gap:.5rem; margin:.5rem 0 .85rem; }
.tq-opts button { text-align:left; padding:.62rem .85rem; font-size:.92rem; font-weight:600;
  border-radius:10px; background:linear-gradient(180deg, rgba(255,255,255,.11), rgba(255,255,255,.05));
  border:1px solid rgba(255,255,255,.15);
  box-shadow:0 3px 0 rgba(0,0,0,.32), inset 0 1px 0 rgba(255,255,255,.08); }
.tq-opts button:hover:not(:disabled) { border-color:rgba(255,255,255,.32); }
.tq-opts button:disabled { cursor:default; }
.tq-opts button .kbd { font-family:var(--mono); font-size:.68rem;
  color:var(--ink2); margin-right:.55rem; opacity:.7; }
.tq-opts button.right { border-color:rgba(216,176,120,.65); background:rgba(216,176,120,.16);
  color:var(--ok); }
.tq-opts button.wrong { border-color:rgba(160,96,96,.6); background:rgba(160,96,96,.12);
  color:#a06060; }
@media (max-width: 900px) {
  .solve-grid { grid-template-columns:minmax(0, 560px); }
}
.chsum { display:inline-flex; align-items:center; gap:.6rem; flex-wrap:wrap; }
.chbar { display:inline-block; width:96px; height:6px; background:rgba(255,255,255,.09);
  border-radius:3px; overflow:hidden; vertical-align:middle; }
.chbar i { display:block; height:100%; border-radius:3px;
  background:linear-gradient(90deg, #6fa23f, #93c95e); transition:width .35s ease; }
.chpct { font-family:var(--mono); font-size:.7rem; color:var(--ink2);
  min-width:3.6em; text-align:right; font-variant-numeric:tabular-nums; }
.solvebtn { font-size:.78rem; padding:.25rem .7rem; }
.exdone { color:var(--green); font-family:var(--mono); font-size:.72rem; }
@keyframes svshake { 25% { transform:translateX(-6px); } 75% { transform:translateX(6px); } }
.svshake { animation:svshake .16s 2; }

/* hover affordances (ui/hover-polish) */
.stlib-row { transition: background .15s, border-color .15s; }
.stlib-row:hover { background: rgba(255,255,255,.04);
  border-bottom-color: rgba(255,255,255,.16); }
.stpat { transition: border-color .15s, transform .15s; }
.stpat:hover { border-color: rgba(255,255,255,.28); transform: translateY(-2px); }
@media (prefers-reduced-motion: reduce) {
  .stpat:hover { transform: none; }
}

/* override layer: later rules win; board/solve surfaces untouched */
:root { --sans: 'Schibsted Grotesk', -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, sans-serif; }

/* 1 · the water becomes ambiance, not noise */
body { background-color: #070c14; }
body::before { content: none; }

/* 2 · one aligned content column */
.wrap { max-width: 62rem; }
.pos-head { max-width: none; }
.wrap > section, .wrap > header { padding: 1.9rem 2.2rem 2rem; border-radius: 14px; }

/* 3 · panels sit on solid glass */
.wrap > section, .wrap > header, details.part2, .stpat, .solve-side, #quiz {
  background: var(--card); backdrop-filter: none; -webkit-backdrop-filter: none;
  border-color: var(--line); box-shadow: none; }

/* 4 · typography: serif for headings, sans for UI, mono for numbers only */
button, .abtn, .sv-sec, .sv-ghost, .solvebtn { font-family: var(--sans); }
#tabs { padding: .65rem 1.1rem; gap: .5rem; background: var(--surface);
  backdrop-filter: none; -webkit-backdrop-filter: none;
  border-bottom: 1px solid var(--hairline); }
#tabs button { font-family: var(--sans); text-transform: none; letter-spacing: .01em;
  font-size: .84rem; font-weight: 600; padding: .46rem .95rem; color: var(--ink2); }
#tabs button.on { color: #fff; }
#loglink { font-family: var(--sans); text-transform: none; letter-spacing: .02em; }
.ch-sub, .stlib-names small { font-family: var(--sans); text-transform: none;
  letter-spacing: .01em; font-size: .78rem; }
.chip { letter-spacing: .01em; padding: .24rem .66rem; border-radius: 8px;
  background: rgba(255,255,255,.05); }
.eyebrow { letter-spacing: .14em; opacity: .85; }
.lede { color: #bcd6ee; }

/* 5 · chapter & shelf rows: quiet by default, one loud thing per page */
details.part2 > summary { padding: 1rem 1.3rem; gap: 1.1rem; }
.ch-num { background: none; border: none; padding: 0; width: 2.2ch;
  color: rgba(233,240,246,.34); font-size: 1.05rem; text-align: right; }
details.part2.done .ch-num { color: var(--ok); background: none; border: none; }
.ch-name { font-size: 1.06rem; letter-spacing: .01em; }
.chbar { width: 120px; height: 7px; background: rgba(255,255,255,.10); }
details.part2 .solvebtn,
.stlib-acts .sv-sec, .exrow .sv-sec, .stlib-acts a, .exrow a {
  background: rgba(216,176,120,.10); border: 1px solid rgba(216,176,120,.32);
  color: var(--ok); box-shadow: none; font-weight: 600; }
details.part2 .solvebtn:hover, .stlib-acts .sv-sec:hover, .exrow .sv-sec:hover {
  background: linear-gradient(180deg, #93c95e, #7cb14a); color: #fff;
  border-color: transparent; box-shadow: 0 3px 0 #567f31; }
.stlib-acts a:hover, .exrow a:hover { border-color: rgba(216,176,120,.7); color: var(--ok); }
details.part2 > summary::after { opacity: .35; }
details.part2:hover > summary::after { opacity: .8; }

/* 6 · hero: keep exactly one pushable-green CTA per page */
.pos-head h1 { font-size: clamp(1.9rem, 3.4vw, 2.5rem); letter-spacing: -.01em; }
.ex-stats .chip { font-size: .72rem; }
.sv-ghost { font-family: var(--sans); text-transform: none; letter-spacing: .01em; }

/* ---------------- Home / progress dashboard ---------------- */
.home-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1rem; margin-top: 1.4rem; }
.home-card { background: var(--card); border: 1px solid var(--line); border-radius: 8px;
  padding: 1.1rem 1.2rem 1.15rem; display: flex; flex-direction: column; gap: .55rem;
  box-shadow: none; }
.home-card h3 { margin: 0; font-size: 1.05rem; display: flex; align-items: baseline;
  justify-content: space-between; gap: .6rem; }
.home-card h3 small { font-family: var(--sans); font-size: .72rem; color: var(--ink2);
  font-weight: 500; }
.home-big { font-family: var(--mono); font-size: 1.7rem; font-weight: 700;
  color: var(--ok); line-height: 1; font-variant-numeric: tabular-nums; }
.home-big small { font-size: .8rem; color: var(--ink2); font-weight: 500; }
.home-sub { font-family: var(--sans); font-size: .78rem; color: var(--ink2); }
.home-card .sv-bar { margin-top: .1rem; }
.home-card .go { margin-top: auto; align-self: flex-start; font-size: .8rem;
  padding: .4rem .9rem; }
.home-cta { margin-top: auto; display: flex; gap: .5rem; align-items: center; }
.home-cta .go { margin-top: 0; }
.home-hot { color: #c9a86a; }
.home-card .go.sv-sec { background: rgba(216,176,120,.10); border: 1px solid rgba(216,176,120,.32);
  color: var(--ok); box-shadow: none; width: auto; }
.home-card .go.sv-sec:hover { background: linear-gradient(180deg, #93c95e, #7cb14a);
  color: #fff; border-color: transparent; box-shadow: 0 3px 0 #567f31; }

/* ---------- settings (board & pieces) ---------- */
#setBtn { margin-left: auto; background: none; border: 1px solid rgba(255,255,255,.14);
  border-radius: 999px; color: var(--ink2); font-size: .95rem; line-height: 1;
  padding: .32rem .6rem; cursor: pointer; }
#setBtn:hover { color: var(--ok); border-color: rgba(216,176,120,.5); }
#tabs #loglink { margin-left: .4rem; }
.set-panel { position: fixed; top: 3.2rem; right: .8rem; z-index: 90;
  width: min(420px, 94vw); max-height: min(80vh, 640px); overflow-y: auto;
  background: var(--panelbg, #0d1626);
  border: 1px solid var(--panelline, #223453); border-radius: 8px;
  padding: 1rem 1.1rem 1.05rem;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.06), 0 18px 50px rgba(0,0,0,.55); }
.set-panel h3 { margin: 0; font-size: 1.02rem; }
.set-h { font-family: var(--sans); font-size: .66rem; letter-spacing: .14em;
  text-transform: uppercase; color: var(--ink2); margin: .75rem 0 .45rem; }
.set-swatches { display: grid; grid-template-columns: repeat(4, 1fr); gap: .5rem; }
.swatch { position: relative; aspect-ratio: 1; border-radius: 10px; overflow: hidden;
  border: 2px solid rgba(255,255,255,.13); background-size: cover; background-position: center;
  cursor: pointer; padding: 0; }
.swatch.p { background: rgba(255,255,255,.07); display: flex; align-items: center;
  justify-content: center; }
.swatch.p img { width: 74%; height: 74%; object-fit: contain; margin-bottom: .5rem; }
.swatch span { position: absolute; left: 0; right: 0; bottom: 0;
  font-family: var(--sans); font-size: .58rem; padding: .12rem 0 .18rem;
  background: rgba(5,15,26,.78); color: var(--ink2); text-align: center; }
.swatch:hover { border-color: rgba(216,176,120,.45); }
.swatch.sel { border-color: var(--acc); box-shadow: 0 0 0 2px rgba(216,176,120,.35); }
.swatch.sel span { color: var(--acc); }
.set-credits { margin-top: .85rem; font-family: var(--sans); font-size: .63rem;
  color: var(--ink2); line-height: 1.55; }

/* ---------- bell + releases + big next ---------- */
#bellBtn { position: relative; background: none; border: 1px solid rgba(255,255,255,.14);
  border-radius: 999px; color: var(--ink2); padding: .34rem .6rem .22rem; cursor: pointer;
  margin-left: auto; }
#bellBtn:hover { color: var(--ok); border-color: rgba(216,176,120,.5); }
#bellBtn + #setBtn { margin-left: .4rem; }
#bellDot { position: absolute; top: -5px; right: -5px; min-width: 15px; height: 15px;
  border-radius: 999px; background: #a06060; color: #fff; font-style: normal;
  font-family: var(--sans); font-size: .6rem; font-weight: 700; line-height: 15px;
  text-align: center; padding: 0 3px; box-shadow: 0 0 0 2px rgba(7,20,34,.9); }
.rel-card h3 small { white-space: nowrap; }
@keyframes svpop { from { transform: scale(.94); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { }

/* ---------- Nihal game database ---------- */
.ndb-filters { display: flex; gap: .55rem; flex-wrap: wrap; margin: 1rem 0 .8rem; }
.ndb-filters input, .ndb-filters select { background: var(--surface2);
  border: 1px solid rgba(255,255,255,.14); border-radius: 9px; color: var(--ink);
  font-family: var(--sans); font-size: .82rem; padding: .45rem .7rem; }
.ndb-filters input { flex: 1 1 220px; }
.ndb-filters input:focus, .ndb-filters select:focus { outline: none;
  border-color: rgba(216,176,120,.55); }
.ndb-scroll { overflow-x: auto; border: 1px solid rgba(255,255,255,.09);
  border-radius: 12px; background: linear-gradient(180deg, rgba(13,32,50,.94), rgba(9,24,40,.92)); }
.ndb-table { width: 100%; border-collapse: collapse; font-family: var(--sans);
  font-size: .8rem; }
.ndb-table th { position: sticky; top: 0; text-align: left; cursor: pointer;
  background: rgba(7,20,34,.97); color: var(--ink2); font-size: .66rem;
  text-transform: uppercase; letter-spacing: .1em; padding: .55rem .7rem;
  border-bottom: 1px solid rgba(255,255,255,.12); white-space: nowrap; user-select: none; }
.ndb-table th:hover { color: var(--ok); }
.ndb-table th.on { color: var(--ok); }
.ndb-table th.on::after { content: " ↕"; opacity: .8; }
.ndb-table td { padding: .42rem .7rem; border-bottom: 1px solid rgba(255,255,255,.05);
  white-space: nowrap; }
.ndb-table td.ndb-ev { max-width: 24ch; overflow: hidden; text-overflow: ellipsis; }
.ndb-table tbody tr { cursor: pointer; }
.ndb-table tbody tr:hover { background: rgba(216,176,120,.09); }
.ndb-table td small { color: var(--ink2); margin-left: .25rem; }
.ndb-mvlist { margin-top: .7rem; max-height: 34vh; overflow-y: auto; line-height: 1.9;
  font-family: var(--mono); font-size: .78rem; }
.ndb-mvlist i { color: var(--ink2); font-style: normal; margin: 0 .15rem 0 .35rem; }
.ndb-mvlist button { background: none; border: none; color: var(--ink);
  font: inherit; padding: .05rem .28rem; border-radius: 5px; cursor: pointer; }
.ndb-mvlist button:hover { background: rgba(216,176,120,.18); }
.ndb-mvlist button.past { color: #a8c6de; }
.ndb-mvlist button.cur { background: rgba(216,176,120,.18); color: #7ec8ff; }

/* ---------- Stockfish 18 panel ---------- */
.sf-row { margin-top: .55rem; }
.sf-btn.on { background: linear-gradient(180deg, #93c95e, #7cb14a); color: #fff;
  border-color: transparent; }
.sf-panel { margin-top: .5rem; background: rgba(7,20,34,.72); border: 1px solid rgba(255,255,255,.1);
  border-radius: 10px; padding: .6rem .7rem; }
.sf-pv { font-family: var(--mono); font-size: .72rem; color: #8fb8d8;
  overflow-wrap: anywhere; line-height: 1.5; }
.sf-note { font-family: var(--sans); font-size: .75rem; color: var(--ink2); }

.ndb-var { margin-top: .6rem; padding: .5rem .6rem; background: rgba(216,176,120,.1);
  border: 1px solid rgba(216,176,120,.35); border-radius: 9px; font-family: var(--sans);
  font-size: .78rem; display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; }
.ndb-vtag { font-size: .62rem; text-transform: uppercase; letter-spacing: .1em; color: var(--ok); }
.ndb-vsan { font-family: var(--mono); color: var(--ink); }
.ndb-var .sv-ghost { margin-left: auto; font-size: .72rem; }
#ndbBoard { cursor: pointer; }

/* ---------- sleek pass: move list, engine panel, toggles ---------- */
[hidden] { display: none !important; }
.ndb-mvlist { max-height: 36vh; border: 1px solid rgba(255,255,255,.08); border-radius: 10px;
  background: rgba(7,20,34,.55); padding: .25rem 0; line-height: 1.45; font-size: .8rem; }
.ndb-mvlist .mrow { display: grid; grid-template-columns: 2.6em 1fr 1fr; align-items: stretch; }
.ndb-mvlist .mrow:hover { background: rgba(255,255,255,.04); }
.ndb-mvlist .mrow i { color: rgba(169,204,236,.45); font-style: normal; text-align: right;
  padding: .12rem .55em .12rem 0; font-size: .72rem; margin: 0; }
.ndb-mvlist button { text-align: left; padding: .12rem .5rem; border-radius: 0; margin: 0;
  color: var(--ink); }
.ndb-mvlist button:hover { background: rgba(216,176,120,.22); }
.ndb-mvlist button.past { color: #9fc0da; }
.ndb-mvlist button.cur { background: rgba(216,176,120,.18); color: #7ec8ff; border-radius: 5px; font-weight: 400; }
.ndb-var { padding: .42rem .6rem; font-size: .74rem; border-radius: 8px; }
.sf-row { margin-top: .6rem; }
.sf-btn { width: 100%; display: flex; align-items: center; gap: .5rem;
  background: rgba(255,255,255,.04); border: 1px solid rgba(255,255,255,.14);
  color: var(--ink2); font-size: .78rem; padding: .48rem .8rem; border-radius: 9px;
  box-shadow: none; }
.sf-btn::after { content: "off"; margin-left: auto; font-size: .62rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink2); }
.sf-btn.on { background: rgba(216,176,120,.12); border-color: rgba(216,176,120,.5);
  color: var(--ok); }
.sf-btn.on::after { content: "on"; color: var(--ok); }
.sf-btn:hover { border-color: rgba(216,176,120,.55); color: var(--ok); }
.sf-panel { background: rgba(7,20,34,.72); padding: .55rem .65rem .35rem; }
.sf-top { gap: .55rem; }
.sf-eval { font-size: 1.3rem; letter-spacing: -.02em; }
.sf-evalbar { height: 6px; margin: .4rem 0 .3rem; }
.sf-line { display: grid; grid-template-columns: 3.6em 1fr; gap: .55rem; align-items: baseline;
  padding: .2rem .15rem; border-top: 1px solid rgba(255,255,255,.05); }
.sf-line:hover { background: rgba(255,255,255,.04); }
.sf-line:first-of-type .sf-lpv { color: #cfe2f2; }
.sf-lsc { min-width: 0; text-align: right; }
.sf-lpv { font-size: .73rem; white-space: normal; display: -webkit-box;
  -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; line-height: 1.45; }
.ndb-mvlist::-webkit-scrollbar, .sf-panel::-webkit-scrollbar { width: 8px; }
.ndb-mvlist::-webkit-scrollbar-thumb { background: rgba(255,255,255,.14); border-radius: 4px; }

/* ---------- per-move engine rail ---------- */
.ndb-mvlist .mrow { grid-template-columns: 2.6em 1fr 1fr 4.4em; }
.mrail { display: flex; flex-direction: column; justify-content: center; gap: 1px;
  padding-right: .5rem; }
.mev { font-family: var(--mono); font-size: .58rem; line-height: 1.25;
  text-align: right; color: rgba(169,204,236,.55); font-variant-numeric: tabular-nums;
  border-right: 2px solid transparent; padding-right: .3rem; font-weight: 400; }
.mev.q-top { border-right-color: #7cb14a; color: var(--ok); }
.mev.q-ok { border-right-color: rgba(255,255,255,.18); }
.mev.q-mid { border-right-color: #c9a86a; color: #e8c98a; }
.mev.q-bad { border-right-color: #a06060; color: #a06060; font-weight: 700; }
.ga-btn { margin-top: .4rem; }
.ga-btn::after { content: ""; }

/* ---------- eval graph + rail refinement ---------- */
.ndb-graph { margin-top: .6rem; border: 1px solid rgba(255,255,255,.1); border-radius: 10px;
  overflow: hidden; cursor: pointer; background: rgba(7,20,34,.62);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.05); }
.ndb-graph svg { display: block; }
.ndb-graph:hover { border-color: rgba(216,176,120,.4); }
.mev { border-right: none; border-left: 2px solid transparent; padding: 0 .4rem 0 .32rem;
  font-size: .6rem; letter-spacing: .01em; }
.mev.q-top { border-left-color: #7cb14a; border-right-color: transparent; }
.mev.q-ok { border-left-color: rgba(255,255,255,.16); border-right-color: transparent; }
.mev.q-mid { border-left-color: #c9a86a; border-right-color: transparent; }
.mev.q-bad { border-left-color: #a06060; border-right-color: transparent; }
.ndb-mvlist .mrow.currow { background: rgba(216,176,120,.08); }
.ndb-mvlist .mrow.currow i { color: var(--ok); }
.ga-btn { transition: background .2s; }

/* ---------- one-surface clean pass (Nihal card) ---------- */
.ndb-side .ndb-headline { font-family: var(--sans); font-size: .78rem; color: var(--ink2);
  margin-bottom: .55rem; letter-spacing: .01em; }
.ndb-side .ndb-headline em { font-style: normal; }
.ndb-side .pov-w { color: var(--ok); }
.ndb-side .pov-l { color: #a06060; }
.ndb-side .pov-d { color: var(--ink2); }
.ndb-toprow { display: flex; align-items: center; justify-content: space-between;
  gap: .6rem; padding-bottom: .55rem; border-bottom: 1px solid rgba(255,255,255,.08); }
.seg { display: flex; border: 1px solid rgba(255,255,255,.16); border-radius: 9px;
  overflow: hidden; }
.seg button { background: none; border: none; color: var(--ink2); font-family: var(--sans);
  font-size: .78rem; padding: .4rem .75rem; cursor: pointer; box-shadow: none; }
.seg button + button { border-left: 1px solid rgba(255,255,255,.12); }
.seg button:hover { background: rgba(255,255,255,.06); color: var(--ink); }
.seg .seg-go { color: var(--ok); }
.seg .seg-go:hover { background: rgba(216,176,120,.16); }
.eng-ctl { display: flex; gap: .3rem; }
.ndb-side .sf-btn { width: auto; background: none; border: none; box-shadow: none;
  color: var(--ink2); font-family: var(--sans); font-size: .74rem; padding: .35rem .5rem;
  border-radius: 7px; display: inline-flex; }
.ndb-side .sf-btn::after { content: none; }
.ndb-side .sf-btn:hover { background: rgba(255,255,255,.06); color: var(--ink); }
.ndb-side .ndb-graph { margin-top: .55rem; border: none; border-radius: 8px;
  background: rgba(0,0,0,.18); box-shadow: none; }
.ndb-side .ndb-var { background: none; border: none; border-left: 2px solid #2a4360;
  border-radius: 0; padding: .3rem 0 .3rem .6rem; margin-top: .55rem; }
.ndb-side .ndb-mvlist { border: none; border-radius: 0; background: none;
  border-top: 1px solid rgba(255,255,255,.08); border-bottom: 1px solid rgba(255,255,255,.08);
  margin-top: .55rem; padding: .2rem 0; max-height: 34vh; }
.ndb-side .ndb-mvlist button { font-size: .84rem; }
.ndb-foot { margin-top: .55rem; font-family: var(--sans); font-size: .74rem; }
.ndb-foot a { color: #8fb8d8; text-decoration: none; border-bottom: 1px dotted rgba(143,184,216,.4); }
.ndb-foot a:hover { color: var(--ok); }

/* ---------- lichess-scale toggle + readable engine lines ---------- */
.eng-toggle { position: relative; display: inline-flex; align-items: center; gap: .55rem;
  background: none; border: none; box-shadow: none; cursor: pointer;
  font-family: var(--sans); font-size: .84rem; font-weight: 600; color: var(--ink2);
  padding: .3rem .45rem .3rem .2rem; border-radius: 8px; }
.eng-toggle:hover { color: var(--ink); background: rgba(255,255,255,.05); }
.eng-toggle .tgl { flex: none; width: 44px; height: 24px; border-radius: 999px;
  background: rgba(255,255,255,.13); border: 1px solid rgba(255,255,255,.2);
  box-shadow: inset 0 1px 3px rgba(0,0,0,.45); transition: background .18s, border-color .18s;
  position: relative; display: block; }
.eng-toggle .tgl i { position: absolute; top: 2px; left: 2px; width: 18px; height: 18px;
  border-radius: 50%; background: #cfd8dc; transition: left .18s, background .18s;
  box-shadow: 0 1px 2px rgba(0,0,0,.5); }
.eng-toggle.on { color: var(--ok); }
.eng-toggle.on .tgl { background: #2a4360; border-color: rgba(216,176,120,.45); }
.eng-toggle.on .tgl i { left: 22px; background: #fff; }
.ndb-side .eng-toggle::before { content: none; }
.ndb-side .eng-toggle { padding: .3rem .45rem .3rem .2rem; }
.sf-line { grid-template-columns: 3.9em 1fr; padding: .3rem .1rem; align-items: center; }
.sf-lsc { font-size: .84rem; }
.sf-lpv { font-size: .87rem; line-height: 1.4; white-space: nowrap; display: block;
  overflow: hidden; text-overflow: ellipsis; -webkit-line-clamp: unset;
  -webkit-box-orient: unset; }
.ndb-side .sf-line + .sf-line { border-top: 1px solid rgba(255,255,255,.06); }

/* toprow breathing room */
.ndb-toprow { flex-wrap: wrap; row-gap: .45rem; }
.ndb-toprow .seg button, .eng-toggle, .eng-review { white-space: nowrap; }
.eng-ctl { align-items: center; gap: .45rem; }

/* ---------- structure strip + figurine size ---------- */
.fg { font-size: 1.32em; line-height: 0; vertical-align: -.07em; }
.ndb-struct { font-family: var(--sans); font-size: .76rem; color: var(--ink2);
  margin-bottom: .5rem; display: flex; flex-wrap: wrap; gap: .3rem .9rem; }
.ndb-struct .stx { display: inline-flex; align-items: baseline; gap: .45rem; color: var(--ok); }
.ndb-struct button { background: none; border: none; padding: 0; cursor: pointer;
  font: inherit; color: inherit; box-shadow: none; }
.ndb-struct .stx-jump { color: var(--ok); font-weight: 600; }
.ndb-struct .stx-jump:hover { text-decoration: underline; }
.ndb-struct .stx-plans, .ndb-struct .stx-go { color: #8fb8d8; font-size: .7rem; }
.ndb-struct .stx-plans:hover, .ndb-struct .stx-go:hover { color: var(--ok); }
.stx-planbox { flex-basis: 100%; display: grid; grid-template-columns: 1fr 1fr; gap: .8rem;
  padding: .55rem 0 .2rem; border-top: 1px solid rgba(255,255,255,.07); margin-top: .2rem; }
.stx-planbox b { color: var(--ink); font-size: .72rem; text-transform: uppercase;
  letter-spacing: .08em; font-weight: 600; }
.stx-planbox ol { margin: .3rem 0 0; padding-left: 1.1rem; }
.stx-planbox li { font-size: .74rem; line-height: 1.45; margin: .2rem 0; color: var(--ink2); }
.stx-src { grid-column: 1 / -1; font-size: .64rem; color: rgba(169,204,236,.55); }
.ndb-table td.ndb-st { color: var(--ok); font-size: .74rem; max-width: 18ch;
  overflow: hidden; text-overflow: ellipsis; }

/* ---------- players selector + book annotations ---------- */
.ndb-players { display: flex; gap: .45rem; flex-wrap: wrap; margin-top: .8rem; }
.ndb-players button { background: rgba(255,255,255,.05); border: 1px solid rgba(255,255,255,.14);
  border-radius: 999px; color: var(--ink2); font-family: var(--sans); font-size: .8rem;
  font-weight: 600; padding: .42rem 1rem; cursor: pointer; box-shadow: none; }
.ndb-players button:hover { color: var(--ink); border-color: rgba(216,176,120,.45); }
.ndb-players button.on { background: linear-gradient(180deg, #93c95e, #7cb14a);
  border-color: transparent; color: #fff; }
.ndb-note { margin-top: .6rem; font-family: Georgia, serif; font-size: .86rem;
  line-height: 1.6; color: #dbe7f2; padding: .55rem .7rem .55rem .85rem;
  border-left: 2px solid rgba(111,174,138,.55); background: rgba(255,255,255,.03);
  border-radius: 0 8px 8px 0; }
.ndb-qm { color: var(--ok); font-size: 1.1em; margin-right: .25rem; }
.ndb-qsrc { display: block; margin-top: .3rem; font-family: var(--sans); font-size: .66rem;
  color: var(--ink2); }
.ndb-mvlist button.noted { text-decoration: underline dotted rgba(111,174,138,.6); text-underline-offset: 3px; }

/* ---------- games-by-structure home ---------- */
.stxc-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: .6rem; margin-top: 1rem; }
.stxc { text-align: left; background: var(--card);
  border: 1px solid var(--line); border-radius: 8px; padding: .8rem .95rem;
  cursor: pointer; display: flex; flex-direction: column; gap: .25rem; box-shadow: none; }
.stxc:hover { border-color: rgba(216,176,120,.5); }
.stxc b { color: var(--ok); font-size: .95rem; }
.stxc-n { font-family: var(--mono); font-size: .78rem; color: var(--ink); }
.stxc-who { font-family: var(--sans); font-size: .66rem; color: var(--ink2); line-height: 1.5; }
.stx-lhead { margin-top: 1rem; display: flex; align-items: baseline; gap: .8rem; flex-wrap: wrap; }
.stx-lhead a { font-family: var(--sans); font-size: .78rem; color: #8fb8d8; text-decoration: none; }
.stx-lhead a:hover { color: var(--ok); }
.stx-home .ndb-scroll { margin-top: .6rem; }
.ndb-players .stx-pill { border-style: dashed; }
.ndb-players .stx-pill.on { border-style: solid; }

/* ---------- quiet solver card ---------- */
@keyframes segpulse { 0%,100% { background: transparent; } 50% { background: rgba(216,176,120,.25); } }
#tab-solve .sf-row .eng-toggle { padding-left: 0; }

/* ---------- the solve strip ----------
   (FOCUS MODE RETIRED 2026-08-12 with its button — a second layout for
   "the board is the hero", which the board-first law has guaranteed by
   default since 2026-08-10. Every body.svfocus rule in the six files
   that carried it died in the same commit.) */
.solve-top { display: flex; align-items: center; justify-content: flex-end; gap: .45rem; }
.solve-top > a:first-child { margin-right: auto; }

/* ---------- lab social: deck card, chat drawer, likes ---------- */
.solve-side { position: relative; }
.solve-side::before, .solve-side::after { content: ""; position: absolute; inset: 0;
  border-radius: inherit; background: rgba(13,32,50,.55);
  border: 1px solid rgba(255,255,255,.07); z-index: -1; }
.solve-side::before { transform: rotate(1.4deg) translate(7px, 5px); }
.solve-side::after { transform: rotate(-1deg) translate(-6px, 8px); opacity: .6; }
#labChat { position: fixed; top: 0; right: 0; bottom: 0; width: 300px; z-index: 60;
  background: var(--surface); border-left: 1px solid var(--hairline);
  display: flex; flex-direction: column; }
body.lc-on .solve-grid, body.lc-on .wrap { margin-right: 310px; }
body.lc-on #tabs { padding-right: 320px; }
@media (max-width: 1100px){ body.lc-on .solve-grid { margin-right: 0; } }
.lc-head { display: flex; align-items: center; gap: .5rem; padding: .8rem .9rem;
  border-bottom: 1px solid var(--hairline); font-family: var(--sans); }
.lc-head b { font-size: .9rem; letter-spacing: .06em; }
.lc-user { color: var(--ok); font-size: .8rem; flex: 1; }
.lc-auth { padding: .8rem .9rem; border-bottom: 1px solid rgba(255,255,255,.08);
  display: flex; flex-direction: column; gap: .5rem; }
.lc-auth input { background: var(--surface2); border: 1px solid rgba(255,255,255,.14);
  border-radius: 8px; color: var(--ink); font-family: var(--sans); font-size: .82rem;
  padding: .45rem .6rem; }
.lc-authrow { display: flex; gap: .5rem; }
.lc-authmsg { font-size: .75rem; color: #ff9db0; min-height: 1em; }
.lc-body { flex: 1; overflow-y: auto; padding: .7rem .9rem; display: flex;
  flex-direction: column; gap: .55rem; }
.lc-msg { font-family: var(--sans); font-size: .82rem; line-height: 1.45; color: var(--ink); }
.lc-msg b { color: var(--acc); }
.lc-t { color: rgba(207,232,255,.35); font-size: .7rem; font-family: var(--mono); }
.lc-chip { font-family: var(--mono); font-size: .7rem; color: var(--ok);
  border: 1px solid rgba(216,176,120,.4); border-radius: 6px; padding: .05rem .35rem;
  cursor: pointer; text-decoration: none; }
.lc-chip:hover { background: rgba(216,176,120,.15); }
.lc-port { flex: 1; overflow-y: auto; padding: .7rem .9rem; display: flex;
  flex-direction: column; gap: .5rem; }
.lc-pcard { font-family: var(--sans); font-size: .8rem; border: 1px solid rgba(255,255,255,.1);
  border-radius: 10px; padding: .5rem .65rem; display: flex; gap: .5rem; align-items: baseline; }
.lc-pcard.go { cursor: pointer; }
.lc-pcard.go:hover { border-color: var(--accdim); }
.lc-pcard b { font-family: var(--mono); font-size: .72rem; color: var(--acc); }
.lc-pcard span { flex: 1; color: var(--ink2); }
.lc-pcard em { color: rgba(207,232,255,.4); font-style: normal; font-size: .72rem; }
.lc-inrow { display: flex; gap: .5rem; padding: .7rem .9rem;
  border-top: 1px solid rgba(255,255,255,.08); }
.lc-inrow input { flex: 1; background: var(--surface2); border: 1px solid rgba(255,255,255,.14);
  border-radius: 999px; color: var(--ink); font-family: var(--sans); font-size: .82rem;
  padding: .5rem .85rem; }
/* redesign: the drawn card */
.sv-card #svBoard svg { width: min(66vh, 600px); height: auto; display: block; }

.sv-boardcol { display: flex; flex-direction: column; gap: .55rem; align-items: flex-start; }
.sv-card { position: relative; background: var(--cardsolid); border: 1px solid var(--hairline3);
  border-radius: 10px; padding: 14px 16px 12px; display: flex; flex-direction: column; gap: 11px; }
.sv-card::before, .sv-card::after { content: ""; position: absolute; inset: 0; z-index: -1;
  border-radius: 10px; background: var(--ghost1); border: 1px solid var(--ghost1l); }
.sv-card::before { transform: translate(13px, 13px); }
.sv-card::after { transform: translate(7px, 7px); background: var(--ghost2); border-color: var(--ghost2l); }
#svCardId { font-family: var(--mono); font-size: .92rem; color: var(--acc); letter-spacing: .02em; }
.sv-statusrow { display: flex; align-items: baseline; gap: 11px;
  border-top: 1px solid var(--hairline); padding-top: 9px; }
.sv-statusrow h2 { margin: 0; font-size: .92rem; font-weight: 500; color: var(--ink); font-family: var(--sans); }
.solve-side::before, .solve-side::after { display: none; }

/* portfolio minis */
.lc-pcard { flex-direction: column; align-items: stretch; }
.lc-prow { display: flex; gap: .5rem; align-items: baseline; }
.lc-prow span { flex: 1; color: var(--ink2); }
.lc-mini { margin-top: .5rem; border-radius: 4px; overflow: hidden; line-height: 0; }
.lc-mini svg { width: 100%; height: auto; display: block; }


/* theme-correct surfaces (must stay last: outranks the legacy reset by order) */
#tab-solve .solve-side { background: var(--card); border-color: var(--line); }


/* ---------- v2 density pass ---------- */
#tabs { height: 44px; gap: .95rem; }
#tabs button { height: 44px; font-size: .8rem; }
/* .set-navbtn's pill (26px !important border-radius era) retired with the
   doorframe — the gear is a strip utility now, sized by its lane */
/* the bell's 44px header sizing retired with the doorframe (2026-08-10) —
   the strip's utility lane (door-frame.css) sizes it now */

/* settings popover — it rises from the gear that opens it (2026-08-11).
   It used to be pinned to the LEFT, at 204 / 220 / 222 / 54px by four
   files: one per retired sidebar width (196, 212, 214) plus the 46px
   svpage rail. Every one of those columns is gone (--wb-left is 0,
   workbench.css sets body{padding-left:0 !important}), so the panel was
   opening ~1150px away from its own button, which the doorframe put in
   the strip's utility lane at the bottom right. Those four rules are
   deleted; this is the panel's ONE position. The narrow full-width case
   is sidebar-nav.css's media block, which still loads after this. */
.set-panel { position: fixed; top: auto; bottom: 3rem; right: 14px; width: 372px; z-index: 80;
  background: var(--surface2); border: 1px solid var(--hairline3); border-radius: 8px;
  box-shadow: 0 18px 48px rgba(0,0,0,.6); padding: 4px 16px 14px; }
.set-row { display: flex; align-items: center; min-height: 38px; gap: .6rem; }
.set-row.set-head { min-height: 40px; }
.set-row.set-head b { font-size: .82rem; color: var(--ink); font-family: var(--sans); }
.set-row.set-tall { min-height: 52px; }
.set-sp { flex: 1; }
.set-x { background: none; border: none; color: var(--mut2); cursor: pointer; font-size: .78rem; padding: 2px 4px; }
.set-x:hover { color: var(--ink); }
.set-sec { font-family: var(--mono); font-size: .62rem; letter-spacing: .15em;
  color: var(--mut2); padding: 9px 0 2px; border-top: 1px solid var(--hairline); margin-top: 5px; }
.set-sec:first-of-type { border-top: none; margin-top: 0; }
.set-lbl { font-size: .76rem; color: var(--ink2); }
.set-panel h3, .set-panel .set-h { display: none; }
.set-panel .set-swatches { display: flex; gap: 7px; flex-wrap: wrap; justify-content: flex-end; }
.set-credits { font-family: var(--mono); font-size: .62rem; color: var(--mut2);
  border-top: 1px solid var(--hairline); padding-top: 9px; margin-top: 5px; }

/* chat resting rail */
#labChat { width: 34px; transition: width .18s ease; overflow: hidden; }
#labChat.open { width: 272px; }
.lc-rail { position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; padding: 10px 0 12px; gap: 12px; cursor: pointer; }
#labChat.open .lc-rail { display: none; }
.lc-vert { writing-mode: vertical-rl; font-family: var(--mono); font-size: .64rem;
  letter-spacing: .2em; color: var(--mut); }
.lc-unbadge { font-family: var(--mono); font-size: .64rem; color: var(--paper);
  background: var(--acc); border-radius: 4px; padding: 1px 5px; }
.lc-full { display: none; flex-direction: column; height: 100%; width: 272px; }
#labChat.open .lc-full { display: flex; }
body { margin-right: 34px; }
body.lc-on { margin-right: 0; }
body.lc-on .solve-grid, body.lc-on .wrap { margin-right: 282px; }
body.lc-on #tabs { padding-right: 292px; }
body:not(.lc-on) #tabs { padding-right: 48px; }
@media (max-width: 900px){
  body { margin-right: 0; }
  #labChat { display: none; }
  #labChat.open { display: flex; width: min(320px, 92vw); }
  body.lc-on .solve-grid, body.lc-on .wrap { margin-right: 0; }
  body.lc-on #tabs { padding-right: 1.6rem; }
}

/* solve density */
.sv-card { padding: 10px 12px 9px; gap: 8px; border-radius: 8px; }
.sv-card::before { transform: translate(10px, 10px); }
.sv-card::after { transform: translate(5px, 5px); }
#svCardId { font-size: .8rem; }
.sv-statusrow { padding-top: 7px; gap: 9px; }
.sv-statusrow h2 { font-size: .82rem; }
.solve-side { padding: .95rem 1rem 1.05rem; }
.solve-top { min-height: 34px; }

/* popover-scale swatches */
.set-panel .set-swatches { display: grid; grid-template-columns: repeat(6, 44px); gap: 7px; }
.set-panel .swatch { width: 44px; height: 44px; border-radius: 6px; background-size: cover; }
.set-panel .swatch span { font-size: .5rem; padding: 1px 0; }
.set-panel .swatch.sel { box-shadow: 0 0 0 2px var(--accdim); border-color: var(--acc); }
.set-panel .swatch.sel span { color: var(--acc); }
.set-panel .swatch:hover { border-color: var(--accdim); }
.set-panel .set-pieces { grid-template-columns: repeat(6, 44px); }
.set-panel .swatch.p img { width: 70%; height: 70%; margin-bottom: .35rem; }
/* A SWATCH ROW OWNS ITS OWN LINE (2026-07-30 pm). Six 44px swatches plus five
   7px gaps is 299px, and the panel's content box is 336px — so a row that put
   an inline label BESIDE the grid had 37px for the label and overflowed on
   anything longer. PIECES had been over by 2px since it shipped (invisible,
   inside the panel's padding); BOARD's wider "Theme" label pushed the same
   grid to 376px, i.e. past the 372px panel itself, and clipped Glass off the
   end. Stacking the label kills the class rather than the instance: the grid
   gets the full content width, and a seventh theme wraps instead of vanishing. */
.set-row.set-tall { align-items: flex-start; padding: 6px 0;
  flex-direction: column; gap: 6px; }
.set-row.set-tall .set-lbl { padding-top: 0; }
.set-row.set-tall .set-sp { display: none; }
.set-panel .set-row.set-tall .set-swatches { justify-content: flex-start; }

/* v2 side panel + coordinates */
.sv-brdrow { display: flex; }
.sv-ranks { display: grid; grid-template-rows: repeat(8, 1fr); width: 13px; }
.sv-ranks span { font-family: var(--mono); font-size: .58rem; color: var(--mut2);
  display: flex; align-items: center; }
.sv-files { display: grid; grid-template-columns: repeat(8, 1fr); margin-left: 13px; margin-top: -2px; }
.sv-files span { font-family: var(--mono); font-size: .58rem; color: var(--mut2); text-align: center; }
.solve-side.v2 { display: flex; flex-direction: column; gap: .8rem; width: 232px; padding: .4rem .2rem; 
  background: none !important; border: none; box-shadow: none; }
.solve-side.v2 .sv-bar { height: 2px; background: var(--hairline2); border-radius: 1px; }
.solve-side.v2 .sv-bar i { display: block; height: 2px; background: var(--acc); border-radius: 1px; }
.solve-side.v2 .sf-row { margin: 0; }

/* ---------- SPEC SYNC: Deep Water exact values (last of its ERA —
   it corrects the chrome-redesign layer before it; the manifest holds
   this file in place) ---------- */
:root { --mut3:#6b7f99; --chatbg:#0a1220; --panelbg:#0d1626; --panelline:#223453; --accborder:#2a4360; }
#tabs { padding: 0 20px; gap: 20px; }
#tabs::before { font-size: 14px; }
#tabs .tabs-inner, #tabs button { font-size: 12.5px; }
#tabs button { color: var(--mut3); padding: 0; }
#tabs button.on { color: var(--ink); }
#tabs button:hover:not(.on) { color: var(--ink); }
#labChat { background: var(--chatbg); }
/* skin only — the panel's POSITION left this rule 2026-08-11 and lives
   once, in chrome-redesign.css, anchored to the gear that opens it */
.set-panel { background: var(--panelbg); border-color: var(--panelline);
  padding: 6px 18px 16px; }
#svCardId { font-size: 13px; }
.sv-statusrow h2 { font-size: 12px; font-weight: 400; color: #c6d5e6; }
.sv-ranks span, .sv-files span { font-size: 9.5px; }
.solve-side.v2 { width: 208px; gap: 14px; }
.lc-msg { font-size: 12px; line-height: 1.45; color: #c6d5e6; }
.lc-msg > div:first-child, .lc-msg b { font-size: 10.5px; }
.lc-msg b { color: var(--ink2); font-weight: 400; }
.lc-t { font-size: 10px; }
.lc-chip { font-size: 9.5px; border-color: var(--accborder); }
.lc-head b { font-size: 10px; font-family: var(--mono); font-weight: 400;
  letter-spacing: .16em; color: var(--mut); text-transform: uppercase; }
.lc-inrow input { font-size: 12px; padding: 6px 9px; border-radius: 5px; }
.sv-card #svBoard svg { width: min(66vh, 640px); }
.solve-grid { gap: 36px; padding: 28px 32px 24px; }
.set-row .set-lbl { font-size: 12px; }
.set-row.set-head b { font-size: 13px; }
.set-sec { font-size: 10px; }
table tr:hover, .ndb-row:hover, .stlib-row:hover { background: var(--panelbg); }

/* ---------- Nihal / list density (spec) ---------- */
.ndb-head { padding: 20px 0 4px; display: flex; flex-direction: column; gap: 10px; }
.ndb-titlerow { display: flex; align-items: baseline; gap: 12px; }
.ndb-titlerow h1 { margin: 0; font-family: var(--sans); font-size: 18px; font-weight: 600;
  color: var(--ink); letter-spacing: 0; }
.ndb-meta { font-family: var(--mono); font-size: 10.5px; color: var(--mut); }
.ndb-subrow { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.ndb-players { display: flex; gap: 6px; flex-wrap: wrap; margin: 0; }
.ndb-players button { font-size: 11.5px; padding: 4px 10px; border-radius: 5px;
  background: none; border: 1px solid var(--btnline); color: var(--ink2); box-shadow: none; }
.ndb-players button:hover { border-color: #33507d; color: #c6d5e6; }
.ndb-players button.on { color: var(--acc); border-color: var(--accborder);
  background: rgba(216,176,120,0.08); font-weight: 400; }
.ndb-statline { font-family: var(--mono); font-size: 11px; color: var(--mut); }
.ndb-statline em { font-style: normal; }
.ndb-statline .ok { color: var(--ok); } .ndb-statline .bad { color: #a06060; }
.ndb-filters { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin: 10px 0 12px; }
.ndb-filters input, .ndb-filters select { font-family: var(--sans); font-size: 11.5px;
  color: var(--ink2); background: none; border: 1px solid var(--btnline); border-radius: 5px;
  padding: 4px 10px; height: auto; }
.ndb-filters input { min-width: 200px; background: var(--surface2); }
.ndb-filters select:hover, .ndb-filters input:focus { border-color: #33507d; color: #c6d5e6; }
.ndb-table { border-collapse: collapse; width: 100%; }
.ndb-table th { font-family: var(--mono); font-size: 9.5px; font-weight: 400;
  letter-spacing: .1em; text-transform: uppercase; color: var(--mut2); text-align: left;
  padding: 0 10px 6px; border-bottom: 1px solid var(--hairline2); }
.ndb-table th.on { color: var(--acc); }
.ndb-table td { font-size: 12px; color: #c6d5e6; height: 30px; padding: 0 10px;
  border-bottom: 1px solid #10192b; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ndb-table tbody tr { cursor: pointer; }
.ndb-table tbody tr:hover { background: var(--panelbg); }
.ndb-table td:first-child, .ndb-table td:nth-child(3), .ndb-table td:nth-child(5),
.ndb-table td:nth-child(8), .ndb-table td:nth-child(9) { font-family: var(--mono); font-size: 11px; color: var(--mut); }
.ndb-table td:nth-child(3) { color: var(--ink2); }
.ndb-table td:nth-child(6) { font-size: 11.5px; color: var(--ink2); }
.ndb-table td:nth-child(7) { font-size: 11.5px; color: var(--mut3); }
.ndb-table td:nth-child(9) { text-align: right; }
.ndb-table .res { font-style: normal; font-family: var(--mono); font-size: 11px; color: var(--ink2); }
.ndb-table .res.ok { color: var(--ok); }
.ndb-table .res.bad { color: #a06060; }

/* ---------- FULL SPEC SWEEP (last of its era, same law as above) ---------- */
/* nav v3 */
#tabs::before { content: none; }
#wordmark { font-family: var(--sans); font-weight: 600; font-size: 14px; color: var(--ink);
  letter-spacing: .01em; white-space: nowrap; margin-right: .9rem; cursor: pointer; }
#loglink { font-family: var(--mono); font-size: 11px; color: var(--mut2); }
#loglink:hover { color: var(--ink2); }
#bellBtn { color: var(--mut2); } #bellBtn:hover { color: var(--ink2); }

/* global controls to spec */
button, .abtn { background: none; border: 1px solid var(--line-card, #26395a); border-color: #26395a;
  border-radius: 5px; color: var(--ink2); font-size: 12px; font-family: var(--sans);
  transition: color .12s ease, border-color .12s ease, background .12s ease; box-shadow: none; text-shadow: none; }
button:hover, .abtn:hover { border-color: #33507d; color: #c6d5e6; }
button.primary, .primary { background: none !important; border: 1px solid var(--accborder) !important;
  color: var(--acc) !important; box-shadow: none !important; font-weight: 400 !important; }
button.primary:hover, .primary:hover { background: var(--wash06, rgba(216,176,120,.06)) !important; }
:root { --wash06: rgba(216,176,120,.06); }
input, select, textarea { background: var(--surface2); border: 1px solid var(--btnline);
  border-radius: 5px; color: #c6d5e6; font-family: var(--sans); font-size: 12px;
  transition: border-color .12s ease, box-shadow .12s ease; }
input:hover, select:hover { border-color: #33507d; }
input:focus, select:focus, button:focus-visible { outline: none; border-color: #33507d;
  box-shadow: 0 0 0 2px rgba(216,176,120,.25); }
::placeholder { color: #455a73; }

/* scrollbars */
* { scrollbar-width: thin; scrollbar-color: #1e2f4c transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #1e2f4c; border-radius: 5px; border: 2px solid var(--paper); }
::-webkit-scrollbar-thumb:hover { background: #2a4360; }

/* page-header compression (every hero) */
.hero, .pos-head { padding: 20px 0 4px !important; margin: 0 !important;
  background: none !important; border: none !important; }
.wrap > header { background: none; border: none; padding-left: 0; padding-right: 0; }
.hero h1, .pos-head h1, .wrap header h1 { font-family: var(--sans); font-size: 18px !important;
  font-weight: 600; letter-spacing: 0; margin: 0 0 4px; color: var(--ink); }
.eyebrow { font-family: var(--mono) !important; font-size: 10px !important;
  letter-spacing: .1em !important; color: var(--mut2) !important; text-transform: uppercase; margin: 0 0 2px !important; }
.lede-line { display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical;
  overflow: hidden; font-size: 12.5px !important; color: var(--mut3) !important;
  max-width: 720px; line-height: 1.5 !important; margin: 0 !important; }
.lede-more { font-family: var(--mono); font-size: 10.5px; color: var(--mut); display: inline-block; margin-top: 2px; }
.lede-more:hover { color: var(--ink2); }
.lede:not(.lede-line) { font-size: 12.5px; color: var(--mut3); max-width: 720px; }

/* dialog */
#labDialog[hidden] { display: none; }
#labDialog .ld-scrim { position: fixed; inset: 0; background: rgba(4,8,16,.6); z-index: 90; }
#labDialog .ld-card { position: fixed; top: 50%; left: 50%; transform: translate(-50%,-50%);
  width: 420px; max-width: 90vw; max-height: 76vh; overflow-y: auto; z-index: 91;
  background: var(--panelbg); border: 1px solid var(--panelline); border-radius: 8px;
  box-shadow: 0 18px 48px rgba(2,6,14,.66); padding: 18px 20px; }
#labDialog .ld-x { position: absolute; top: 10px; right: 10px; border: none; color: var(--mut2); font-size: 12px; }
#labDialog .ld-x:hover { color: var(--ink); }
#labDialog .ld-body { font-size: 12.5px; color: var(--ink2); line-height: 1.6; }
#labDialog .ld-body b { color: var(--ink); }

/* editorial prose + footer + misc deviations */
.wrap > section { background: none; border: none; padding-left: 0; padding-right: 0; }
.wrap p, details p { font-size: 13px; color: var(--ink2); line-height: 1.65; max-width: 720px; }
footer.wrap { font-family: var(--mono); font-size: 10px; color: var(--mut2); text-align: center;
  padding: 28px 0; text-shadow: none; }
.vb.check { color: #c9a86a; }

/* solve status states + engine chrome */
.st-ok { font-style: normal; color: var(--ok); }
.st-bad { font-style: normal; color: #a06060; }
.sf-panel { background: var(--panelbg); border: 1px solid var(--panelline); border-radius: 5px; }
.eng-toggle { border: 1px solid var(--btnline) !important; font-family: var(--mono); font-size: 11px; }
.eng-toggle.on, .eng-toggle[aria-pressed="true"] { color: var(--acc); border-color: var(--accborder) !important;
  background: var(--wash06) !important; }

/* list rows: hover-only actions + density */
.stlib-row { min-height: 40px; }
.stlib-row .stlib-acts { opacity: 0; transition: opacity .12s ease; }
.stlib-row:hover .stlib-acts { opacity: 1; }
.stlib-names { font-size: 12px; }
.stlib-names small { font-family: var(--mono); font-size: 11px; color: var(--mut); }
.stlib-elo { font-family: var(--mono); font-size: 11px; color: var(--mut); }

/* green-era controls -> spec system */
.sv-sec, .sv-sec.go, .sv-sec.shuf { border-color: #26395a !important; color: var(--ink2) !important;
  background: none !important; box-shadow: none !important; }
.sv-sec:hover { border-color: #33507d !important; color: #c6d5e6 !important; }
.sv-sec.go { color: var(--acc) !important; border-color: var(--accborder) !important; }
.sv-sec.go:hover { background: var(--wash06) !important; }
.chip { font-family: var(--mono); font-size: 10.5px; color: var(--mut);
  border: 1px solid var(--btnline); border-radius: 4px; background: none; box-shadow: none; }
.chip.ok { color: var(--ok); border-color: rgba(111,174,138,.4); background: none; }
.chip.bad { color: #a06060; border-color: rgba(160,96,96,.4); }
#tab-home .stat-big, .card .big, .prognum { color: var(--acc) !important; }


/* reconcile layer — stays after the era sections it retires */
a:hover { color:#b3ddff; }
body { font-size:14.5px; }
section h2 { font-size:16px; font-weight:600; }
.pos-book h2 { font-size:15px; }
#quiz h1 { font-size:18px; font-weight:600; }
.solve-side h2 { font-size:15px; }
.strip { background:none; border:none; border-top:1px solid var(--hairline); border-bottom:1px solid var(--hairline); border-radius:0; }
.strip div { border-right:1px solid var(--hairline); }
.strip .n { color:var(--acc); font-size:1.25rem; }
.tally div { background:var(--card); border:1px solid var(--line); border-top:2px solid var(--ok); }
.tally div.mid { border-top-color:#c9a86a; } .tally div.bad { border-top-color:var(--bad); }
blockquote { border-left:2px solid var(--hairline3); }
ol.proc li::before { color:var(--mut2); }
.pg-head { color:var(--mut2); }
tr.clickable:hover td, .al:hover, .unit:hover { background:var(--panelbg); }
figure.pat.clickable:hover, .stpat:hover, .stxc:hover, details.part2:hover { border-color:#33507d; }
details.part2, .stpat { border-radius:8px; }
.unit-list { background:none; border:0; border-radius:0; }
#xbtn:hover, #xbtn:focus { border-color:#33507d; color:var(--ink); }
.ndb-table th:hover { color:var(--ink2); }
.stxc b { color:var(--ink); }
.ndb-struct .stx { color:var(--ink2); }
.ndb-struct .stx-jump { color:var(--acc); }
.ndb-note { font-family:var(--sans); border-left:2px solid var(--hairline3); background:none; border-radius:0; }
.sf-pv, .sf-lpv { color:var(--mut); }
.sf-line:first-of-type .sf-lpv { color:#c6d5e6; }
.sf-eval { color:var(--ok); }
.eng-toggle.on .tgl { background:var(--accborder); border-color:var(--accdim); }
.ndb-mvlist button.cur { background:var(--acc-wash); color:var(--acc); font-weight:400; }
.ndb-mvlist .mrow.currow { background:rgba(216,176,120,.06); }
.mev.q-top { border-left-color:var(--ok); color:var(--ok); }
.chbar { height:2px; background:var(--hairline2); border-radius:1px; }
.chbar i { background:var(--acc); border-radius:1px; }
.sv-bar { height:2px; background:var(--hairline2); border-radius:1px; }
.sv-bar i { background:var(--acc); height:2px; border-radius:1px; }
.home-big { color:var(--acc); }
.home-hot { color:#c9a86a; }
.pulse { animation:none; }
.tq-opts button { background:none; border:1px solid var(--btnline); box-shadow:none; border-radius:5px; font-weight:400; }
.tq-opts button:hover:not(:disabled) { border-color:#33507d; color:#c6d5e6; }
.tq-opts button.right { color:var(--ok); border-color:rgba(111,174,138,.5); background:rgba(111,174,138,.08); }
.tq-opts button.wrong { color:var(--bad); border-color:rgba(160,96,96,.5); background:rgba(160,96,96,.08); }
.vz-plist { background:var(--card); border-radius:5px; }
.lc-user { color:var(--ink2); }
.lc-chip { color:var(--acc); }
.lc-chip:hover { background:rgba(216,176,120,.08); }
.lc-authmsg { color:#a06060; }
.lc-auth input { border-radius:5px; }
.ndb-foot a, .stx-lhead a { color:var(--acc); border-bottom-color:var(--accfaint); }
.ndb-foot a:hover, .stx-lhead a:hover { color:#b3ddff; border-bottom-color:var(--accdim); }
.seg { border:1px solid var(--btnline); border-radius:5px; }
.seg button + button { border-left:1px solid var(--btnline); }
.seg .seg-go { color:var(--acc); }
.seg .seg-go:hover { background:var(--wash06); }
#setBtn:hover { color:var(--ink); border-color:#33507d; }
#bellBtn:hover { color:var(--ink2); }
#bellDot { background:var(--acc); color:#0a111c; box-shadow:0 0 0 2px var(--surface); }
button:hover, .abtn:hover { border-color:#33507d; }
.swatch:hover { border-color:var(--accdim); }
/* nihal table: spec grid + quiet dots + nav weight */
#tabs button { font-weight: 400; }
#tabs button.on { font-weight: 500; }
.ndb-table { table-layout: fixed; }
.ndb-table th:nth-child(1), .ndb-table td:nth-child(1) { width: 78px; }
.ndb-table th:nth-child(3), .ndb-table td:nth-child(3) { width: 58px; }
.ndb-table th:nth-child(4), .ndb-table td:nth-child(4) { width: 60px; }
.ndb-table th:nth-child(5), .ndb-table td:nth-child(5) { width: 44px; }
.ndb-table th:nth-child(6), .ndb-table td:nth-child(6) { width: 150px; }
.ndb-table th:nth-child(8), .ndb-table td:nth-child(8) { width: 88px; }
.ndb-table th:nth-child(9), .ndb-table td:nth-child(9) { width: 52px; }
.ndb-table .side-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block;
  vertical-align: baseline; margin-right: 4px; opacity: .75; box-shadow: none; }
.ndb-table .side-dot.sw { background: #d7e3f2; border: none; }
.ndb-table .side-dot.sb { background: #22313f; border: 1px solid #45587a; }


/* positional unit rows: two columns since the id badge was removed */
.unit { grid-template-columns: 1fr 7.5rem; }

/* ---------- solved popup (shared by all puzzle surfaces) ---------- */
#winPop { position: fixed; inset: 0; z-index: 95; display: none;
  align-items: center; justify-content: center;
  background: rgba(4,8,16,.52); backdrop-filter: blur(2.5px); -webkit-backdrop-filter: blur(2.5px); }
#winPop.open { display: flex; }
.wp-card { width: min(21rem, calc(100vw - 2.5rem)); text-align: center;
  background: var(--panelbg, #0d1626); border: 1px solid var(--panelline, #223453);
  border-radius: 12px; padding: 1.6rem 1.7rem 1.25rem;
  box-shadow: 0 24px 70px rgba(0,0,0,.55); animation: wpin .16s ease-out; }
.wp-mark { width: 2.7rem; height: 2.7rem; margin: 0 auto .65rem; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 1.25rem; color: var(--ok); border: 1.5px solid currentColor; }
.wp-title { margin: 0 0 .3rem; font-size: 1.18rem; letter-spacing: .01em; }
.wp-sub { margin: 0 0 1.1rem; font-size: .84rem; color: var(--ink2); line-height: 1.45; }
.wp-sub[hidden] { display: none; }
.wp-next { display: block; width: 100%; font-size: .95rem; font-weight: 600;
  padding: .6rem 1rem; cursor: pointer; }
.wp-next[hidden] { display: none; }
.wp-stay { display: inline-block; margin-top: .7rem; background: none; border: none;
  color: var(--ink2); font-size: .76rem; cursor: pointer;
  text-decoration: underline; text-decoration-style: dotted; text-underline-offset: 3px; }
.wp-stay:hover { color: var(--ink); }
#winPop.neutral .wp-mark { color: var(--ink2); }
@keyframes wpin { from { opacity: 0; transform: translateY(8px) scale(.97); } }
@media (prefers-reduced-motion: reduce) { .wp-card { animation: none; } }

/* ---------- Opening Lab SESSIONS + shared ot components ----------
   Successor of openlab-trainer.css (2026-08-11): the page rules died with
   the legacy openings page; what lives here serves surfaces that are very
   much alive — the drill/spar session on the solve board (the master-book
   panel, the why-line), the engine v2 chrome, the sync tab's
   games grid chrome (ot-b / ot-eco / ot-linehead), and the settings
   inputs. The room's own furniture is openings-room.css (lr-*). */
.ot-b { font-style: normal; font-family: var(--mono); font-size: .62rem; padding: 0 .28em;
  border: 1px solid var(--hairline); border-radius: 4px; color: var(--ink2); }
.ot-b.sharp { color: var(--mid); border-color: var(--mid); }
.ot-b.only { color: var(--bad); border-color: var(--bad); font-weight: 700; }
.ot-b.alt { color: var(--mut); }
.ot-crumb { font-family: var(--mono); font-size: .72rem; color: var(--ink2);
  word-spacing: .12em; line-height: 1.6; }
.ot-note { margin-top: .5rem; font-size: .82rem; color: var(--ink2);
  border-left: 2px solid var(--acc); padding-left: .6rem; }
/* the sync tab's games grid head + empty note (13-ot-games renders both) */
.ot-linehead { font-family: var(--mono); font-size: .64rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--mut); padding: .5rem .6rem .3rem; }
.ot-lmeta { color: var(--mut2); font-size: .66rem; }
.set-num { background: var(--panelbg); color: var(--ink); border: 1px solid var(--hairline);
  border-radius: 5px; font-family: var(--mono); font-size: .74rem; padding: .2rem .35rem; width: auto; }
input.set-num { width: 3.4em; }
body.repmode #svLikeBtn, body.repmode #svCopyBtn { display: none; }

/* build-mode master book panel */
.ot-book { border: 1px solid var(--hairline); border-radius: 8px; background: var(--card);
  padding: .4rem .5rem .3rem; margin: .55rem 0 .1rem; }
.ot-bookhead { font-family: var(--mono); font-size: .64rem; letter-spacing: .06em;
  text-transform: uppercase; color: var(--mut); padding: .1rem .25rem .4rem; }
.ot-bookhead em.hot { color: var(--mid); font-style: normal; }
.ot-bookrow { display: flex; align-items: center; gap: .5rem; padding: .22rem .3rem;
  border-radius: 5px; cursor: pointer; font-family: var(--mono); font-size: .78rem; }
.ot-bookrow:hover { background: var(--surface2); }
.ot-bsan { min-width: 4.4em; color: var(--ink); white-space: nowrap; }
.ot-bbest { color: var(--mid); margin-left: .28em; font-style: normal; }
.ot-bknown { color: var(--green); margin-left: .28em; font-style: normal; }
.ot-bpct { width: 2.9em; text-align: right; color: var(--ink2); flex: none; }
.ot-bbar { flex: 1; display: flex; height: 9px; border-radius: 3px; overflow: hidden;
  border: 1px solid var(--hairline); min-width: 54px; }
.ot-bbar .w { background: #dfe7ee; }
.ot-bbar .d { background: rgba(143, 163, 187, .38); }
.ot-bbar .b { background: #1a2232; }
/* min-width, never width: "4,174,814" is 9 tabular digits and a fixed 4.6em
   box hard-clips the fact while the decorative bar keeps its flex slack */
.ot-bgames { min-width: 4.6em; text-align: right; color: var(--mut2); font-size: .66rem; flex: none; }
.ot-bookempty, .ot-booknote { font-family: var(--mono); font-size: .66rem; color: var(--mut);
  padding: .18rem .3rem .25rem; }

/* live SF18 evals inside the book panel */
.ot-bev { font-family: var(--mono); font-size: .68rem; color: var(--ink); flex: none;
  min-width: 3.2em; text-align: right; }
.ot-bev.neg { color: var(--bad); }
.ot-bookrow.eng { border-top: 1px dashed var(--hairline); border-radius: 0; margin-top: .15rem;
  padding-top: .3rem; }
.ot-bookrow.eng + .ot-bookrow.eng { border-top: none; margin-top: 0; padding-top: .22rem; }
.ot-bengtag { flex: 1; text-align: right; font-family: var(--mono); font-size: .6rem;
  color: var(--mut); letter-spacing: .04em; }

/* engine panel v2 — lichess-style rows + header */
.sf-cand.v2 { display: flex; align-items: flex-start; gap: .55rem; padding: .34rem .45rem;
  margin: 0; border: none; background: none; border-radius: 7px; cursor: pointer; }
.sf-cand.v2:hover { background: var(--surface2); }
.sf-cand.v2 .sf-chip { flex: none; font-family: var(--mono); font-size: .74rem; font-weight: 700;
  background: #e8eef4; color: #0e1522; border-radius: 6px; padding: .12rem .38rem;
  min-width: 3.5em; text-align: center; margin-top: .12rem; box-sizing: border-box; }
.sf-cand.v2 .sf-pv { flex: 1; min-width: 0; font-family: var(--mono); font-size: .78rem;
  color: var(--ink); line-height: 1.75; white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; word-spacing: .1em; }
.sf-cand.v2.sel .sf-pv { white-space: normal; }
.sf-cand.v2 .sf-caret { flex: none; color: var(--mut); font-size: .58rem; padding-top: .34rem; }
.sf-cand.v2 .pvm:hover { color: var(--acc); }
.sf-cand.v2 .sf-cann { color: var(--mid); font-size: .68rem; }
.sf-btn.v2::after { content: none; }
.sf-btn.v2 { font-size: .86rem; }
.sf-btn.v2 .eng-depth { margin-left: auto; font-family: var(--mono); font-size: .68rem;
  color: var(--ink2); letter-spacing: .02em; }
.sf-btn.v2 .eng-name { font-family: var(--mono); font-size: .68rem; color: var(--ink2); }
#pvPeek { position: fixed; top: 0; left: 0; width: 176px; z-index: 240; pointer-events: none;
  opacity: 0; transition: opacity .1s; border: 1px solid var(--hairline); border-radius: 9px;
  overflow: hidden; box-shadow: 0 12px 36px rgba(0,0,0,.55); background: var(--card); }
#pvPeek.on { opacity: 1; }
#pvPeek .pvpeek-b { line-height: 0; }
#pvPeek .pvpeek-b svg { display: block; width: 100%; height: auto; }

/* engine header v3 — reference match: pill+check · Analysis · ••• · depth | name · gear */
.sf-row.v2 { display: flex; align-items: center; gap: .55rem; padding: .15rem 0; }
.sf-row.v2 .sf-btn.v2 { width: auto; flex: none; padding: .28rem .1rem; border: none;
  background: none; box-shadow: none; font-size: .95rem; font-weight: 600; color: var(--ink);
  gap: .6rem; letter-spacing: 0; }
.sf-row.v2 .sf-btn.v2.on { background: none; border: none; color: var(--ink); }
.sf-row.v2 .sf-btn.v2:hover { border: none; color: var(--ink); }
.sf-row.v2 .sf-dots { color: var(--mut); letter-spacing: .12em; cursor: pointer;
  font-size: .95rem; padding: .1rem .15rem; user-select: none; }
.sf-row.v2 .sf-dots:hover { color: var(--ink); }
.sf-row.v2 .sf-hsp { flex: 1; }
.sf-row.v2 .eng-depth, .sf-row.v2 .eng-name { font-family: var(--sans); font-size: .82rem;
  color: var(--ink2); white-space: nowrap; }
.sf-row.v2 .sf-gear { color: var(--mut); cursor: pointer; font-size: 1rem; user-select: none; }
.sf-row.v2 .sf-gear:hover { color: var(--ink); }
.eng-toggle.v2 .tgl i { display: flex; align-items: center; justify-content: center; }
.eng-toggle.v2 .tgl i::after { content: "✓"; font-size: 11px; font-weight: 700;
  color: #2a313d; opacity: 0; line-height: 1; }
.eng-toggle.v2.on .tgl i::after { opacity: 1; }
/* chips — white rounded, shared by engine rows and book rows */
.sf-cand.v2 .sf-chip { background: #f2f4f6; color: #15181d; font-family: var(--mono);
  font-weight: 700; font-size: .8rem; border-radius: 8px; padding: .18em .5em;
  min-width: 3.6em; text-align: center; margin-top: .05rem; box-sizing: border-box; }
.sf-cand.v2 .sf-pv { font-family: var(--sans); font-size: .86rem; font-weight: 500;
  color: var(--ink); line-height: 1.75; letter-spacing: .01em; }
.sf-cand.v2 .sf-caret { padding-top: .4rem; }
.ot-bev { background: #f2f4f6; color: #15181d; font-weight: 700; border-radius: 7px;
  padding: .08em .4em; min-width: 3.2em; text-align: center; font-size: .66rem; }
.ot-bev.neg { color: #15181d; }

.sf-cand.v2 { flex-direction: row; }

.sf-row.v2 .sf-btn.v2 { text-transform: none; letter-spacing: .01em; }
.sf-row.v2 .eng-toggle.v2 .tgl { background: #39414f; border-color: #39414f; }
.sf-row.v2 .eng-toggle.v2.on .tgl { background: #dfe7ee; border-color: #dfe7ee; }
.sf-row.v2 .eng-toggle.v2.on .tgl i { background: #fff; }
.sf-row.v2 .eng-depth, .sf-row.v2 .eng-name { font-size: .74rem; }
.sf-row.v2 .eng-name { overflow: hidden; text-overflow: ellipsis; flex: 0 1 auto; min-width: 0; }

.sf-row.v2 .eng-toggle .tgl { width: 44px; height: 24px; }
.sf-row.v2 .eng-toggle .tgl i { width: 18px; height: 18px; top: 2px; left: 2px; }
.sf-row.v2 .eng-toggle.on .tgl i { left: 22px; }

.sf-row.v2 { flex-wrap: wrap; row-gap: .1rem; }
.sf-row.v2 .eng-depth { margin-left: auto; }

/* ---------- left sidebar navigation (grouped accordion) ---------- */
#tabs { position: fixed; top: 0; left: 0; bottom: 0; width: 214px; height: auto;
  flex-direction: column; align-items: stretch; flex-wrap: nowrap;
  overflow-y: auto; overflow-x: hidden; padding: .9rem .7rem 1rem; gap: .1rem;
  z-index: 60; background: var(--surface);
  border-right: 1px solid var(--hairline); border-bottom: none; box-shadow: none; }
#tabs::before { content: none; }
#wordmark { display: block; font-family: var(--sans); font-weight: 600; font-size: 1.02rem;
  color: var(--ink); cursor: pointer; padding: .15rem .45rem .85rem; }
#tabs .sg { display: flex; flex-direction: column; }
#tabs .sg-lbl { font-family: var(--mono); font-size: .64rem; letter-spacing: .13em;
  text-transform: uppercase; color: var(--mut); padding: .5rem .45rem; }
#tabs .sg-body { display: flex; flex-direction: column; padding: 0 0 .3rem; }
#tabs .sg-body button[data-tab] { width: 100%; height: auto; text-align: left;
  padding: .4rem .5rem .4rem 1.05rem; border: none; border-left: 2px solid transparent;
  border-bottom: none; border-radius: 0 6px 6px 0; font-size: .84rem; }
#tabs .sg-body button[data-tab].on { color: var(--ink); border-left-color: var(--acc);
  border-bottom: none; background: var(--surface2); font-weight: 500; }
#tabs .side-sp { flex: 1; min-height: .8rem; }
#tabs #bellBtn { align-self: flex-start; margin-left: .3rem; height: auto; }
#tabs #setBtn { align-self: flex-start; margin: .35rem 0 0 .3rem; }
#tabs #loglink { margin: .55rem 0 0 .5rem; }
body { padding-left: 214px; }
body.lc-on #tabs { padding-right: .7rem; }
/* (the .set-panel left-pin for a 214px sidebar died 2026-08-11 — the
   panel's one position is chrome-redesign.css's, anchored to its gear) */
#sideTgl { display: none; position: fixed; top: .55rem; left: .55rem; z-index: 70;
  font-size: 1.05rem; line-height: 1; background: none; color: var(--ink);
  border: 0; border-radius: 0; padding: .38rem .6rem; cursor: pointer; }
#sideBk { position: fixed; inset: 0; background: rgba(0, 0, 0, .45); z-index: 59; }
@media (max-width: 900px){
  body { padding-left: 0; }
  #sideTgl { display: block; }
  #tabs { transform: translateX(-105%); transition: transform .18s ease; width: 240px;
    box-shadow: 10px 0 34px rgba(0, 0, 0, .5); }
  body.sideopen #tabs { transform: translateX(0); }
  .set-panel { left: .8rem; right: .8rem; bottom: 3.4rem; width: auto; }
}

/* solver: solution notation + variation analysis */

/* (the tree/linelist/gap-panel ot- blocks that closed this file died
   2026-08-11 with the legacy openings page; the surviving ot- chrome —
   session book panel, sync grid head — lives in ot-session.css) */

/* ---- articles: study editions ---- */
.art-flow { max-width: 46rem; margin: 0 auto; padding: 0 1.2rem 3rem; }
.art-h { font-size: 1.22rem; margin: 2.3rem 0 .5rem; }
.art-p { font-family: Georgia, serif; font-size: .95rem; line-height: 1.62; margin: .8rem 0; }
.art-fig { margin: 1.5rem auto; text-align: center; cursor: pointer; }
.art-figbrd { width: min(340px, 86vw); margin: 0 auto; border-radius: 6px; overflow: hidden;
  box-shadow: 0 8px 26px rgba(0,0,0,.45); }
.art-figbrd svg, .art-cardbrd svg { display: block; width: 100%; height: auto; }
.art-fig:hover .art-figbrd { outline: 2px solid rgba(216,176,120,.5); }
.art-fig figcaption { font-family: var(--sans); font-size: .74rem; color: var(--ink2); margin-top: .5rem; }
.art-gamecard { display: flex; gap: 1rem; align-items: center; margin: 1.3rem 0; padding: .8rem;
  border: 1px solid rgba(255,255,255,.14); border-radius: 12px; cursor: pointer;
  background: rgba(255,255,255,.03); }
.art-gamecard:hover { border-color: rgba(216,176,120,.55); background: rgba(216,176,120,.06); }
.art-cardbrd { flex: 0 0 132px; border-radius: 5px; overflow: hidden; }
.art-cardmeta { display: flex; flex-direction: column; gap: .25rem; font-family: var(--sans); }
.art-cardmeta b { font-size: 1.02rem; }
.art-cardmeta span { font-size: .78rem; color: var(--ink2); }
.art-cardmeta .art-cardgo { color: var(--ok); font-size: .8rem; margin-top: .25rem; }
.art-src { margin: 2.4rem 0 0; padding: .7rem .9rem; border-left: 2px solid #2a4360;
  font-family: var(--sans); font-size: .78rem; color: var(--ink2); }
.art-note { margin-top: .6rem; font-family: Georgia, serif; font-size: .88rem; line-height: 1.55;
  padding: .55rem .7rem; background: rgba(111,174,138,.08); border-left: 2px solid var(--ok);
  border-radius: 0 8px 8px 0; }
.art-moves { margin-top: .7rem; font-size: .92rem; line-height: 2.0; max-height: 44vh;
  overflow-y: auto; padding-right: .3rem; }
.art-moves .artm { background: none; border: none; color: var(--ink); font-family: inherit;
  font-size: inherit; padding: 0 .14rem; cursor: pointer; border-radius: 4px; }
.art-moves .artm:hover { background: rgba(216,176,120,.18); }
.art-moves .artm.cur { background: #7ec8ff; color: #06121f; }
.art-moves .artm.cur .fg, .art-moves .artm.cur i { color: #06121f; }
.art-moves .artm.noted { border-bottom: 2px dotted var(--ok); }
.art-moves .artm.d1 { color: var(--ink2); font-size: .9em; }
.art-moves .artm.d2, .art-moves .artm.d3 { color: var(--ink2); opacity: .78; font-size: .85em; }
.art-moves .art-par { color: var(--ink2); opacity: .6; }
.art-moves .art-start { font-family: var(--sans); font-size: .74rem; color: var(--ink2); }
.art-moves .art-res { font-family: var(--sans); font-weight: 700; margin-left: .3rem; }
.art-moves .artm i { font-style: normal; font-weight: 700; }
.art-moves .ng-good, .art-moves .ng-brill { color: var(--ok); }
.art-moves .ng-bad, .art-moves .ng-blun { color: #e08585; }
.art-moves .ng-int, .art-moves .ng-dub { color: #d9b86a; }

.ot-b.ot-eco { flex: none; font-weight: 600; color: var(--sea, #7fb3d3);
  border-color: color-mix(in srgb, var(--sea, #7fb3d3) 50%, transparent); min-width: 2.1em; text-align: center; }

.ot-linegrp { display: flex; align-items: center; gap: .5rem; padding: .42rem .6rem .3rem;
  cursor: pointer; border-top: 1px solid var(--hairline); font-size: .78rem; }
.ot-linegrp:first-of-type { border-top: none; }
.ot-linegrp:hover { background: var(--surface2); }
.ot-linegrp b { font-weight: 600; letter-spacing: .01em; }
.ot-gcaret { font-style: normal; color: var(--mut2); flex: none; width: .8em; }
.ot-linegrp .ot-ldrill { margin-left: auto; opacity: 0; flex: none; }
.ot-linegrp:hover .ot-ldrill { opacity: 1; }
.ot-linerow { padding-left: 1.6rem; }
.ot-lvar { flex: none; color: var(--ink); max-width: 38%; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.ot-lvar + .ot-lsan { color: var(--mut2); }
.art-picker { margin-top: 1rem; }
.art-head { margin: .4rem 0 1.6rem; padding-bottom: 1.1rem; border-bottom: 1px solid rgba(255,255,255,.1); }
.art-title { font-size: 1.55rem; margin: 0 0 .35rem; }
.art-byline { font-family: var(--sans); font-size: .78rem; color: var(--ink2); margin-bottom: .8rem; }
.art-blurb { font-size: 1.02rem; color: var(--ink); }


/* scoped to #tab-home so releases and other tabs keep the old card look */
#tab-home .wrap { max-width: 68rem; }
#tab-home .pos-head h1 { font-size: 26px !important; font-weight: 650;
  letter-spacing: -.01em; margin-top: 2px !important; }
#tab-home .ex-stats { justify-content: flex-start; gap: .5rem; margin-top: 1rem; }
#tab-home .home-grid { grid-template-columns: repeat(4, 1fr); gap: 14px; margin-top: 1.6rem; }
#tab-home .home-card { border-radius: 10px; padding: 15px 17px 14px; gap: 6px; }
#tab-home .hc-tag { font-family: var(--mono); font-size: 9.5px; letter-spacing: .13em;
  text-transform: uppercase; color: var(--mut); }
#tab-home .home-card h3 { display: block; font-size: 15px; font-weight: 600; letter-spacing: 0; }
#tab-home .home-big { color: var(--ink); font-size: 24px; margin-top: 4px; }
#tab-home .home-big.empty { color: var(--mut2); font-weight: 500; }
#tab-home .home-big small { color: var(--mut); }
#tab-home .home-sub { font-size: 12px; line-height: 1.45; color: var(--ink2); min-height: 2.7em; }
#tab-home .home-card .sv-bar { margin-top: 4px; }
#tab-home .home-cta { align-items: center; margin-top: auto; padding-top: 8px; }
#tab-home .home-cta .go { font-size: 12px; padding: .42rem .8rem; border-radius: 7px; }
#tab-home .home-cta .shuf { color: var(--mut); font-size: 11.5px; padding: .42rem .3rem; }
#tab-home .home-cta .shuf:hover { color: var(--ink2); }

/* hero: the resume card — full width, the one filled CTA on the page */
#tab-home .home-card.home-hero { grid-column: 1 / -1; display: grid;
  grid-template-columns: minmax(0,1fr) auto; column-gap: 2rem; align-items: center;
  padding: 24px 26px; border-radius: 12px; background: var(--cardsolid);
  border: 1px solid var(--hairline3); box-shadow: 0 1px 0 rgba(255,255,255,.04) inset; }
#tab-home .home-card.home-hero .home-big { font-size: 30px; }
#tab-home .home-card.home-hero .home-sub { min-height: 0; }
#tab-home .home-card.home-hero .sv-bar { max-width: 420px; margin-top: 8px; }
#tab-home .home-card.home-hero .home-cta { grid-row: 1 / span 5; grid-column: 2;
  flex-direction: column; align-items: stretch; gap: .5rem; padding-top: 0; }
/* the home hero's filled primary is retired with every other filled
   slab — the house verb (EOF layer) dresses it now */

#tab-home .home-card.home-hero button.primary:hover { background: var(--green2) !important;
  border-color: var(--green2) !important; }
#tab-home .home-card.home-hero .shuf { text-align: center; }

@media (max-width: 1150px) {
  #tab-home .home-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 640px) {
  #tab-home .home-grid { grid-template-columns: 1fr; }
  #tab-home .home-card.home-hero { grid-template-columns: 1fr; }
  #tab-home .home-card.home-hero .home-cta { grid-row: auto; grid-column: 1; margin-top: .8rem; }
}

/* sidebar legibility pass — group labels readable, items breathe */
#tabs { padding: 1.1rem .8rem 1rem; }
#wordmark { font-size: 1.08rem; padding-bottom: 1rem; }
#tabs .sg { margin-top: .45rem; }
#tabs .sg:first-of-type { margin-top: 0; }
#tabs .sg-lbl { font-size: .68rem; letter-spacing: .12em; color: var(--ink2); padding: .55rem .5rem; }
#tabs .sg-body button[data-tab] { font-size: .86rem; padding-top: .44rem; padding-bottom: .44rem; }


/* one skin, two token sets: SCORESHEET (light, default) and NOCTURNE
   (dark). The bare :root tokens are only the no-JS fallback — a head
   boot script sets data-lab-theme BEFORE CSS parses, so one of these
   blocks always wins. Preview without saving: report.html?theme=nocturne */



/* ---- shared mop-up: dark-era literals -> theme tokens --------- */











/* selected pills / primaries: ink on light, cream on dark */

 

 









/* deepwater text/hover literals -> theme tokens */












/* ---- chrome: sidebar + chat rail (both editorial themes) ------ */













/* ---------------- Home skin: one ruleset, per-theme vars -------- */







/* stat folio */







/* cards */












/* CTAs as editorial links */







/* hero: inverted plate */

 
 















/* ---- DEEP OCEAN — Kanagawa Wave palette -------------------------
   rebelot/kanagawa.nvim "wave" (deep ocean tones, after Hokusai's
   Great Wave): sumiInk blue-blacks, waveBlue panels, fujiWhite
   parchment text, crystalBlue accent, carpYellow highlight.
   Board stays the brightest element. ------------------------------ */





/* ocean selected pills / primaries: waveBlue2 fill, parchment text */






/* on any screen with a board, the board is the only saturated element —
   ambient chrome drops to neutral, only move feedback keeps color */
/* THE BOARD'S ONE EDGE (2026-07-30) — all boards are 360-viewBox svgs, so one
   rule is the whole edge treatment. It replaces a stack of three: a 7px
   --boardmat "gallery mat" that was invisible (#0b0e10 against #0e1113 paper)
   and, being content-box on a width:100% svg, pushed every rail board 14px
   wider than its host — measured 291px of board in a 279px pane, with the
   coverage ring clipped off the right-hand side in six rooms; a 1px --line
   host border in a navy (#1b2740) that belongs to no graphite token; and a
   3px radius that cropped the corner squares of a grid of squares.
   One hairline, border-box, square corners. */
svg[viewBox="0 0 360 360"] { border: 1px solid var(--hairline4, #2c353b);
  border-radius: 0; box-sizing: border-box; }

/* sidebar: no accent indicator while a board is up */
body.calmboard #tabs .sg-body button[data-tab].on { border-left-color: var(--hairline3); }

/* ambient links -> neutral */
#tab-solve a, #tab-positional a, #tab-quiz a, #tab-theme a,
#tab-vision a, #tab-structures a, #tab-articles a, #tab-openings a, #tab-nihal a {
  color: var(--ink2); text-decoration-color: color-mix(in srgb, var(--ink2) 35%, transparent); }
#tab-solve a:hover, #tab-positional a:hover, #tab-quiz a:hover,
#tab-theme a:hover, #tab-vision a:hover, #tab-structures a:hover, #tab-articles a:hover,
#tab-openings a:hover, #tab-nihal a:hover { color: var(--ink); }

/* primary buttons near boards -> quiet neutral fill */
#tab-solve button.primary, #tab-structures button.primary, #tab-vision button.primary,
#tab-theme button.primary, #tab-quiz button.primary {
  background: color-mix(in srgb, var(--ink) 9%, transparent) !important;
  color: var(--ink) !important; border-color: transparent !important; box-shadow: none !important; }
#tab-solve button.primary:hover, #tab-structures button.primary:hover,
#tab-vision button.primary:hover, #tab-theme button.primary:hover,
#tab-quiz button.primary:hover {
  background: color-mix(in srgb, var(--ink) 15%, transparent) !important; }

/* accent micro-elements -> neutral */
#tab-solve #svCardId { color: var(--ink2); }
#tab-solve .sv-bar i, #tab-vision .sv-bar i, #tab-structures .sv-bar i { background: var(--mut); }
#tab-solve .eng-toggle.on, #tab-vision .eng-toggle.on, #tab-nihal .eng-toggle.on {
  color: var(--ink2) !important; border-color: var(--btnlineh) !important;
  background: color-mix(in srgb, var(--ink) 5%, transparent) !important; }
#tab-solve .eng-toggle.on .tgl, #tab-vision .eng-toggle.on .tgl, #tab-nihal .eng-toggle.on .tgl {
  background: var(--btnlineh); border-color: var(--btnlineh); }
#tab-vision #vztDepth button.on { border-color: var(--btnlineh); color: var(--ink2);
  background: color-mix(in srgb, var(--ink) 5%, transparent); }
#tab-structures .sv-sec.go { color: var(--ink2) !important; border-color: var(--btnline) !important; }

/* article current-move highlight -> ink */
#tab-articles .artm.cur { background: var(--ink); color: var(--paper); }
#tab-articles .artm.noted { border-bottom-color: var(--mut); }
#tab-nihal .ndb-mvlist button.cur { background: color-mix(in srgb, var(--ink) 10%, transparent);
  color: var(--ink); }
#tab-nihal .ndb-mvlist .mrow.currow { background: color-mix(in srgb, var(--ink) 6%, transparent); }
#tab-nihal .ndb-struct .stx-jump { color: var(--ink2); }


/* rail */
.lc-rail { align-items: center; justify-content: center; cursor: pointer;
  color: var(--mut); transition: background .12s ease, color .12s ease; }
.lc-rail:hover { color: var(--ink); background: color-mix(in srgb, var(--ink) 6%, transparent); }
.lc-ico { display: block; }
.lc-unbadge { position: absolute; top: 9px; right: 4px; min-width: 15px; height: 15px;
  border-radius: 999px; background: var(--bad); color: #fff; font-family: var(--mono);
  font-size: 9px; font-weight: 700; line-height: 15px; text-align: center; padding: 0 3px; }

/* header */
.lc-head { padding: 11px 13px; border-bottom: 1px solid var(--hairline); gap: 7px; }
.lc-head b { font-family: var(--sans); font-size: 13.5px; font-weight: 650;
  letter-spacing: 0; color: var(--ink); text-transform: none; }
.lc-user { flex: 1; font-size: 11.5px; color: var(--mut);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lc-hbtn { background: none; border: none; color: var(--mut); font-family: var(--sans);
  font-size: 11px; padding: 3px 6px; cursor: pointer; border-radius: 5px; }
.lc-hbtn:hover { color: var(--ink); background: color-mix(in srgb, var(--ink) 6%, transparent); }
.lc-hbtn.lc-x { display: flex; align-items: center; padding: 4px; }

/* sign-in card */
.lc-auth { padding: 14px; border-bottom: 1px solid var(--hairline);
  display: flex; flex-direction: column; gap: 8px;
  background: color-mix(in srgb, var(--ink) 3%, transparent); }
.lc-authtitle { font-size: 12px; font-weight: 600; color: var(--ink); }
.lc-auth input { background: var(--card); border: 1px solid var(--btnline);
  border-radius: 6px; color: var(--ink); font-size: 12.5px; padding: 8px 10px; }
.lc-auth input:focus { outline: none; border-color: var(--accborder); }
.lc-authrow { display: flex; gap: 8px; align-items: center; }
.lc-primary { background: var(--acc); border: 1px solid var(--acc); color: var(--paper);
  border-radius: 6px; font-size: 12px; font-weight: 600; padding: 7px 14px; cursor: pointer; }
.lc-primary:hover { background: var(--green2); border-color: var(--green2); }
.lc-ghostbtn { background: none; border: none; color: var(--ink2); font-size: 12px;
  padding: 7px 6px; cursor: pointer; }
.lc-ghostbtn:hover { color: var(--ink); }
.lc-authmsg { color: var(--bad); font-size: 11.5px; min-height: 1em; }

/* messages: avatars, grouping, day separators */
.lc-body { padding: 10px 12px; }
.lc-day { display: flex; align-items: center; gap: 10px; margin: 10px 0 6px;
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--mut2); }
.lc-day::before, .lc-day::after { content: ""; flex: 1; border-top: 1px solid var(--hairline); }
.lc-day:first-child { margin-top: 0; }
.lc-msg { display: flex; gap: 8px; margin-top: 10px; }
.lc-msg.grouped { margin-top: 2px; }
.lc-msg.grouped .lc-ava { visibility: hidden; height: 0; }
.lc-msg.grouped .lc-mh { display: none; }
.lc-ava { flex: none; width: 26px; height: 26px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: rgba(255,255,255,.92); font-size: 11px; font-weight: 650; font-family: var(--sans); }
.lc-mw { min-width: 0; flex: 1; }
.lc-mh { display: flex; align-items: baseline; gap: 7px; }
.lc-mh b { font-size: 12px; font-weight: 650; color: var(--ink); }
.lc-t { font-family: var(--mono); font-size: 9.5px; color: var(--mut2); }
.lc-x { font-size: 12.5px; line-height: 1.5; color: var(--ink2); word-wrap: break-word; }
.lc-chip { display: inline-block; margin-top: 3px; font-family: var(--mono); font-size: 10px;
  color: var(--acc); border: 1px solid var(--accborder); border-radius: 5px;
  padding: 1px 6px; cursor: pointer; }
.lc-chip:hover { background: var(--wash06); }

/* composer */
.lc-inrow { padding: 10px 12px; border-top: 1px solid var(--hairline);
  gap: 8px; align-items: center; }
.lc-inrow input { background: var(--card); border: 1px solid var(--btnline);
  border-radius: 999px; color: var(--ink); font-size: 12.5px; padding: 8px 14px; }
.lc-inrow input:focus { outline: none; border-color: var(--accborder); }
.lc-inrow input:disabled { opacity: .55; }
.lc-send { flex: none; width: 34px; height: 34px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--acc); border: none; color: var(--paper); cursor: pointer; }
.lc-send:hover { background: var(--green2); }
.lc-send:disabled { background: color-mix(in srgb, var(--ink) 12%, transparent);
  color: var(--mut); cursor: default; }

/* portfolio cards */
.lc-pcard { border: 1px solid var(--hairline2); border-radius: 8px;
  padding: 9px 10px; background: var(--card); }
.lc-pcard.go:hover { border-color: var(--accborder); }
.lc-pcard b { color: var(--acc); }


#artNote { background: var(--card); border: 1px solid var(--hairline3);
  border-left: 3px solid var(--acc); border-radius: 6px; padding: 12px 14px; }


.pf-wrap { max-width: 62rem; padding: 2rem 1.2rem 3rem; }
.pf-idcard { display: flex; align-items: center; gap: 14px; background: var(--card);
  border: 1px solid var(--hairline2); border-radius: 10px; padding: 16px 18px; }
.pf-ava { flex: none; width: 56px; height: 56px; border-radius: 50%; display: flex;
  align-items: center; justify-content: center; color: rgba(255,255,255,.92);
  font-family: 'Libre Caslon Text', serif; font-size: 26px; font-weight: 700; }
.pf-ava.guest { background: var(--hairline3); color: var(--paper); }
.pf-idmain { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.pf-idmain b { font-family: 'Libre Caslon Text', serif; font-size: 22px; color: var(--ink); }
.pf-ranktitle { font-size: 13px; font-weight: 600; color: var(--acc); }
.pf-sub { font-size: 11.5px; color: var(--mut); }
.pf-btn { border-radius: 6px; font-size: 12px; padding: 7px 14px; cursor: pointer; }
.pf-btn.acc { font-weight: 400; } /* fill retired; the house PRIMARY verb dresses it */
.pf-btn.acc:hover { background: var(--green2); border-color: var(--green2); }
.pf-btn.ghost { background: none; border: 1px solid var(--btnline); color: var(--ink2); }
.pf-btn.ghost:hover { color: var(--ink); border-color: var(--btnlineh); }

.pf-grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-top: 14px; }
@media (max-width: 700px) { .pf-grid2 { grid-template-columns: 1fr; } }
.pf-card { background: var(--card); border: 1px solid var(--hairline2); border-radius: 10px;
  padding: 14px 16px; display: flex; flex-direction: column; gap: 9px; }
.pf-cardtag { font-family: var(--mono); font-size: 9.5px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--mut); }
.pf-ladder { display: flex; gap: 14px; }
.pf-step { font-size: 24px; color: var(--mut2); opacity: .45; cursor: default; }
.pf-step.on { color: var(--ink); opacity: 1; }
.pf-bar { height: 3px; background: var(--hairline2); border-radius: 2px; overflow: hidden; }
.pf-bar i { display: block; height: 100%; background: var(--acc); border-radius: 2px; }
.pf-cardsub { font-size: 12px; color: var(--ink2); }
.pf-cardsub b { color: var(--ink); font-variant-numeric: tabular-nums; }
.pf-nextrow { display: flex; gap: 10px; align-items: center; }
.pf-nextrow b { font-size: 13.5px; color: var(--ink); }
.pf-mono-badge { font-family: var(--mono); font-size: 10.5px; color: var(--mut);
  border: 1px solid var(--hairline3); border-radius: 5px; padding: 2px 6px; }

.pf-sec { margin: 1.8rem 0 .7rem; padding-top: 1rem; border-top: 1px solid var(--hairline);
  font-family: var(--mono); font-size: 10px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--mut); }
#pfBadges { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 10px; }
.pf-badge { background: var(--card); border: 1px solid var(--hairline2); border-radius: 8px;
  padding: 10px 12px; display: flex; flex-direction: column; gap: 4px; opacity: .5; }
.pf-badge b { font-size: 12.5px; color: var(--ink); }
.pf-badge span { font-size: 10.5px; color: var(--mut); }
.pf-badge.got { opacity: 1; border-color: var(--accborder); }
.pf-badge.got .pf-mono-badge { color: var(--acc); border-color: var(--accborder); }

.pf-tgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
.pf-tcard { background: var(--card); border: 1px solid var(--hairline2); border-radius: 8px;
  padding: 8px; display: flex; flex-direction: column; gap: 6px; }
.pf-tcard.go { cursor: pointer; }
.pf-tcard.go:hover { border-color: var(--accborder); }
.pf-mini { border-radius: 5px; overflow: hidden; line-height: 0; }
.pf-mini svg { width: 100%; height: auto; display: block; }
.pf-trow { display: flex; justify-content: space-between; align-items: baseline; }
.pf-trow b { font-family: var(--mono); font-size: 11px; color: var(--acc); }
.pf-trow em { font-style: normal; font-size: 10px; color: var(--mut2); }
.pf-tt { font-size: 11.5px; color: var(--ink2); white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; }
.pf-share { align-self: flex-start; background: none; border: 1px solid var(--btnline);
  border-radius: 5px; color: var(--mut); font-size: 10.5px; padding: 3px 8px; cursor: pointer; }
.pf-share:hover { color: var(--ink); border-color: var(--btnlineh); }
.pf-empty { border: 1px dashed var(--hairline3); border-radius: 10px; padding: 20px;
  font-size: 12.5px; color: var(--mut); line-height: 1.6; }


/* opening-dna insignia chips (profile + own chat messages) */
.pf-opens { display: flex; gap: 4px; margin-top: 2px; flex-wrap: wrap; }
.pf-open { font-family: var(--mono); font-size: 10px; color: var(--ink2);
  border: 1px solid var(--hairline3); border-radius: 4px; padding: 1px 5px;
  letter-spacing: .02em; }
.lc-mh .pf-open { margin-left: 2px; }


#tab-elite .el-viewseg { margin: .4rem 0 1rem; align-self: flex-start; }
#tab-elite .seg button.on { color: var(--ink); background: rgba(216,176,120,.14); }
#tab-elite .el-mut { color: var(--mut); font-weight: 300; }
#tab-elite .el-empty { padding: 1.6rem 1rem; color: var(--mut); font-size: .86rem;
  line-height: 1.6; text-align: center; }
#tab-elite .el-empty code { font-family: var(--mono); font-size: .78rem; color: var(--ink2); }
#tab-elite .el-linkbtn { background: none; border: none; color: var(--acc);
  cursor: pointer; font: inherit; text-decoration: underline; padding: 0; }

/* --- ratings view --- */
#tab-elite .el-rgrid { display: grid; grid-template-columns: minmax(0,1fr) minmax(300px,400px);
  gap: 1.1rem; align-items: start; }
#tab-elite .el-rscroll { max-height: 74vh; }
#tab-elite .el-rtable td, #tab-elite .el-rtable th { padding: .38rem .5rem; }
#tab-elite .el-rtable, #tab-elite .el-games { table-layout: auto; }
#tab-elite .el-rtable td:nth-child(2) { max-width: 21ch; overflow: hidden;
  text-overflow: ellipsis; }
#tab-elite .el-rtable tr[data-id] { cursor: pointer; }
#tab-elite .el-rtable tr.on td { background: rgba(216,176,120,.10); }
#tab-elite .el-rtable td:first-child { color: var(--mut); }
#tab-elite .el-r { font-family: var(--mono); font-size: .82rem; color: var(--ink);
  font-variant-numeric: tabular-nums; }
#tab-elite .el-up { color: var(--ok); font-family: var(--mono); font-size: .78rem; }
#tab-elite .el-dn { color: var(--bad); font-family: var(--mono); font-size: .78rem; }
#tab-elite .el-gcard { background: var(--card); border: 1px solid var(--hairline2);
  border-radius: 12px; padding: .9rem 1rem 1rem; position: sticky; top: 12px; }
#tab-elite .el-ghead { display: flex; flex-direction: column; gap: .3rem; margin-bottom: .55rem; }
#tab-elite .el-gname { display: flex; flex-direction: column; gap: 2px; }
#tab-elite .el-gname b { font-size: 1.02rem; color: var(--ink); }
#tab-elite .el-gname span { font-size: .76rem; }
#tab-elite .el-gname a { color: var(--acc); text-decoration: none; }
#tab-elite .el-gname a:hover { text-decoration: underline; }
#tab-elite .el-gcur { display: flex; gap: .9rem; flex-wrap: wrap; }
#tab-elite .el-gcur span { font-family: var(--mono); font-size: .68rem; color: var(--mut);
  letter-spacing: .04em; }
#tab-elite .el-gcur b { color: var(--ink); font-size: .8rem; margin-left: 2px; }
#tab-elite .el-series { align-self: flex-start; margin-bottom: .5rem; }
#tab-elite .el-graph { min-height: 120px; cursor: crosshair; }
#tab-elite .el-graph svg { display: block; }
#tab-elite .el-ax { fill: var(--mut); font-family: var(--mono); font-size: 9px; }
#tab-elite .el-gread { min-height: 1.2em; font-family: var(--mono); font-size: .7rem;
  color: var(--ink2); margin-top: .35rem; font-variant-numeric: tabular-nums; }

/* --- live view --- */
#tab-elite .el-events { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px,1fr));
  gap: .7rem; }
#tab-elite .el-evcard { display: flex; flex-direction: column; gap: .28rem; text-align: left;
  background: var(--card); border: 1px solid var(--hairline2); border-radius: 10px;
  padding: .7rem .85rem; cursor: pointer; color: var(--ink2); font-family: var(--sans); }
#tab-elite .el-evcard:hover { border-color: var(--btnlineh); }
#tab-elite .el-evcard.on { border-color: var(--acc); box-shadow: 0 0 0 1px var(--acc) inset; }
#tab-elite .el-evcard b { color: var(--ink); font-size: .88rem; line-height: 1.3; font-weight: 500; }
#tab-elite .el-evplayers { font-size: .72rem; color: var(--mut); line-height: 1.45; }
#tab-elite .el-evmeta { font-size: .7rem; color: var(--mut2); }
#tab-elite .el-soon { font-family: var(--mono); font-size: .66rem; color: var(--mid); }
#tab-elite .el-livepill { display: inline-flex; align-items: center; gap: 5px;
  font-family: var(--mono); font-size: .66rem; letter-spacing: .08em; color: var(--bad); }
#tab-elite .el-livepill i, #tab-elite .el-dot { width: 7px; height: 7px; border-radius: 50%;
  background: var(--bad); animation: elpulse 1.6s ease-in-out infinite; display: inline-block; }
#tab-elite .el-livepill.sm { font-size: .6rem; }
#tab-elite .el-livepill.sm i { width: 5px; height: 5px; }
@keyframes elpulse { 0%,100% { opacity: 1; } 50% { opacity: .25; } }
#tab-elite .el-rounds { display: flex; gap: .4rem; flex-wrap: wrap; margin: .9rem 0 .7rem; }
#tab-elite .el-rd { background: var(--card); border: 1px solid var(--hairline2);
  border-radius: 7px; color: var(--ink2); font-family: var(--mono); font-size: .7rem;
  padding: 4px 10px; cursor: pointer; display: inline-flex; align-items: center; gap: 6px; }
#tab-elite .el-rd:hover:not(:disabled) { border-color: var(--btnlineh); color: var(--ink); }
#tab-elite .el-rd.on { border-color: var(--acc); color: var(--ink); }
#tab-elite .el-rd:disabled { opacity: .38; cursor: default; }
#tab-elite .el-rd .el-dot { width: 6px; height: 6px; }
#tab-elite .el-games tr[data-i] { cursor: pointer; }
#tab-elite .el-games tr.on td { background: rgba(216,176,120,.10); }
#tab-elite .el-res { font-family: var(--mono); font-size: .74rem; text-align: center; }
#tab-elite #elGamesWrap { overflow-x: auto; }
#tab-elite .el-games td:nth-child(2), #tab-elite .el-games td:nth-child(4) {
  max-width: 34ch; overflow: hidden; text-overflow: ellipsis; }

/* --- player --- */
#tab-elite .el-clocks { display: flex; gap: .5rem; align-items: baseline;
  font-family: var(--mono); font-size: .78rem; color: var(--ink2); min-height: 1.1em;
  font-variant-numeric: tabular-nums; }
#tab-elite .el-clocks .el-clk { color: var(--ink); }
#tab-elite #elFollow.on { color: var(--bad); }
#tab-elite #elFollow .el-dot { margin-right: 5px; }

@media (max-width: 900px){
  #tab-elite .el-rgrid { grid-template-columns: 1fr; }
  #tab-elite .el-gcard { position: static; }
  #tab-elite .el-rscroll { max-height: 56vh; }
}


.ri-open { display: inline-flex; align-items: center; gap: 5px; margin-left: .5rem;
  background: none; border: 1px solid var(--accborder); border-radius: 6px;
  color: var(--acc); font-family: var(--sans); font-size: 11px; font-weight: 600;
  padding: 4px 10px; cursor: pointer; }
.ri-open:hover { background: var(--wash06); color: var(--green2); border-color: var(--green2); }
.ri-open svg { display: block; }

.ri-h { font-family: 'Libre Caslon Text', serif; font-size: 19px; font-weight: 700;
  color: var(--ink); margin-bottom: 4px; }
.ri-ctx { font-size: 12px; color: var(--ink2); margin-bottom: 12px; }
.ri-ctx b { color: var(--ink); font-weight: 600; }
.ri-eco { font-family: var(--mono); font-size: 10px; color: var(--mut); }
.ri-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 10px 0 12px; border-top: 1px solid var(--hairline); }
.ri-lbl { font-family: var(--mono); font-size: 9.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--mut); }
.ri-cutlbl { margin-left: auto; }
.ri-seg { display: inline-flex; border: 1px solid var(--btnline); border-radius: 6px; overflow: hidden; }
.ri-seg button { background: none; border: none; border-radius: 0; color: var(--ink2);
  font-size: 11.5px; padding: 5px 11px; cursor: pointer; }
.ri-seg button.on { background: color-mix(in srgb, var(--ink) 10%, transparent);
  color: var(--ink); font-weight: 600; }
.ri-stepper button { font-size: 14px; padding: 3px 9px; }
.ri-stepper button:disabled { opacity: .35; cursor: default; }
.ri-stepper b { align-self: center; min-width: 2ch; text-align: center;
  font-variant-numeric: tabular-nums; color: var(--ink); font-size: 12px; }
.ri-line { font-size: 13px; line-height: 2.05; color: var(--ink); word-spacing: .18em;
  padding: 10px 12px; background: color-mix(in srgb, var(--ink) 4%, transparent);
  border-radius: 8px; }
.ri-line .new { color: var(--acc); font-weight: 650; }
.ri-line .cov { color: var(--mut); }
.ri-sum { font-size: 12px; color: var(--ink2); margin-top: 9px; }
.ri-sum b { color: var(--acc); font-variant-numeric: tabular-nums; }
.ri-actions { display: flex; gap: 8px; margin-top: 14px; }
.ri-empty { font-size: 12.5px; color: var(--mut); line-height: 1.6;
  border: 1px dashed var(--hairline3); border-radius: 8px; padding: 12px 14px; }
.ri-done { font-size: 30px; color: var(--ok); line-height: 1; margin-bottom: 8px; }


/* articles player: bigger board vs side panel, no layout strobe */
html { scrollbar-gutter: stable; }
#artPlayer .solve-grid { grid-template-columns: minmax(300px, calc(100vh - 110px)) minmax(280px, 310px); }
#artBoard { touch-action: none; cursor: pointer; }

/* ratings card: archive game dropdowns */
#elGGames { margin-top: .55rem; border-top: 1px solid var(--hairline); }
.el-dd { display: flex; align-items: center; gap: .45rem; padding: .42rem .1rem .3rem;
  cursor: pointer; font-family: var(--mono); font-size: .66rem; letter-spacing: .12em;
  text-transform: uppercase; color: var(--mut); }
.el-dd:hover { color: var(--ink); }
.el-dd b { font-weight: 600; letter-spacing: inherit; }
.el-ddt { font-size: .78rem; margin: 0 0 .3rem; }
.el-ddt td { padding: .22rem .4rem; }
.el-ddnote { font-size: .68rem; padding: .4rem 0; }

/* ratings table: expansion row beneath the selected player */
.el-exprow > td { padding: 0 !important; border-bottom: 1px solid var(--hairline2); }
.el-exp { padding: .2rem .8rem .55rem 2.2rem; background: var(--wash06, rgba(126,160,200,.05)); }
.el-ddwrap { max-height: 300px; overflow-y: auto; scrollbar-width: thin;
  border: 1px solid var(--hairline); border-radius: 6px; margin: 0 0 .4rem; }

/* result pill: box = the side the player had, word = their result.
   Chess-side colors are theme-invariant (like the board), so the two
   variants fork component-local vars off one shared ruleset. */
.res-pill { --rp-bg: #ece7d6; --rp-ink: #2b2b33; --rp-line: #c9c2ac;
  display: inline-block; min-width: 3.1em; text-align: center;
  padding: .1em .5em .12em; border-radius: 5px;
  background: var(--rp-bg); color: var(--rp-ink);
  border: 1px solid var(--rp-line);
  font-family: var(--mono); font-size: .68rem; letter-spacing: .04em; }
.res-pill.b { --rp-bg: #121218; --rp-ink: #e4dfcc; --rp-line: #55556e; }
.res-pill.won { font-weight: 700; }

/* result pill: box = the side the player had, word = their result.
   Chess-side colors are theme-invariant (like the board), so the two
   variants fork component-local vars off one shared ruleset. */
.res-pill { --rp-bg: #ece7d6; --rp-ink: #2b2b33; --rp-line: #c9c2ac;
  display: inline-block; min-width: 3.1em; text-align: center;
  padding: .1em .5em .12em; border-radius: 5px;
  background: var(--rp-bg); color: var(--rp-ink);
  border: 1px solid var(--rp-line);
  font-family: var(--mono); font-size: .68rem; letter-spacing: .04em; }
.res-pill.b { --rp-bg: #121218; --rp-ink: #e4dfcc; --rp-line: #55556e; }
.res-pill.won { font-weight: 700; }

#tab-mistakes .mk-list{max-width:46rem;margin:1.2rem auto 3rem;display:flex;
  flex-direction:column;gap:.45rem}
#tab-mistakes .mk-row{display:flex;align-items:center;gap:.9rem;cursor:pointer;
  padding:.6rem .9rem;border:1px solid var(--line);border-radius:8px;
  background:var(--card)}
#tab-mistakes .mk-row:hover{border-color:var(--acc)}
#tab-mistakes .mk-n{opacity:.55;font-variant-numeric:tabular-nums;min-width:2.2rem}
#tab-mistakes .mk-who{flex:1}
#tab-mistakes .mk-cost{font-variant-numeric:tabular-nums;opacity:.8}
#tab-mistakes .mk-pb{font-variant-numeric:tabular-nums;font-size:.82em;opacity:.65;
  white-space:nowrap}
#tab-mistakes .mut{opacity:.6;text-align:center;margin:2rem 0}

/* Your Mistakes: report block (13d v2) */
#tab-mistakes .mk-report{max-width:46rem;margin:1.4rem auto 0;padding:1.1rem 1.2rem;
  border:1px solid var(--line);border-radius:10px;background:var(--card)}
#tab-mistakes .mk-stats{display:flex;gap:2rem;flex-wrap:wrap;margin-bottom:1rem}
#tab-mistakes .mk-stat b{font-size:1.5rem;font-variant-numeric:tabular-nums;display:block}
#tab-mistakes .mk-stat span{color:var(--mut);font-size:.82rem}
#tab-mistakes .mk-cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(14rem,1fr));
  gap:1.4rem;margin-bottom:.8rem}
#tab-mistakes .mk-colh{color:var(--mut);font-size:.82rem;letter-spacing:.04em;
  text-transform:uppercase;margin:0 0 .4rem}
#tab-mistakes .mk-mot{display:flex;justify-content:space-between;padding:.2rem 0;
  border-bottom:1px solid var(--hairline)}
#tab-mistakes .mk-mot b{font-variant-numeric:tabular-nums}
#tab-mistakes .mk-clock{margin:.4rem 0 0;color:var(--ink2)}
#tab-mistakes .mk-row.done{opacity:.55}
#tab-mistakes .mk-row.done .mk-n{color:var(--ok)}

/* Your Mistakes: review strip + due rows (13d v3) */
#tab-mistakes .mk-due{max-width:46rem;margin:1.2rem auto 0;display:flex;
  align-items:center;gap:1rem;justify-content:space-between;padding:.7rem 1rem;
  border:1px solid var(--acc);border-radius:10px;background:var(--card)}
#tab-mistakes .mk-gobtn{font:inherit;cursor:pointer;padding:.45rem 1.2rem;
  border-radius:6px;border:1px solid var(--acc);background:var(--acc);
  color:var(--paper);font-weight:600}
#tab-mistakes .mk-row.due{border-color:var(--acc)}
#tab-mistakes .mk-row.due .mk-n{color:var(--acc)}

/* Your Mistakes: signature + thrown rows (13d v4) */
#tab-mistakes .mk-sig{display:flex;gap:.5rem;align-items:baseline;padding:.28rem 0;
  border-bottom:1px solid var(--hairline);flex-wrap:wrap}
#tab-mistakes .mk-sig b{font-variant-numeric:tabular-nums}
#tab-mistakes .mk-sig span{margin-left:auto;white-space:nowrap}
#tab-mistakes .mk-report .mk-colh{margin-top:1rem}
#tab-mistakes .mk-note{font-style:normal;text-transform:none;letter-spacing:0;
  color:var(--mut2)}
#tab-mistakes .mk-null{color:var(--mut);font-size:.85rem;margin:.8rem 0 0;
  font-style:italic}

/* Your Mistakes: expandable signatures + replay rows (13d v5) */
#tab-mistakes .mk-sighead{cursor:pointer}
#tab-mistakes .mk-sighead .mk-car{margin-left:auto;color:var(--mut2);
  transition:transform .15s}
#tab-mistakes .mk-sighead.open .mk-car{transform:rotate(180deg)}
#tab-mistakes .mk-sighead:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
#tab-mistakes .mk-sub{margin:0 0 .3rem .9rem;border-left:2px solid var(--hairline2);
  padding-left:.8rem}
#tab-mistakes .mk-inst{display:flex;gap:.5rem;align-items:baseline;cursor:pointer;
  padding:.26rem 0;border-bottom:1px solid var(--hairline);
  font-variant-numeric:tabular-nums;flex-wrap:wrap}
#tab-mistakes .mk-inst:hover .mk-play{color:var(--acc)}
#tab-mistakes .mk-play{margin-left:auto;color:var(--mut2);white-space:nowrap}
@media (prefers-reduced-motion: reduce){
  #tab-mistakes .mk-sighead .mk-car{transition:none}
}

/* (sync form moved to #tab-sync — its component layer lives at EOF) */

/* Your Mistakes: deviation rows (13d v7) */
#tab-mistakes .mk-devpct{color:var(--mut2);font-size:.8rem;white-space:nowrap;
  font-variant-numeric:tabular-nums;margin-left:.4rem}

/* Your Mistakes: prescription + drift + endgame-rate rows (13d v8) */
#tab-mistakes .mk-rx{flex-direction:column;align-items:flex-start;gap:.15rem}
#tab-mistakes .mk-rxplan{font-size:.88rem;color:var(--ink2)}
#tab-mistakes .mk-rxplan i{font-style:normal;color:var(--mut);font-size:.82rem}
#tab-mistakes .mk-egrow{font-size:.88rem;color:var(--ink2);
  font-variant-numeric:tabular-nums}
#tab-mistakes .mk-egrow i{font-style:normal;color:var(--mut2);font-size:.8rem}

/* Your Mistakes: reset link (13d v9) — the platform toggle moved to #tab-sync */
#tab-mistakes .mk-resetrow{max-width:46rem;margin:1.5rem auto 3rem;text-align:right}
#tab-mistakes .mk-linkbtn{font:inherit;font-size:.82rem;background:none;
  border:none;color:var(--mut);cursor:pointer;text-decoration:underline;
  text-underline-offset:3px}
#tab-mistakes .mk-linkbtn:hover{color:var(--bad)}

#tab-mistakes #mkGames{max-width:46rem;margin:1.4rem auto 0}
#tab-mistakes .mk-glist{display:flex;flex-direction:column;gap:.35rem;
  max-height:30rem;overflow-y:auto;padding-right:.3rem}
#tab-mistakes .mk-grow{display:flex;align-items:center;gap:.8rem;cursor:pointer;
  padding:.5rem .8rem;border:1px solid var(--line);border-radius:8px;
  background:var(--card);min-width:0}
#tab-mistakes .mk-grow:hover{border-color:var(--acc)}
#tab-mistakes .mk-gres{font-weight:700;font-variant-numeric:tabular-nums;
  min-width:1.5rem;text-align:center;border-radius:6px;padding:.05rem .25rem;
  font-size:.85em;color:var(--mut);border:1px solid var(--line)}
#tab-mistakes .mk-gres.win{color:var(--ok);border-color:var(--ok)}
#tab-mistakes .mk-gres.loss{color:var(--bad);border-color:var(--bad)}
#tab-mistakes .mk-gwho{flex:1;min-width:0;white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis}
#tab-mistakes .mk-gwho i{font-style:normal;color:var(--mut);font-size:.82em;
  margin-left:.5rem}
#tab-mistakes .mk-geco{color:var(--mut);font-size:.8em;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;max-width:13rem}
@media (max-width:640px){
  #tab-mistakes .mk-geco{display:none}
}

.std-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));
  gap:10px;margin-top:.4rem}
.std-card{background:var(--card);border:1px solid var(--line);border-radius:12px;
  padding:10px;cursor:pointer;transition:border-color .15s,transform .15s}
.std-card:hover{border-color:var(--acc);transform:translateY(-2px)}
.std-card .brd svg{width:100%;height:auto;display:block;border-radius:6px}
.std-card h3{font-size:.85rem;margin:.5rem 0 .3rem;line-height:1.25}
.std-card .chipline{display:flex;flex-wrap:wrap;gap:4px}
.std-plan{border-top:1px solid var(--line);padding:.6rem 0 .5rem}
.std-plan:first-child{border-top:none;padding-top:.2rem}
.std-plan-h{display:flex;align-items:center;gap:.45rem;flex-wrap:wrap}
.std-plan-h b{font-size:.92rem}
.std-plan .why{margin:.35rem 0 .45rem;font-size:.84rem;color:var(--mut);line-height:1.5}
.std-ev{display:flex;flex-wrap:wrap;gap:6px;align-items:center}
.std-ctl .mut{font-size:.72rem}
.std-watch.cur{border-color:var(--acc);color:var(--acc)}
.std-chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:.35rem}
.std-ctl{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:.4rem}
.std-libpl{display:block;color:var(--acc);opacity:.85;font-size:.7rem;margin-top:.15rem}

/* mainline in 2-ply rows (pkSheetRow); variations as indented flow blocks
   between the rows they branch from */
#artMoves .mrow { grid-template-columns: 2.6em 1fr 1fr; }
#artMoves .mrow button i { font-style: normal; font-weight: 700; margin: 0; }
#artMoves .m-ell { color: var(--ink2); opacity: .6; padding: .12rem .5rem; }
#artMoves .mvar { padding: .1rem .6rem .1rem 2.4em; line-height: 1.85; font-size: .88em; }
#artMoves .mvar .artm { padding: .05rem .28rem; border-radius: 5px; }
#artMoves .mvar i { margin: 0 0 0 .1rem; }
#artMoves .art-start { margin: .15rem .3rem; }
#artMoves .m-res { padding: .2rem .6rem .35rem; }
/* town art colors live in LOCAL component vars, never global tokens — moody
   night ocean by default, paper daylight under scoresheet */
#tab-world{
  --iw-sea:#0a1626; --iw-wave:#132540; --iw-sand:#2b3c58; --iw-grass:#10283e;
  --iw-grass2:#0d2236; --iw-path:#1c2f4a; --iw-wall:#182c46; --iw-wall2:#14263c;
  --iw-roof:#24466b; --iw-roof2:#2f5d8a; --iw-wood:#233650; --iw-glow:#7ec8ff;
  --iw-stone:#203653; --iw-dark:#0a1422; --iw-ink:#d7e3f2;
  --iw-tree:#16404a; --iw-rock:#243a58;
}

.iw-wrap{max-width:1340px;margin:0 auto;padding:1.1rem 1.2rem 2.5rem}
.iw-top{display:flex;align-items:baseline;gap:1rem;margin:.4rem 0 .8rem;flex-wrap:wrap}
.iw-brand b{font-size:1.35rem;letter-spacing:.01em}
.iw-brand .iw-sub{color:var(--mut);font-size:.8rem;margin-left:.6rem}
.iw-chips{margin-left:auto;display:flex;gap:.45rem}
.iw-chip{border:1px solid var(--hairline3);border-radius:999px;padding:.28rem .75rem;
  font-size:.82rem;color:var(--ink2);background:var(--surface)}
#iwBanner{border:1px solid var(--hairline3);border-left:3px solid var(--acc);
  background:var(--surface);border-radius:8px;padding:.5rem .8rem;margin:0 0 .7rem;
  font-size:.86rem;color:var(--ink)}
.iw-grid{display:grid;grid-template-columns:minmax(0,1fr) 300px;gap:.9rem;align-items:start}
.iw-stagewrap{border:1px solid var(--hairline2);border-radius:12px;overflow:hidden;
  background:var(--iw-sea);line-height:0}
#iwStage{width:100%;height:auto;display:block;cursor:pointer}
.iw-sea{fill:var(--iw-sea)}
.iw-seatext{fill:var(--mut);font-size:26px;font-family:var(--mono)}
.iw-side{display:flex;flex-direction:column;gap:.9rem;min-width:0}
.iw-panel{border:1px solid var(--hairline);border-radius:10px;background:var(--surface);
  padding:.7rem .8rem}
.iw-ptitle{font-size:.72rem;letter-spacing:.12em;text-transform:uppercase;color:var(--mut);
  margin:0 0 .55rem}
.iw-ptitle.iw-bt{margin-top:.8rem}
.iw-skill{display:flex;gap:.55rem;align-items:center;padding:.28rem 0}
.iw-skico{width:1.5rem;text-align:center;font-size:.95rem;flex:none}
.iw-skmain{flex:1;min-width:0}
.iw-skname{display:flex;justify-content:space-between;font-size:.83rem;color:var(--ink)}
.iw-skname b{color:var(--acc);font-weight:600}
.iw-skbar{height:4px;border-radius:2px;background:var(--hairline2);margin-top:.22rem;overflow:hidden}
.iw-skbar i{display:block;height:100%;background:var(--acc);opacity:.75;border-radius:2px}
.iw-quest{display:flex;gap:.55rem;align-items:flex-start;padding:.45rem .5rem;margin:0 -.5rem;
  border-radius:8px;cursor:pointer}
.iw-quest:hover{background:var(--ghost1l)}
.iw-quest>span{flex:none;width:1.4rem;text-align:center}
.iw-quest b{display:block;font-size:.84rem;font-weight:600;color:var(--ink)}
.iw-quest small{display:block;font-size:.74rem;color:var(--mut);margin-top:.1rem}
.iw-quest.done{opacity:.55;cursor:default}
.iw-quest.ready b{color:var(--acc)}
.iw-claimhint{color:var(--acc) !important}
.iw-quest.bounty{align-items:center}
.iw-quest.bounty .iw-mini{margin-left:auto}
.iw-mini{font:inherit;font-size:.72rem;background:none;color:var(--acc);cursor:pointer;
  border:1px solid var(--btnline);border-radius:6px;padding:.2rem .55rem;flex:none}
.iw-mini:hover{border-color:var(--acc)}
.iw-empty{color:var(--mut);font-size:.78rem;padding:.2rem 0}
.iw-item{display:inline-flex;align-items:center;gap:.2rem;border:1px solid var(--hairline2);
  border-radius:8px;padding:.3rem .5rem;margin:0 .3rem .3rem 0;font-size:1rem;cursor:default}
.iw-item b{font-size:.68rem;color:var(--mut)}
#iwToast{position:fixed;left:50%;bottom:1.4rem;transform:translate(-50%,140%);
  z-index:60;pointer-events:none;transition:transform .28s ease}
#iwToast.on{transform:translate(-50%,0)}
#iwToast .iwt-in{background:var(--cardsolid);border:1px solid var(--hairline3);
  border-radius:999px;padding:.5rem 1rem;font-size:.84rem;color:var(--ink);
  box-shadow:0 6px 24px rgba(0,0,0,.35)}
.iw-dlg{max-width:26rem}
.iw-qhead{display:flex;gap:.7rem;align-items:flex-start;margin-bottom:.7rem}
.iw-qico{font-size:1.5rem;flex:none}
.iw-bust{flex:none;width:64px;height:54px;border-radius:12px;background:var(--iw-sea);
  border:1px solid var(--hairline3)}
.iw-qwho{display:block;font-style:normal;font-size:.7rem;letter-spacing:.08em;
  text-transform:uppercase;color:var(--acc);margin:.15rem 0 .1rem}
.iw-qsay{min-height:2.4em;cursor:pointer}
@media (prefers-reduced-motion: no-preference){
  @keyframes iwFlap{from{transform:rotate(0)}to{transform:rotate(-26deg)}}
  .iw-wing{transform-box:fill-box;transform-origin:right center;
    animation:iwFlap .5s ease-in-out infinite alternate}
}
.iw-qhead b{font-size:1rem}
.iw-qhead small{display:block;color:var(--mut);margin-top:.25rem;line-height:1.45}
.iw-qsteps{margin:.6rem 0}
.iw-qstep{font-size:.85rem;color:var(--ink2);padding:.22rem 0}
.iw-qstep.ok{color:var(--ok)}
.iw-qstep b{color:var(--mut);font-weight:400;margin-left:.3rem}
.iw-qdone{color:var(--mut);font-size:.82rem;margin-top:.5rem}
.iw-cta{display:block;width:100%;margin-top:.7rem;padding:.55rem .9rem;font:inherit;
  font-size:.88rem;cursor:pointer;border-radius:8px;
  background:var(--acc) !important;color:var(--paper) !important;border:1px solid var(--acc) !important}
.iw-cta:hover{filter:brightness(1.08)}
@media (max-width:980px){
  .iw-grid{grid-template-columns:1fr}
  .iw-side{flex-direction:row;flex-wrap:wrap}
  .iw-side .iw-panel{flex:1 1 260px}
}
/* --- paper-doll characters: one renderer, recolor via CSS vars --- */
.iw-char .cS{fill:var(--iwS)}
.iw-char .cH{fill:var(--iwH)}
.iw-char .cT{fill:var(--iwT)}
.iw-char .cB{fill:var(--iwB)}
.iw-char .cC{fill:var(--iwC,#3f7d5a)}
.iw-char.walking>g{animation:iwBob .42s ease-in-out infinite alternate}
@keyframes iwBob{from{transform:translate(-32px,-84px) translateY(0)}
  to{transform:translate(-32px,-84px) translateY(-2.5px)}}
.iw-chname{fill:var(--iw-ink);font-size:12.5px;opacity:.75;
  font-family:'Schibsted Grotesk',sans-serif;paint-order:stroke;
  stroke:var(--iw-sea);stroke-width:3px;stroke-linejoin:round}
.iw-bub rect{fill:var(--cardsolid);stroke:var(--hairline3)}
.iw-bub path{fill:var(--cardsolid)}
.iw-bub text{fill:var(--ink);font-size:13px;font-family:'Schibsted Grotesk',sans-serif}

/* --- character creator --- */
.iw-cthead{font-size:1.05rem;display:block;margin-bottom:.7rem}
.iw-cre{display:flex;gap:1rem;align-items:flex-start}
.iw-crprev{flex:none;width:120px;border:1px solid var(--hairline2);border-radius:10px;
  background:var(--iw-sea);padding:.4rem}
.iw-crprev svg{width:100%;height:auto;display:block}
.iw-crops{flex:1;min-width:0}
.iw-crlbl{font-size:.68rem;letter-spacing:.1em;text-transform:uppercase;color:var(--mut);
  margin:.5rem 0 .25rem}
.iw-crlbl:first-child{margin-top:0}
.iw-crrow{display:flex;gap:.32rem;flex-wrap:wrap}
.iw-crdot{width:22px;height:22px;border-radius:50%;border:2px solid transparent;
  cursor:pointer;padding:0}
.iw-crdot.on{border-color:var(--acc);outline:1px solid var(--acc);outline-offset:1px}
.iw-crhair{font:inherit;font-size:.72rem;background:none;color:var(--ink2);cursor:pointer;
  border:1px solid var(--btnline);border-radius:6px;padding:.22rem .5rem}
.iw-crhair.on{color:var(--acc);border-color:var(--acc)}
.iw-crfoot{display:flex;gap:.7rem;align-items:center;margin-top:.9rem}
.iw-crfoot .iw-cta{margin-top:0}
/* --- town --- */
#iwStage .iw-hot{cursor:pointer}
#iwStage .iw-hot:hover{filter:brightness(1.13)}
.iw-bsign{fill:var(--iw-ink);font-size:13px;font-family:'Schibsted Grotesk',sans-serif;
  opacity:.9;paint-order:stroke;stroke:var(--iw-grass);stroke-width:3px;stroke-linejoin:round}
.iw-blabel{fill:var(--iw-ink);opacity:.85}
/* --- world alive: day/night phases (per theme register) --- */
#tab-world .iw-stagewrap.iw-day{--iw-sea:#0d1d31;--iw-grass:#143049;--iw-grass2:#112c44;
  --iw-sand:#32455f;--iw-path:#24374f;--iw-stone:#263c5c}
#tab-world .iw-stagewrap.iw-dusk{--iw-sea:#0b1828;--iw-grass:#122c44;--iw-grass2:#0f2740}



.iw-day .iw-beam{display:none}
.iw-storm .iw-sea{filter:brightness(.86)}
.iw-locked{opacity:.62}
#tab-world .iw-stagewrap.iw-isle2{--iw-grass:#22303d;--iw-grass2:#1d2a36;--iw-sand:#3a4656;
  --iw-sea:#081220;--iw-tree:#2c4444;--iw-stone:#3e4a5e;--iw-rock:#33415a}

.iw-star{fill:#dfe9f5}
.iw-rain line{stroke:var(--iw-wave);stroke-width:1.5;opacity:.55}
.iw-qmark{font:700 20px 'Schibsted Grotesk',sans-serif;fill:#ffd763;paint-order:stroke;
  stroke:rgba(10,20,34,.75);stroke-width:3px}
.iw-qmark.ready{fill:#7edb9a}
.iw-ripple{fill:none;stroke:var(--iw-glow);stroke-width:2;opacity:.7}
.iw-puff circle{fill:var(--iw-sand);opacity:.75}
.iw-sparkdot{fill:var(--iw-glow);opacity:0}
@media (prefers-reduced-motion: no-preference){
  @keyframes iwWaveShift{to{stroke-dashoffset:-72}}
  .iw-anim-wave{animation:iwWaveShift 8s linear infinite}
  .iw-anim-wave2{animation:iwWaveShift 12s linear infinite reverse}
  @keyframes iwSmokeUp{0%{transform:translateY(0);opacity:.45}80%{opacity:.12}
    100%{transform:translateY(-28px);opacity:0}}
  .iw-smoke circle{fill:var(--iw-ink);opacity:0;animation:iwSmokeUp 3.6s ease-out infinite}
  @keyframes iwFlagWave{0%,100%{transform:skewY(0)}50%{transform:skewY(7deg)}}
  .iw-flag{transform-box:fill-box;transform-origin:left center;
    animation:iwFlagWave 2.3s ease-in-out infinite}
  @keyframes iwBeamSweep{0%,100%{transform:rotate(-13deg);opacity:.09}
    50%{transform:rotate(13deg);opacity:.22}}
  .iw-beam{transform-box:fill-box;transform-origin:left center;opacity:.14;
    animation:iwBeamSweep 6.5s ease-in-out infinite}
  @keyframes iwStarTw{0%,100%{opacity:.25}50%{opacity:.95}}
  .iw-star{animation:iwStarTw 3.2s infinite}
  .iw-lamp{animation:iwStarTw 4.4s infinite}
  @keyframes iwBirdFly{from{transform:translate(-80px,130px)}to{transform:translate(1360px,50px)}}
  .iw-birds{stroke:var(--iw-ink);stroke-width:2;fill:none;opacity:.45;
    animation:iwBirdFly 40s linear infinite}
  @keyframes iwRainF{to{transform:translateY(28px)}}
  .iw-rain{animation:iwRainF .55s linear infinite}
  @keyframes iwSway{from{transform:rotate(-1.2deg)}to{transform:rotate(1.2deg)}}
  .iw-canopy{transform-box:fill-box;transform-origin:50% 92%;
    animation:iwSway 5.8s ease-in-out infinite alternate}
  @keyframes iwStep{from{transform:rotate(11deg)}to{transform:rotate(-11deg)}}
  .iw-char.walking .iw-legL{transform-box:fill-box;transform-origin:50% 5%;
    animation:iwStep .34s ease-in-out infinite alternate}
  .iw-char.walking .iw-legR{transform-box:fill-box;transform-origin:50% 5%;
    animation:iwStep .34s ease-in-out infinite alternate-reverse}
  @keyframes iwMarkBob{from{transform:translateY(0)}to{transform:translateY(-5px)}}
  .iw-qmark{animation:iwMarkBob 1.1s ease-in-out infinite alternate}
  @keyframes iwKnock{50%{filter:brightness(1.4)}}
  .iw-knock{animation:iwKnock .45s}
  @keyframes iwRip{to{r:36;opacity:0}}
  .iw-ripple{animation:iwRip .6s ease-out forwards}
  @keyframes iwPuffA{to{transform:translateY(-9px);opacity:0}}
  .iw-puff circle{animation:iwPuffA .55s ease-out forwards}
  @keyframes iwSparkA{0%{opacity:0;transform:translateY(6px)}30%{opacity:1}
    100%{opacity:0;transform:translateY(-28px)}}
  .iw-sparkdot{animation:iwSparkA 1.05s ease-out forwards}
}
/* --- house --- */
.iw-tile{fill:var(--iw-wall2);opacity:.35;stroke:var(--iw-dark);stroke-width:1}
.iw-tile.open{opacity:.7;stroke:var(--iw-glow);stroke-dasharray:5 4;cursor:pointer}
.iw-tile.open:hover{opacity:1}
.iw-item.placing{outline:2px solid var(--acc);outline-offset:1px}

/* --- island chronicle: deeds + progress atlas (world tab) --- */
.iw-chip.iw-ready{border-color:var(--acc);color:var(--acc);box-shadow:0 0 8px color-mix(in srgb, var(--acc) 35%, transparent)}
.iw-chronsub{font-size:.78rem;color:var(--mut);margin:-2px 0 10px}
.iw-chron{display:grid;grid-template-columns:1fr 1fr;gap:16px;max-height:min(62vh,640px);overflow:auto;padding-right:4px}
@media (max-width:900px){.iw-chron{grid-template-columns:1fr}}
.iw-chroncol{min-width:0}
.iw-atlas{display:flex;gap:9px;align-items:center;padding:7px 8px;border-radius:9px;cursor:pointer}
.iw-atlas:hover{background:color-mix(in srgb, var(--acc) 9%, transparent)}
.iw-atico{font-size:1.05rem;flex:none;width:1.5em;text-align:center}
.iw-atmain{flex:1;min-width:0}
.iw-atname{font-size:.85rem;font-weight:600}
.iw-atstat{font-size:.74rem;color:var(--mut);margin:1px 0 3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.iw-deed{display:flex;gap:9px;align-items:center;padding:6px 8px;border-radius:9px}
.iw-deed.ready{background:color-mix(in srgb, var(--acc) 10%, transparent)}
.iw-deed.done{opacity:.55}
.iw-dico{font-size:1rem;flex:none;width:1.5em;text-align:center}
.iw-dmain{flex:1;min-width:0}
.iw-dmain b{font-size:.83rem}
.iw-dmain small{display:block;font-size:.72rem;color:var(--mut);margin:0 0 3px}
.iw-dgot{color:var(--good, #7ddba3);font-weight:700}
.iw-dp{font-size:.72rem;color:var(--mut);flex:none}
.iw-claim{border-color:var(--acc) !important;color:var(--acc) !important}
.iw-manihead{color:var(--acc);margin-right:4px}
.iw-mani{cursor:pointer;text-decoration:underline;text-decoration-color:color-mix(in srgb, var(--ink) 25%, transparent);text-underline-offset:3px}
.iw-mani:hover{color:var(--acc)}
.iw-cta2{margin-top:8px}
#iwBanner{cursor:default}

/* --- world art pass: RS-grade island (13g) --- */
.iw-foam{animation:iwFoam 9s linear infinite}
.iw-foam2{animation:iwFoam 14s linear infinite reverse}
@keyframes iwFoam{to{stroke-dashoffset:-96}}
.iw-sparkle{stroke:#dff0f4;stroke-width:1.6;opacity:0;animation:iwSparkle 3.2s ease-in-out infinite}
@keyframes iwSparkle{0%,72%,100%{opacity:0}80%,92%{opacity:.55}}
.iw-fire{opacity:0;animation:iwFire 3.6s ease-in-out infinite}
@keyframes iwFire{0%,100%{opacity:0;transform:translateY(0)}35%{opacity:.9}55%{opacity:.5;transform:translateY(-7px)}80%{opacity:0;transform:translateY(-12px)}}
.iw-win{opacity:.16;transition:opacity .5s}
.iw-dusk .iw-win{opacity:.72}
.iw-night .iw-win{opacity:.95}
.iw-storm .iw-win{opacity:.6}
.iw-tint{fill:transparent;transition:fill .5s}
.iw-dusk .iw-tint{fill:#c26a35;opacity:.10}
.iw-night .iw-tint{fill:#0a1c3c;opacity:.30}
.iw-storm .iw-tint{fill:#101a2c;opacity:.24}
.iw-night.iw-storm .iw-tint{fill:#081226;opacity:.42}

/* --- world art pass 2: naturalistic ground palette under the new buildings --- */
#tab-world .iw-stagewrap{--iw-sea:#14405c;--iw-wave:#8fd8f0;--iw-sand:#d3bd85;
  --iw-path:#bca781;--iw-grass:#4d7c46;--iw-grass2:#437039;--iw-stone:#a8987a;
  --iw-wood:#6a4a32;--iw-tree:#3d7350;--iw-rock:#7e8694}
#tab-world .iw-stagewrap.iw-day{--iw-sea:#175073;--iw-grass:#4d7c46;--iw-grass2:#437039;
  --iw-sand:#d6c18a;--iw-path:#bca781;--iw-stone:#a8987a}
#tab-world .iw-stagewrap.iw-dusk{--iw-sea:#123a55;--iw-grass:#41673c;--iw-grass2:#395d34;
  --iw-sand:#c3ab77;--iw-path:#a8926e;--iw-stone:#93825f}
#tab-world .iw-stagewrap.iw-night{--iw-sea:#0b2338;--iw-grass:#2c4d32;--iw-grass2:#26452c;
  --iw-sand:#9d8d66;--iw-path:#8a7a5e;--iw-stone:#7e7260}

/* --- world art pass 3: OSRS scene language — olive ground, grey roads, torchlight --- */
#tab-world .iw-stagewrap{--iw-grass:#5a6b2a;--iw-grass2:#4f5f24;--iw-path:#6e7276;
  --iw-sand:#9a8f6a;--iw-sea:#22475e;--iw-stone:#84888e;--iw-wave:#7fb8d4}
#tab-world .iw-stagewrap.iw-day{--iw-grass:#5a6b2a;--iw-grass2:#4f5f24;--iw-path:#6e7276;
  --iw-sand:#9a8f6a;--iw-sea:#22475e;--iw-stone:#84888e}
#tab-world .iw-stagewrap.iw-dusk{--iw-grass:#4c5a24;--iw-grass2:#42501f;--iw-path:#63666a;
  --iw-sand:#8a805f;--iw-sea:#1c3c50;--iw-stone:#777b81}
#tab-world .iw-stagewrap.iw-night{--iw-grass:#37431c;--iw-grass2:#2f3a18;--iw-path:#4e5155;
  --iw-sand:#6e6749;--iw-sea:#122b3d;--iw-stone:#5f6369}
.iw-flame{transform-box:fill-box;transform-origin:50% 100%;animation:iwFlick 1.1s ease-in-out infinite}
@keyframes iwFlick{0%,100%{transform:scaleY(1) scaleX(1)}30%{transform:scaleY(1.18) scaleX(.92)}
  60%{transform:scaleY(.88) scaleX(1.08)}80%{transform:scaleY(1.08) scaleX(.95)}}
.iw-night .iw-tint{fill:#0a1c3c;opacity:.34}
.iw-dusk .iw-tint{fill:#b35a2a;opacity:.12}

/* --- world 3D layer (13g3) --- */
#iw3c{width:100%;display:block;cursor:crosshair}
#tab-world .iw-stagewrap{position:relative}
#iw3labels{position:absolute;inset:0;pointer-events:none;overflow:hidden;line-height:1.15}
.iw3lab{position:absolute;left:0;top:0;white-space:nowrap;font:600 12.5px 'Schibsted Grotesk',sans-serif;
  color:#f2f6f9;text-shadow:0 1px 2px #000,0 0 4px #000,0 0 8px rgba(0,0,0,.6)}
.iw3lab.npc{color:#ffd763;font-size:11.5px}
.iw3lab.bang{color:#ffd763;font-size:14px;font-weight:800}
.iw3lab.ok{color:#7edb9a;font-size:13px;font-weight:800}
.iw3lab.sign{font-size:12px}
.iw3lab.dim{color:#aab6c2;font-size:11px}
.iw3lab.bub{max-width:200px;white-space:normal;background:#0d1a2ae8;border:1px solid #7cb8d840;
  border-radius:8px;padding:3px 8px;font-weight:500;font-size:11.5px;color:#dce8f2;text-shadow:none}

/* --- master-games / structure popup (13e smPanel) — component layer.
   The host also carries .exg-panel, so rows, stacked player names, pills,
   search field and the show-more button are the explorer's own primitives;
   this layer is the floating shell, title bar, segmented tabs, toolbar and
   row actions. */
.sm-pop{position:fixed;right:14px;top:60px;z-index:60;width:min(560px,94vw);
  max-height:min(82vh,880px);display:flex;flex-direction:column;padding:0;
  border-radius:14px;background:var(--card);border:1px solid var(--hairline3);
  border-top:2px solid var(--accdim);
  box-shadow:0 24px 64px rgba(0,0,0,.62),0 6px 20px rgba(0,0,0,.45);overflow:hidden}
.sm-head{flex:none;display:flex;flex-direction:column;gap:.5rem;
  padding:.6rem .75rem .65rem;border-bottom:1px solid var(--hairline2);
  background:color-mix(in srgb, var(--surface2) 55%, var(--card))}
.sm-titlebar{display:flex;align-items:center;gap:.5rem}
.sm-title{font-family:var(--mono);font-size:.66rem;font-weight:500;
  letter-spacing:.16em;text-transform:uppercase;color:var(--ink2)}
.sm-x{margin-left:auto;flex:none;line-height:1;opacity:.7}
.sm-x:hover{opacity:1}
.sm-tabs{display:flex;align-items:center;gap:2px;padding:2px;width:fit-content;
  max-width:100%;background:var(--surface);border:1px solid var(--hairline2);
  border-radius:9px}
.sm-tab{appearance:none;background:none;border:none;border-radius:7px;
  cursor:pointer;font-family:var(--mono);font-size:.66rem;letter-spacing:.07em;
  text-transform:uppercase;color:var(--mut);padding:.34rem .62rem;white-space:nowrap}
.sm-tab:hover{color:var(--ink)}
.sm-tab.on{color:var(--ink);background:var(--surface2);
  box-shadow:inset 0 0 0 1px var(--hairline3)}
.sm-tab b{font-weight:700}
.sm-sub{font-size:.74rem;color:var(--mut);line-height:1.45}
.sm-ctl{display:flex;align-items:center;gap:.4rem;flex-wrap:wrap}
.sm-rf{display:inline-flex;gap:.35rem}
.sm-sort{display:inline-flex;gap:2px;margin-left:auto;padding:2px;
  background:var(--surface);border:1px solid var(--hairline2);border-radius:8px}
.sm-sort button{appearance:none;background:none;border:none;cursor:pointer;
  font-family:var(--mono);font-size:.62rem;letter-spacing:.06em;color:var(--mut);
  padding:.24rem .5rem;border-radius:6px}
.sm-sort button:hover{color:var(--ink)}
.sm-sort button.on{color:var(--ink);background:var(--surface2)}
.sm-list{flex:1 1 auto;min-height:0;overflow-y:auto;padding:.3rem .5rem .55rem}
.sm-row .sm-act,.sm-deck .sm-act{flex:none;width:1.55rem;height:1.55rem;padding:0;
  display:inline-flex;align-items:center;justify-content:center;font-size:.8rem;
  line-height:1;border-radius:50%;opacity:.5}
.sm-row:hover .sm-act,.sm-deck:hover .sm-act{opacity:1}
.sm-build{border-top:1px dashed var(--hairline2);margin-top:.5rem}
.sm-foot{display:flex;gap:.5rem;margin-top:.6rem;padding-top:.55rem;
  border-top:1px solid var(--hairline)}
/* the cart tab renders through the ONE grid (vgrid), and a virtual grid
   needs a bounded body to window into — this popup owns its host's
   height and the row action inside it (T3, 2026-08-11: home from
   one-grid-lists.css) */
#smCartGrid{height:min(48vh,420px)}
#smCartGrid .vg-row .sm-act{padding:0 4px;min-height:0;border:0;background:none}


/* the popup's TWIN verb (2026-08-22): an in-prose ghost word in the title
   bar before ✕ — the door into the lab below; rendered only when the
   board's position has a pair-off to offer */
.sm-titlebar .sm-twin{margin-left:auto;flex:none;line-height:1;opacity:.7}
.sm-titlebar .sm-twin:hover{opacity:1}
.sm-titlebar .sm-twin ~ .sm-x{margin-left:.4rem}

/* ====== THE STRUCTURE LAB — #smCmp, the two-board compare (13e-structcmp)
   in the door voice (2026-08-22, reports/STRUCTURE-TWIN-PANE-2026-08-22.md).
   An overlay on a board session standing ABOVE the strip (bottom:26px —
   the door chip stays visible and live, the doorframe law's C2). Pine
   ground, the landing's four type roles, the verbs ONE band: the solve
   plate's materials restated as this file's own classes — single
   ownership per prefix (tests/css-ownership.test.mjs: `smc-` has one
   owner). Every --dv-* read carries its fallback (the body-class-gate
   law). Geometry: the head and the band are fixed, each pane's word /
   number / strip are fixed, and the board is --smc-bd — written by
   13e-structcmp smcFit from what is free, never guessed. Nothing here
   scrolls but a pane's strip and a summoned swap menu. */
#smCmp{
  --smc-gap:18px; --smc-bd:400px;
  position:fixed; left:0; right:0; top:0; bottom:26px; z-index:70;
  display:flex; flex-direction:column; overflow:hidden;
  background:var(--dv-pine,#24382d); color:var(--dv-buff-ink,#efe9d6);
}
.smc-head{
  flex:none; height:34px; display:flex; align-items:center; gap:14px; min-width:0;
  padding:0 var(--smc-gap,18px);
}
.smc-eyebrow{
  flex:none; font-family:var(--mono,'Spline Sans Mono',Menlo,monospace); font-size:10.5px;
  letter-spacing:.16em; text-transform:uppercase; color:var(--dv-sage,#a9b8a6);
}
.smc-fact{
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace); font-size:10.5px;
  letter-spacing:.06em; color:var(--dv-flag-lt,#e0906c); font-variant-numeric:tabular-nums;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-width:0;
}
.smc-panes{
  flex:1 1 0; min-height:0; display:flex; justify-content:center; align-items:flex-start;
  gap:var(--smc-gap,18px); padding:0 var(--smc-gap,18px); overflow:hidden;
}
.smc-pane{
  position:relative; width:var(--smc-bd,400px); flex:none; min-width:0;
  display:flex; flex-direction:column; gap:8px;
}
/* the pane's word: the players, or what the position is; the focused
   pane's in ink, the other's in sage */
.smc-phead{ flex:none; height:34px; display:flex; align-items:center; gap:10px; min-width:0; }
.smc-word{
  font-family:var(--serif,'Libre Caslon Text',Georgia,serif); font-weight:400; font-size:15px;
  color:var(--dv-sage,#a9b8a6); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-width:0;
}
.smc-pane.focus .smc-word{ color:var(--dv-buff-ink,#efe9d6); }
.smc-phead .smc-fact{ flex:none; }
.smc-sk{ color:var(--dv-sage,#a9b8a6); }
.smc-ghost{
  flex:none; margin-left:auto; border:0; background:none; padding:0; cursor:pointer; border-radius:0;
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace); font-size:10.5px; letter-spacing:.05em;
  color:var(--dv-moss,#5d6b5f);
}
.smc-ghost:hover{ color:var(--dv-buff,#e9e1cc); }
/* the board: width is the fit's, the svg height:auto (a viewBox svg in a
   non-square box letterboxes, taking its edge with it) */
.smc-board{ flex:none; width:var(--smc-bd,400px); line-height:0; }
.smc-board svg{ display:block; width:100%; height:auto; }
/* the number: white's share as a bar, the score and the line under it */
.smc-ev{ flex:none; height:40px; display:flex; flex-direction:column; justify-content:center; gap:7px; min-width:0; }
.smc-track{ display:block; height:6px; background:rgba(233,225,204,.14); overflow:hidden; }
.smc-track i{ display:block; height:100%; width:50%; background:var(--dv-buff,#e9e1cc); transition:width .3s ease; }
.smc-evrow{ display:flex; align-items:baseline; gap:12px; min-width:0; }
.smc-evrow b{
  flex:none; font-family:var(--mono,'Spline Sans Mono',Menlo,monospace); font-size:13px; font-weight:400;
  color:var(--dv-buff-ink,#efe9d6); font-variant-numeric:tabular-nums lining-nums;
}
.smc-pv{
  flex:1; min-width:0; font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:12px; color:var(--dv-sage,#a9b8a6); white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
/* the moves: a bounded scroller of its own (the one thing here that scrolls) */
.smc-strip{
  position:relative; flex:none; max-height:52px; overflow-y:auto; overscroll-behavior:contain;
  scrollbar-width:thin; font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:12px; line-height:1.45; color:var(--dv-sage,#a9b8a6);
}
.smc-strip i{
  font-style:normal; font-family:var(--mono,'Spline Sans Mono',Menlo,monospace);
  font-size:10px; color:var(--dv-moss,#5d6b5f);
}
.smc-m{ cursor:pointer; padding:0 .2em; }
.smc-m:hover{ color:var(--dv-buff,#e9e1cc); }
.smc-m.cur{ color:var(--dv-buff-ink,#efe9d6); background:rgba(233,225,204,.12); }
/* the swap menu: summoned buff paper, the map's material */
.smc-menu{
  position:absolute; top:34px; left:0; right:0; z-index:5; max-height:300px; overflow-y:auto;
  background:var(--dv-buff,#e9e1cc); color:var(--dv-ink,#24342b);
}
.smc-msec{
  padding:8px 12px 4px; font-family:var(--mono,'Spline Sans Mono',Menlo,monospace); font-size:10px;
  letter-spacing:.14em; text-transform:uppercase; color:var(--dv-moss,#5d6b5f);
  border-bottom:1px solid rgba(36,56,45,.32);
}
.smc-mrow{
  display:flex; align-items:baseline; gap:10px; padding:6px 12px; cursor:pointer;
  border-bottom:1px solid rgba(36,56,45,.18);
}
.smc-mrow b{
  font-family:var(--serif,'Libre Caslon Text',Georgia,serif); font-weight:400; font-size:14px;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-width:0;
}
.smc-mrow span{
  margin-left:auto; flex:none; font-family:var(--mono,'Spline Sans Mono',Menlo,monospace);
  font-size:10.5px; color:var(--dv-moss,#5d6b5f); font-variant-numeric:tabular-nums;
}
.smc-mrow:hover{ background:rgba(36,56,45,.08); }
/* the drill's sentence slot (S4): the question while it stands, the verdict
   and the why after — ONE slot at ONE height in both phases (the
   phase-invariant law), its own scroller past three lines */
.smc-ask{
  flex:none; height:66px; margin:0 var(--smc-gap,18px) 9px; overflow-y:auto; overscroll-behavior:contain;
  scrollbar-width:thin; font-family:var(--serif,'Libre Caslon Text',Georgia,serif); font-style:italic;
  font-size:15px; line-height:1.45; color:var(--dv-buff-ink,#efe9d6); max-width:72ch;
}
.smc-ask b{ font-style:normal; font-weight:400; color:var(--dv-flag-lt,#e0906c); }
.smc-ask.smc-ok b{ color:var(--dv-buff,#e9e1cc); }
/* the rows withheld while the question stands: the organ keeps its height */
.smc-ledger.smc-held .smc-lrow:not(.smc-lhead){ visibility:hidden; }
/* the ledger (S2): the mechanisms as rows under the pair — the label, then
   each position's value in its own column; a fact one side lacks is a dash
   in moss. Bounded: seven rows, then its own scroller. */
.smc-ledger{
  flex:none; margin:0 var(--smc-gap,18px) 9px; max-height:calc(8 * 22px);
  overflow-y:auto; overscroll-behavior:contain; scrollbar-width:thin;
  border-top:1px solid rgba(233,225,204,.14);
}
.smc-lrow{
  /* the two value columns stand UNDER the two boards: the panes centre
     `bd gap bd` in the same width, so `1fr bd bd 1fr` with the same gap
     lands each position's facts beneath its board; the label sits in the
     left margin, right-aligned against the first board */
  display:grid; grid-template-columns:minmax(0,1fr) var(--smc-bd,400px) var(--smc-bd,400px) minmax(0,1fr);
  gap:0 var(--smc-gap,18px); align-items:baseline; height:22px; padding:0;
  border-bottom:1px solid rgba(233,225,204,.08);
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif); font-size:12px;
  color:var(--dv-buff-ink,#efe9d6); font-variant-numeric:tabular-nums;
}
.smc-lrow.smc-lhead{
  position:sticky; top:0; z-index:1; background:var(--dv-pine,#24382d);
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace); font-size:10px; letter-spacing:.12em;
  text-transform:uppercase; color:var(--dv-sage,#a9b8a6); border-bottom-color:rgba(233,225,204,.22);
}
.smc-lrow.smc-lhead .smc-lc{ white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.smc-ll{ font-family:var(--mono,'Spline Sans Mono',Menlo,monospace); font-size:11px; color:var(--dv-sage,#a9b8a6); white-space:nowrap; text-align:right; }
.smc-lc{ min-width:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.smc-lc.smc-none{ color:var(--dv-moss,#5d6b5f); }
#smCmp.smc-narrow .smc-ledger{ max-height:calc(5 * 22px); }
#smCmp.smc-narrow .smc-lrow{ grid-template-columns:minmax(60px,.5fr) minmax(0,1fr) minmax(0,1fr); gap:0 12px; padding:0 4px; }
#smCmp.smc-narrow .smc-ll{ text-align:left; }
/* THE BAND — the solve plate's verb band, restated (.34 rule, .26 dividers,
   open cells, the red inversion on hover, the armed cell flag-light, the
   way out a moss ghost cell) */
.smc-band{
  flex:none; height:60px; display:flex; flex-wrap:nowrap; gap:0; align-items:stretch;
  background:var(--dv-pine-hi,#2b4336); border-top:1px solid rgba(233,225,204,.34);
}
.smc-cell{
  flex:1 1 auto; min-width:0; height:100%;
  border:0; border-right:1px solid rgba(233,225,204,.26); border-radius:0;
  background:none; color:var(--dv-buff-ink,#efe9d6); cursor:pointer; padding:0 12px;
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:12px; font-weight:500; letter-spacing:.1em; line-height:1;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  transition:color .15s ease, border-color .15s ease, background-color .15s ease;
}
.smc-band > :last-child{ border-right:0; }
.smc-cell:hover{ background:var(--dv-flag,#a8402c); color:#f2e8d8; border-color:transparent; }
.smc-cell:disabled{ color:var(--dv-moss,#5d6b5f); cursor:default; opacity:1; }
.smc-cell:disabled:hover{ background:none; border-color:rgba(233,225,204,.26); }
.smc-cell.smc-go{ color:var(--dv-flag-lt,#e0906c); }
.smc-cell.smc-back{ flex:0 0 auto; padding:0 20px; color:var(--dv-moss,#5d6b5f); }
.smc-cell.smc-back:hover{ background:none; color:var(--dv-buff,#e9e1cc); border-color:rgba(233,225,204,.26); }
.smc-cell:focus-visible{ outline:2px solid var(--dv-flag-lt,#e0906c); outline-offset:-2px; }
/* narrow: the panes stack (smcFit says when); under the floor one pane
   shows (smc-one) and the band carries the ⇄ cell. The band takes
   solve's own narrow recipe — cells fix at 44px and it wraps. */
#smCmp.smc-narrow .smc-panes{ flex-direction:column; align-items:center; }
/* the band's twin sheet (narrow): the same buff paper, summoned above the band */
.smc-band{ position:relative; }
.smc-tmenu{ top:auto; bottom:100%; max-height:min(60vh,320px); }
#smCmp.smc-one .smc-pane:not(.focus){ display:none; }
@media (max-width:1000px){
  .smc-band{ height:auto; flex-wrap:wrap; }
  .smc-cell{ height:44px; }
}
/* --- world 3D minimap + orbit cursor --- */
#iw3mini{position:absolute;top:10px;right:10px;width:150px;height:150px;pointer-events:auto}
#iw3mini canvas{width:150px;height:150px;border-radius:50%;cursor:pointer;
  box-shadow:0 4px 18px rgba(0,0,0,.55)}
#iw3mini .iw3-n{position:absolute;left:50%;top:50%;margin:-9px 0 0 -6px;font:800 12px 'Schibsted Grotesk',sans-serif;
  color:#7fd4ff;text-shadow:0 1px 2px #000;pointer-events:none}
#iw3c:active{cursor:grabbing}

/* --- world 3D hover verb (the yellow text) --- */
#iw3hover{position:absolute;pointer-events:none;z-index:5;display:none;
  font:700 13.5px 'Schibsted Grotesk',sans-serif;color:#ffd435;white-space:nowrap;
  text-shadow:0 1px 0 #000,0 -1px 0 #000,1px 0 0 #000,-1px 0 0 #000,0 2px 4px rgba(0,0,0,.7)}

/* one filled button is the accent budget; the 34vh scrollbox cap and hover-
   only affordances are lifted inside #tab-sync only */
#tab-sync .sync-card{display:flex;flex-direction:column;gap:.55rem;
  margin:0 0 1.4rem;padding:.95rem 1.05rem;border:1px solid var(--hairline2);
  border-radius:12px;background:var(--card)}
#tab-sync .sync-row{display:flex;gap:.55rem;align-items:stretch;flex-wrap:wrap}
#tab-sync #mkPlat{display:flex;align-items:stretch;border:1px solid var(--hairline3);
  border-radius:9px;overflow:hidden;background:var(--surface)}
#tab-sync #mkPlat button{font:inherit;font-size:.85rem;padding:.5rem .85rem;
  background:none;color:var(--mut);border:none;border-radius:0;cursor:pointer}
#tab-sync #mkPlat button + button{border-left:1px solid var(--hairline2)}
#tab-sync #mkPlat button:hover{color:var(--ink)}
#tab-sync #mkPlat button.on{background:var(--accfaint);color:var(--ink);font-weight:600}
#tab-sync #mkPlat button:focus-visible{outline:2px solid var(--acc);outline-offset:-2px}
#tab-sync #mkUserIn{flex:1 1 15rem;min-width:12rem;font:inherit;padding:.5rem .8rem;
  background:var(--surface);color:var(--ink);border:1px solid var(--hairline3);
  border-radius:9px}
#tab-sync #mkUserIn::placeholder{color:var(--mut2)}
#tab-sync #mkUserIn:focus{outline:none;border-color:var(--acc)}
#tab-sync #mkGo{flex:none;font:inherit;font-weight:600;cursor:pointer;
  padding:.5rem 1.15rem;border-radius:9px;border:1px solid var(--acc);
  background:var(--acc);color:var(--paper)}
#tab-sync #mkGo:hover{filter:brightness(1.08)}
#tab-sync #mkGo:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
#tab-sync #mkSyncMsg{font-size:.85rem;color:var(--mut);min-height:0}
#tab-sync #mkSyncMsg:empty{display:none}
#tab-sync #mkSyncMsg.bad{color:var(--bad)}
#tab-sync #mkSyncMsg.ok{color:var(--ok)}

/* sync games list — the page content, not a sidebar widget: no 34vh cap,
   and no heavy solid panel — rows breathe directly on the page */
#tab-sync .ot-linelist{max-height:none;overflow:visible;background:none;
  border:none;border-radius:0;border-top:1px solid var(--hairline2);
  margin-bottom:3rem}
#tab-sync .ot-linelist .ot-linehead{padding:.7rem .1rem .45rem}
/* (.ot-linerow rules died 2026-08-11 — the grid renders vgrid rows) */

.sf-cand.v2 .sf-pv .pvm{cursor:pointer}

.sm-subrow{display:flex;align-items:center;gap:.55rem}
.sm-subrow .sm-sub{flex:1;min-width:0}
.sm-struct{flex:none;width:36px;height:36px;border:1px solid var(--hairline2);
  border-radius:6px;background:var(--surface)}

/* (the structure lab's #smWrap.sm-launch launcher panel — three ghost
   verbs in a rounded shell under the explorer's book, and .sm-of, its
   demoted aggregate — died 2026-08-18: the launcher is ONE cell of the
   solve plate's band now, dressed by the band; 13e smSync.) */

#exgList{max-height:46vh;overflow-y:auto;scrollbar-width:thin}

/* 1 · status bar — the strip is a ROW of the frame at every width now
   (workbench.css); the fixed-overlay era and its display:none base died
   with the doorframe (2026-08-10) */
/* (the repmode --bd override died 2026-08-13 with the one-face rework:
   sessions take the svpage board budget whole.) */
#svAppBar .svapp-l b{color:var(--ink2);font-weight:600}
#svAppBar .svapp-r{margin-left:auto;display:flex;gap:1.2rem}
#svAppBar .svapp-eng b{color:var(--ink)}

/* 2 · dock-panel headers: one mono-caps strip per panel on the rep boards.
   The ENGINE head joined this list 2026-08-11
   and LEFT it 2026-08-13: one engine face, dressed by engine-pane.css
   on every svpage screen. It is the same intent the
   reading board's "THREE REGISTERS, ONE VOICE" block wrote separately on
   2026-08-01 — and that block never landed a single property: an id beats
   its three classes on .ot-bookhead, and engine-pane's `border:none
   !important` ate the one hairline it won on the toggle. Two rules, one
   intent, and the later one inert. This is the surviving owner, so the
   register that was missing comes here rather than the dead rule being
   escalated. Measured before (1440x900 explorer session): book head
   9.6px/400/.14em rgb(105,122,104) underlined · engine head
   10.56px/500/.16em rgb(179,191,174) not underlined. After: one voice.
   The engine toggle still has no bottom hairline — its seam is the
   .sf-row border-top above it — because stripping that !important is a
   re-boxing risk the engine pane has already been bitten by. */
body.repmode #tab-solve .ot-bookhead,
body.repmode #tab-solve .exg-panel .exg-sec{
  font-family:var(--mono);font-size:.6rem;font-weight:500;letter-spacing:.14em;
  text-transform:uppercase;color:var(--mut2);
  border-bottom:1px solid var(--hairline);padding:.12rem .1rem .4rem;
  margin-bottom:.15rem}

/* 3 · squared work surfaces */
body.repmode #tab-solve .ot-book{border-radius:3px}
.sm-pop{border-radius:6px}

/* 4 · database table headers */
.sm-colhead{display:flex;align-items:baseline;gap:.55rem;
  padding:.05rem .3rem .3rem;font-family:var(--mono);font-size:.56rem;
  letter-spacing:.12em;text-transform:uppercase;color:var(--mut2)}
.sm-colhead .sm-ch-p{flex:1;min-width:0}
.sm-colhead .sm-ch-r{width:2.6em;text-align:center}
.sm-colhead .sm-ch-y{flex:none;text-align:right}
.sm-colhead .sm-ch-a{width:3.65rem}
/* (5 · the ot-colhead / ot-grow2 table blocks died 2026-08-11 — nothing
   has emitted those rows since the games lists moved to vgrid) */

/* 6 · density: database rows, not web cards */
/* (the explorer's own row density left this file 2026-08-11 —
   explorer-session.css owns the rows it renders) */

#cmdk{position:fixed;inset:0;z-index:80;background:rgba(3,7,14,.55);
  display:flex;align-items:flex-start;justify-content:center;padding-top:16vh}
#cmdk[hidden]{display:none}
.cmdk-box{width:min(560px,92vw);background:var(--card);
  border:1px solid var(--hairline3);border-radius:10px;overflow:hidden;
  box-shadow:0 24px 64px rgba(0,0,0,.6),0 6px 20px rgba(0,0,0,.4)}
#cmdkIn{width:100%;font:inherit;font-size:.95rem;padding:.7rem .9rem;
  background:var(--surface);color:var(--ink);border:none;
  border-bottom:1px solid var(--hairline2);outline:none}
#cmdkList{max-height:46vh;overflow-y:auto;padding:.3rem}
.cmdk-row{display:flex;align-items:center;gap:.6rem;padding:.42rem .6rem;
  border-radius:6px;cursor:pointer;font-size:.86rem}
.cmdk-row:hover{background:var(--surface2)}
.cmdk-row.sel{background:var(--accfaint)}
.cmdk-row i{margin-left:auto;font-style:normal;font-family:var(--mono);
  font-size:.6rem;letter-spacing:.1em;text-transform:uppercase;color:var(--mut2)}
.cmdk-none{font-family:var(--mono);font-size:.7rem;color:var(--mut2);
  padding:.7rem .6rem;line-height:1.5}
.cmdk-foot{padding:.35rem .9rem;border-top:1px solid var(--hairline);
  font-family:var(--mono);font-size:.58rem;letter-spacing:.08em;color:var(--mut2)}

/* explorer notation pane: the sheet's own box is explorer-session.css's
   since 2026-08-11; these two are the KIT's row geometry */
#exgSheet.ndb-mvlist .mrow{grid-template-columns:2.6em 1fr 1fr}
#exgSheet .mrail{display:none}

/* sortable column head in the master-games popup */
.sm-colhead [data-act]{cursor:pointer}
.sm-colhead [data-act]:hover{color:var(--ink)}

/* --- account & sync card (19-cloudsync, injected into Profile) --- */
.cs-acct{display:flex;flex-direction:column;gap:.5rem;padding:.7rem .8rem;
  border:1px solid var(--hairline2);border-radius:12px;background:var(--card);
  margin-bottom:1.1rem}
.cs-row{display:flex;align-items:center;gap:.55rem;flex-wrap:wrap}
.cs-row input{flex:1 1 9rem;min-width:8rem;font-family:var(--sans);font-size:.85rem;
  color:var(--ink);background:var(--surface2);border:1px solid var(--hairline3);
  border-radius:8px;padding:.42rem .6rem}
.cs-row input:focus{outline:none;border-color:var(--acc)}
.cs-ok{font-family:var(--mono);font-size:.66rem;letter-spacing:.06em;color:var(--ok)}
.cs-sub{font-family:var(--mono);font-size:.66rem;color:var(--mut);line-height:1.55}
.cs-err{color:var(--bad)}
.cs-err:empty{display:none}
.cs-fill{flex:1}

/* --- world 3D filmic overlay: vignette + grain --- */
#iw3vig{position:absolute;inset:0;pointer-events:none;z-index:4;
  background:radial-gradient(ellipse 108% 100% at 50% 44%, transparent 58%, rgba(4,9,16,.38) 100%),
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2'/><feColorMatrix type='saturate' values='0'/></filter><rect width='140' height='140' filter='url(%23n)' opacity='.05'/></svg>");
  mix-blend-mode:normal}

/* --- world 3D door-enter fade --- */
#iw3fade{position:absolute;inset:0;background:#04070d;opacity:0;pointer-events:none;z-index:6;
  transition:opacity .3s}

/* --- the account card's primary (19 csCardFill) — the form it used to open
   is now a room of its own (js/19b-account.js, .ac-* at EOF) --- */
.cs-auth-go{appearance:none;cursor:pointer;width:100%;margin-top:.2rem;
  background:var(--acc) !important;color:#0a1622 !important;border:1px solid var(--acc) !important;
  border-radius:10px;padding:.6rem .9rem;font-family:var(--sans);font-size:.92rem;font-weight:700}
.cs-auth-go:hover{filter:brightness(1.08)}
.cs-auth-go:disabled{opacity:.6;cursor:wait}
.cs-acct .cs-auth-go{width:auto;padding:.42rem .8rem;font-size:.84rem}

/* ---- update chip (00b-perf updShow): a quiet corner chip, never a modal.
   Shown when the service worker has a newer build cached and waiting.
   ONE block — an earlier duplicate set `left` against this `right` and
   stretched the chip across the whole viewport. ---- */
.pl-upd{position:fixed;right:16px;bottom:16px;left:auto;width:max-content;
  max-width:calc(100vw - 32px);z-index:340;display:flex;align-items:center;gap:10px;
  background:var(--cardsolid);border:1px solid var(--hairline3);border-radius:10px;
  padding:10px 12px;font:500 13px/1 var(--mono);color:var(--ink);
  box-shadow:0 6px 24px rgba(0,0,0,.35)}
.pl-upd button{font:600 12px/1 var(--mono);border-radius:7px;padding:7px 10px;cursor:pointer}
.pl-upd #plUpdGo{background:var(--acc);border:1px solid var(--acc);color:var(--paper)}
.pl-upd #plUpdX{background:none;border:none;color:var(--mut);padding:4px 2px}
.pl-upd #plUpdX:hover{color:var(--ink)}

/* one --g-* grid/density set + one --mo-* motion set; zebra/hair/sel fork
   off --ink/--acc via color-mix, so only body.dense and reduced-motion
   carry real overrides. NEVER-ANIMATE law: tab switches, ⌘K, hover-in,
   board flips and scoresheet stepping stay 0ms — --mo-move is reserved
   for the one chess-piece slide. */
@font-face { font-family:"Fig"; font-style:normal; font-weight:400; font-display:swap;
  src:url(data:font/woff2;base64,d09GMgABAAAAAAl8AA8AAAAAEuQAAAkmAAJeuAAAAAAAAAAAAAAAAAAAAAAAAAAAGhYbIByBFh+BdgZWAFgRDAqZOJRSATYCJAMeCxwABCAFg1QHIBtZDyiOwzgW3ISdxr+fx23/545hbERbiJGIUYWCOcBqMAos9AX7v/F1BPErgufT86W5pGRNZzYbyHLCX30CAx/t/9baxRt0abekvYZoaaROpv8d1uYNsrung3sU3Ut4swahaCgqTcQSkUwKlEqlUtqlCA+dSpwDU5JQRO3YZ79e7QAIAFgAGY8Boqz2oAAESEEGqLBYRYEb4AAA//8fLrPil8EKECl/x+rvgJcMNziU+duIzdnZPmTiDd1Gh9k44NR3Dxsdxu5+zdCITKhIh9H6CXt72UD7sD/mxobwa2czh/ppYVjfPigYx4eMwljPkB4YeBPLaVlP7WIfwA+nTBa4vgsAsBcA8DYAph0AEPJgJT3IYEanMWQk4gBgE0AbBNhSYquS1du3gUxj5LDUqL8XezNhaA4HAojL3hvhHLQEmADMBOZaACSzDsBwQg8BAEa6MBhuOIbh4M01HLqqi7ogd1GhrS6i/0Ronesg+hgAgmwGQlJEkEyKopzHwT8aBxw0jP//x3bK8+bBhrKgj/TRAAez5Q1qMXADTIghH4DdIO+YRAC80Mtcc3/CgDAbQBTPwEYMhJ0X8fh4LE/pgktEIrFEhru4MFNZHHYEyz2Ow0sgObU4n6/EBwB/EivR/T5cYmZWe1wqc1htNohdszOETbJ3hzmdiHY4CCt1J3Ol2IBxGVOMU+kOB6KdTnJWg+jritUeiEAkIoEEApile6+C9vnsdoiNOpOITVsOniVnzx9G9KFzhPXMgRmHlj5+n5y9exS2lNa3WCn/hszmOlKWRJlbL6GpNqqpH45H1OE8phlRLC0AcNG0pmW1x+5tKGzr9uj1yYmcMF3ryj31MvOHrBQbyOlZDQx5Zl1jeKD6FDNsIBEbCKBKAyQIEIl0JJPQIiJ6ZNKMBDBzIR5oigI+0iKmBwc3HUN0wnqPR/kOLXLqnLrdYfsiDiHaeaVaRq4J3xli14wXBxt1RbXS6yhYYleIunl6PSIRgQgggIT6F9GOh/M21XXcvyxH787eP04fu0dY78ysRvQhROvsEM9PzbxtiP4cIVuhjfJOdWidiPZ26vatY22tqbtOkhfAQhBWb1Tna6GsEoSut4a2PAKWg2ARyUo2goVqTR11qluuBcsnkICZv3pmEbEb0RBm6/C3xW4nZ53OF6PG1mhZu5NqsXs9otftSvezY40ZBIjahui3dedT9kU7EH3RHu9DCSQhe3a1Q6gD4SfT7G9C/LUO7YIaNf78p7CrGThIx9oV+khpPfXZqBVA0pLDGY+lwaLaEcx6VhkHRhGaAWKUPHiNRnTyqRGzfsdSbuYpO4boclFjImkhfnw6amiJjSAmVVZCRz0h2uqEniv9FKxNhVlE55Tk1oGFANZClFn7NZ82k3+1P9STJDFuY4IIhTJ8w7Kq2hVV1dVLlWHNet1C7WTzvEXV0uqqmhVuvVId32KGtwC7UhLza0zi6Pz5GzSFSf3X+wcGb9zsNVSVy7Dg7B9v/Zw8UDyg69Xhlsk/3/qwIhgzeqUhDEL1gf5j/tyCpO4F8wN3zPWy3vHwvDPt5TnnlqfHrQUgev53CyJbpNcafaWNx6Q5L3/3Z8LFWn6T9Gq5n7T8qlT69MLX2PHEfF8/6XOlj6/yuTQk3wPrTD7z8XsRPtcafWSN13wISsNtPAnYVoX0WplUVnZNymru3PwopjkmPi/gwxNl/acyn8fucO6I5VMq+Wfsjk6veKEoPkgkCMoXCeMTBK6WJNdX/c79UZ3vHhgaFC8QBiaETrYSuo4c+Mbo3foklyksCAyNdKGg2iY03musvfvXLgYjX/in+yJ6jdApBmwtCpQ7PxQsD9XLd365jRQGxyVGgcCnBcFLBXjHBUDsyw7x+v3rOdtMSxpXKhtXLDZtp7ebFjetRkWoadUS0zb39fvk48wUQUri9q+qX2gNbZ3errXUZBFZlKbEAPRCENxb/kla5i8jB09mh5dAZUHlLo0oU8svvrmUpZUrIg/oEXIEXSuFvPifZWceqjz5ZfLS8P0fJeqVh0Y+yUz/VSD0sl7hLCfVcw4MHJgzgUu2qi8oFylRq8KpDmb/vCL303drrT4ar/Qb5emNN9JtDVLfdIj75IsUUtzAiStqNuv13tNf5mPPl967nb7l9bBcl3qjMWrhRv7LF61Rskr1H1dkPjEDJebKDqaP/6DeO2lyq6iizeVgUFyR2C2Ly1zckVjCIaQyD4tzV2CrKmRhiM8VAe9QepuiIyPypvKyZ3mPR1tJoPIVd+liA6P6wEHZ1Fzh3OTjyUcQZkr5dgYh/EsFi1WhUsqUciFPyJ8Hip+vjqR1dqWkpKGP1DmS2tOdlJLcldTK5v11icu79BeP+/djLufx3yEni1AYqoE96Vt2BC9VU/PeKZKX1dRSq1Tyg3eXfdNDKVRquTxcLY9UUcWsF/e8WybXrKqtCS/TvNNau0y9M3hL+pnGFxlzckYKp355wUJHJflTuSPkr4Z36Va8C8ruLLzz8KGnhLySN1WQXzA9kZ+bfeWV6wLsR0xw/ZUrWXkTLphASFBf8ZF4fHhfiNz7Fc4Kh7zSWQnq+6UWS0vk9qfDomHuzaA3YVJhP3rdDfHSbOJLwZ7pYSGu67PiMK83JNEbqSpOHTvGB0eYR+3r/P1uhfeom0vernGifqkeZ8To+ypHfbxrdJ9c8vGKGejQy92ld4NChHl67xTz3v94WW7iorjAwy5tlUaHp6+UKOEktWffyUmom2Ax/1Zjz2sg/Wnr9R2wC9ZyJmz++JVWbuavbn5uzqrn1xT/WJv/7vhHxal3fweAG0hbuQ7+5wvA+Y/D/VXNAbIOx8Hwh9AzEu7ChzToFKpGsQRSfQ4CADaDAgUYsDTkL6jlXKEBAxDuDtBkQ5yIQIJiEzFwQ8V9Gd6+OCQywRNVnNYFRKgHCgwbYWbUS89gjD+EQye5xeIhdiQJLengMX/Iz/kxJpCk7tZuUCRTGspRdG2eAQPgraFITRTrZkLMaCKfbpdoILaOTGaUdjkb1CdkQ/Q0yh9Jw7aksCF9Yl5rnHQKaLsm7ZbR9suK9YdeQ2SEyToMUKiztsuwwQYzAqrR2oyZ5DMhz++n3RpI1Iv15o+HaEiAFKmSuRgwpPf/PA0AAA==) format("woff2");
  unicode-range:U+2654-265F; }
:root {
  --g-rowh:26px; --g-px:8px; --g-fs:12.5px;
  --g-hair:1px solid color-mix(in srgb, currentColor 12%, transparent);
  --g-zebra:color-mix(in srgb, var(--ink) 3%, transparent);
  --g-hover:color-mix(in srgb, var(--ink) 6%, transparent);
  --g-sel:color-mix(in srgb, var(--acc) 14%, transparent);
  --g-selbar:inset 2px 0 0 var(--acc);
  --chrome:system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --mo-fast:80ms; --mo-move:140ms; --mo-enter:160ms; --mo-exit:90ms; --mo-bar:300ms;
  --mo-ease:cubic-bezier(.2,0,0,1); --mo-ok:1;
}
body.dense, :root[data-dense="1"] { --g-rowh:24px; }
@media (prefers-reduced-motion: reduce) {
  :root { --mo-ok:0; --mo-fast:0ms; --mo-move:0ms; --mo-enter:0ms; --mo-exit:0ms; --mo-bar:0ms; }
}
/* Figurines: the 2.4KB DejaVu subset (U+2654-265F) renders identically on
   every platform, so SAN pieces stop depending on the OS symbol font. The
   glyphs are render-only -- js/07-daily-sf.js maps them back to KQRBN on copy. */
.fg { font-family:"Fig", var(--sans); font-size:1.18em; line-height:0; vertical-align:-.08em; }
/* the ~30 ad-hoc transition declarations converge on the motion tokens;
   later layers win, so this one ruleset retunes the base chrome without
   touching earlier eras. */
button, .abtn { transition:transform var(--mo-fast) var(--mo-ease),
  box-shadow var(--mo-fast) var(--mo-ease), border-color var(--mo-fast) var(--mo-ease),
  background var(--mo-fast) var(--mo-ease), filter var(--mo-fast) var(--mo-ease); }

/* .vg — dense pooled rows on the --g-* tokens; zebra by DATA PARITY (pooled
   rows move, nth-child would lie); numerics always tabular */
.vg { display:flex; flex-direction:column; min-height:0; height:100%;
  border:var(--g-hair); border-radius:3px; background:var(--card);
  font-family:var(--chrome); font-size:var(--g-fs); color:var(--ink); }
.vg-head { display:grid; grid-template-columns:var(--gcols); flex:none;
  border-bottom:var(--g-hair); }
.vg-h { position:relative; appearance:none; background:none; border:none; min-width:0;
  text-align:left; font-family:var(--mono); font-size:.6rem; letter-spacing:.1em;
  text-transform:uppercase; color:var(--mut); padding:.34rem var(--g-px);
  cursor:pointer; user-select:none; overflow:hidden; white-space:nowrap; }
.vg-h:disabled { cursor:default; }
.vg-h:not(:disabled):hover { color:var(--ink); }
.vg-h.on { color:var(--ink); }
.vg-h.num { text-align:right; }
.vg-h .vg-arrow { font-style:normal; font-size:.52rem; margin-left:.2rem; color:var(--acc); }
.vg-grip { position:absolute; right:-4px; top:0; bottom:0; width:8px; z-index:3;
  cursor:col-resize; touch-action:none; }
.vg-grip:hover, .vg-grip:active { background:var(--accfaint); }
.vg-body { position:relative; flex:1; min-height:0; overflow-y:auto; overflow-x:hidden;
  overscroll-behavior:contain; scrollbar-gutter:stable; outline:none; }
.vg-body:focus-visible { box-shadow:inset 0 0 0 1px var(--accdim); }
.vg-spacer { width:1px; visibility:hidden; }
.vg-win { position:absolute; top:0; left:0; right:0; will-change:transform; }
.vg-row { display:grid; grid-template-columns:var(--gcols); align-items:stretch;
  height:var(--g-rowh); border-bottom:var(--g-hair); cursor:default; }
.vg-row.alt { background:var(--g-zebra); }
.vg-row:hover { background:var(--g-hover); }
.vg-row.sel, .vg-row.sel.alt { background:var(--g-sel); box-shadow:var(--g-selbar); }
.vg-c { padding:0 var(--g-px); line-height:var(--g-rowh); white-space:nowrap;
  overflow:hidden; text-overflow:ellipsis; min-width:0; }
.vg-c.num { text-align:right; font-variant-numeric:tabular-nums lining-nums; }
.vg-empty { padding:.9rem var(--g-px); color:var(--mut); font-size:.8rem; }
/* the transient board preview a vgrid single-click paints (13c exgPreview):
   a faint accent frame marks it until the next real repaint */
body.vgpeek #svBoard svg { outline:2px solid var(--accfaint); outline-offset:-2px; }
/* explorer games grid host: the earlier-era 46vh scrollbox rule must not
   fight the vgrid's managed height; players stay one-line inside dense rows */
#exgList.vg { max-height:none; overflow:hidden; margin-top:.25rem; }
/* (the explorer's cells inside a vgrid row are explorer-session.css's
   since 2026-08-11; the kit keeps the row's own contract) */
.vg .res-pill { font-size:.86em; }

/* The splitter kit's CSS (.split-v, body.splitting) is gone with
   js/04d-splitter-kit.js — THE FRAME DOES NOT RESIZE (2026-07-28). This rule
   is NOT splitter CSS and stays: it is the containing block other absolutely
   positioned children of the solve grid are placed against. */
#tab-solve > .solve-grid { position:relative; }

/* the strip's fact classes — the strip itself is a frame ROW styled by
   door-frame.css; the fixed-overlay rules and the :empty collapse died
   with the doorframe (2026-08-10: the strip carries the way home, so it
   is never empty and never absent) */
.stb-eng i{display:inline-block;width:7px;height:7px;border-radius:50%;
  background:var(--ok);margin-right:.4em;vertical-align:0}
.stb-eng{color:var(--ink2)}
.stb-ok{color:var(--ok)}
.stb-dim{color:var(--mut2)}

/* chrome is not selectable — SAN, FEN, prose and chat STAY selectable; no
   tap flash, no pull-refresh; board pages lock to 100dvh */
html { -webkit-tap-highlight-color: transparent; }
body { overscroll-behavior-y: none; }
button, .abtn, .sv-ghost, .sv-sec, .solvebtn, [data-tab], .sf-mpv-btn,
.vg-h, .chip, summary { cursor: default; }
a, a *, .ot-bookrow .ot-bsan, .pvm { cursor: pointer; }
#tabs, .sf-row, .sf-mpv, .vg-head, #svAppBar, .cmdk-wrap, .ot-bookhead, .exg-ctlrow, .set-shell, .pl-upd {
  user-select: none; -webkit-user-select: none; }
.ndb-mvlist, .ot-crumb, .sf-pv, .exg-var, .exg-sheet, .ac-form input,
.ot-booknote, .art-note, .src, code, pre { user-select: text; -webkit-user-select: text; }
.ndb-mvlist, #exgSheet, .exg-sheet, #syncGames, .sm-list, .lc-body,
.vg-body, .ot-book, .exg-panel, .cs-body {
  overscroll-behavior: contain; scrollbar-gutter: stable; }
/* the 100dvh zero-document-scroll lock is a desktop workbench frame; mobile
   keeps the document flow (boards are wider than small viewports) */
@media (min-width: 1000px) {
  body.svpage { height: 100dvh; overflow: hidden; }
}
/* labMenu (js/04e-chrome-kit.js): ONE context menu + tooltip skin */
.labmenu { position: fixed; z-index: 400; min-width: 180px; padding: 4px; inset: auto; margin: 0;
  background: var(--cardsolid); border: 1px solid var(--hairline3); border-radius: 8px;
  box-shadow: 0 10px 34px rgba(0,0,0,.45); font-family: var(--chrome); font-size: 12.5px;
  color: var(--ink); opacity: 0; transform: translateY(-3px);
  transition: opacity var(--mo-fast) var(--mo-ease), transform var(--mo-fast) var(--mo-ease); }
.labmenu.on { opacity: 1; transform: none; }
.labmenu button { display: flex; width: 100%; align-items: baseline; gap: .6rem;
  appearance: none; background: none; border: none; border-radius: 5px;
  padding: .42rem .6rem; font: inherit; color: var(--ink); text-align: left; cursor: default; }
.labmenu button:hover, .labmenu button.hot { background: var(--g-hover); }
.labmenu button:disabled { color: var(--mut2); }
.labmenu button.danger { color: var(--bad); }
.labmenu button .lm-hint { margin-left: auto; font-family: var(--mono);
  font-size: .58rem; color: var(--mut2); }
.labmenu .lm-sep { height: 1px; margin: 4px 6px; background: var(--hairline2); }
.labtip { position: fixed; z-index: 401; max-width: 280px; padding: .3rem .5rem;
  background: var(--cardsolid); border: 1px solid var(--hairline3); border-radius: 6px;
  box-shadow: 0 6px 22px rgba(0,0,0,.4); font-family: var(--chrome); font-size: 11.5px;
  line-height: 1.4; color: var(--ink2); pointer-events: none; margin: 0; inset: auto; }
.labmenu, .labtip { -webkit-touch-callout: none; }

/* --sans is the one chrome token (~200 consumers). Schibsted tops out at
   600 — font-synthesis-weight:none kills the fake 700s. Numeric columns
   tabular+lining. */
:root { --sans: var(--chrome); }
body { font-synthesis-weight: none; }
.ndb-table td, .ot-bpct, .ot-bgames, .exg-y, .ot-bev, .svapp-r, .cs-sub,
.cs-ok, .unit .ct, .vb, .ot-lmeta {
  font-variant-numeric: tabular-nums lining-nums; }
.nag { font-family: var(--chrome); }
.nag.w { color: var(--ink); }
.nag.b { color: var(--mut); }
.nag.eq { color: var(--mut2); }
/* settings checkboxes (FEEL section): quiet native-adjacent control */
.set-chk { appearance: none; width: 2.1rem; height: 1.15rem; border-radius: 999px;
  background: var(--surface2); border: 1px solid var(--hairline3); position: relative;
  cursor: default; transition: background var(--mo-fast) var(--mo-ease); }
.set-chk::after { content: ""; position: absolute; top: 2px; left: 2px; width: .78rem;
  height: .78rem; border-radius: 50%; background: var(--mut);
  transition: transform var(--mo-fast) var(--mo-ease), background var(--mo-fast) var(--mo-ease); }
.set-chk:checked { background: var(--accfaint); border-color: var(--acc); }
.set-chk:checked::after { transform: translateX(.95rem); background: var(--acc); }

/* sidebar: slimmer, hairline group dividers, edge-bar selection */
#tabs { width: 196px; padding: .7rem .55rem .9rem; }
body { padding-left: 196px; }
#wordmark { font-size: .95rem; padding: .1rem .45rem .65rem; }
#tabs .sg { border-top: 1px solid var(--hairline); padding-top: .15rem; }
#tabs .sg:first-of-type { border-top: none; }
#tabs .sg-lbl { padding: .42rem .45rem .3rem; font-size: .58rem; letter-spacing: .16em;
  color: var(--mut2); }
#tabs .sg-body button[data-tab] { padding: .28rem .45rem .28rem .9rem; font-size: .78rem;
  border-radius: 0 3px 3px 0; font-family: var(--chrome); }
#tabs .sg-body button[data-tab].on { background: var(--g-sel); box-shadow: var(--g-selbar);
  border-left-color: var(--acc); }
/* hero: from document header to console header */
.hero { padding: 1.5rem 0 1.2rem; gap: 1.6rem; }
.hero h1 { font-size: clamp(1.7rem, 3.6vw, 2.3rem); margin: .1rem 0 .55rem; }
.hero p.lede { font-size: .98rem; color: var(--ink2); }
.eyebrow { font-size: .62rem; margin-bottom: .35rem; }
section { padding: 1.7rem 0; }
section h2 { font-size: 1.25rem; }
/* cards: squared, flatter, denser */
.home-card, .wrap > section, .wrap > header, .strip, details.part2, .tally div,
.set-panel, .ndb-side .ndb-shell, .cs-acct {
  border-radius: 5px !important; }
#tab-home .home-card { padding: 12px 14px 11px; gap: 5px; }
#tab-home .home-card h3 { font-size: 14px; }
.home-grid, .gal { gap: 1rem; }
/* buttons: squared toolbar language */
button, .abtn { border-radius: 4px; padding: .34rem .7rem; font-size: .82rem; }
.sv-ghost, .sv-sec { border-radius: 4px; }
.chip { border-radius: 4px; }
/* stat strip tighter */
.strip div { padding: .7rem .8rem; }
.strip .n { font-size: 1.15rem; }

/* ocean value punch (round 2): the same flat navy everywhere was the real
   "nothing changed" — deeper base, lifted card surfaces, crisper hairlines
   and ink. One token block re-skins every surface; scoresheet untouched. */

body { background: var(--paper); }

/* the grid IS the panel — heights are managed in JS (otgGridSize /
   elGridSize / exgGridSize): openings 40vh, sync 76vh, ratings 74vh */
/* (#otGamesPanel died with the legacy openings page 2026-08-11) */
#syncGames.ot-linelist { max-height: none; overflow: visible;
  border: none; background: none; }
.ot-vggrid { margin: 0 .5rem .55rem; }
#syncGames .ot-vggrid { margin: 0 0 .55rem; }
.ot-vggrid .ot-ldrill { margin: 0; opacity: .45; padding: 0; font-size: .66rem;
  display: block; width: 100%; text-align: left; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.ot-vggrid .vg-row:hover .ot-ldrill, .ot-vggrid .vg-row.sel .ot-ldrill { opacity: 1; }
.ot-vggrid .ot-b { vertical-align: baseline; }
/* elite: the skeleton table's scroll wrapper becomes a plain column — the
   vgrid scrolls itself; the selected player's archive expansion sits under
   the grid instead of an inline table row. */
#tab-elite .el-rscroll { max-height: none; overflow: visible; border: none; }
#elExp:empty { display: none; }
#elExp .el-exp { padding-left: .8rem; border: var(--g-hair); border-top: none; }
#elRGrid.vg .el-up, #elRGrid.vg .el-dn { font-size: .92em; }
/* a virtual grid needs a bounded body to window into — the elite tab's
   archive expansion is a host, so its height is host geometry (T3,
   2026-08-11: home from one-grid-lists.css, which was two rooms' host
   heights sharing a file because they shared a widget) */
#elArch #archGrid { height: min(62vh,600px); }

.solve-top .sv-ico { font-size: .82rem; padding: .08rem .42rem; opacity: .7; }
.solve-top .sv-ico:hover { opacity: 1; }

#exgSheet.ndb-mvlist { line-height: 1.75; }
#exgSheet.ndb-mvlist .mrow i { color: var(--mut2); }
#exgSheet.ndb-mvlist .mrow:hover { background: var(--wash06); }
#exgSheet.ndb-mvlist button { color: var(--ink); font-size: .92rem;
  padding: .14rem .55rem; }
#exgSheet.ndb-mvlist button.past { color: var(--mut); }
#exgSheet.ndb-mvlist button:hover { background: var(--accfaint); }
#exgSheet.ndb-mvlist button.cur { background: var(--accfaint); color: var(--acc);
  font-weight: 600; }
#exgSheet.ndb-mvlist .mrow.currow { background: var(--wash06); }
#exgSheet.ndb-mvlist .mrow.currow i { color: var(--acc); }

/* .home-dir is the whole nav transcribed from the sidebar DOM itself
   (hdBuild) — one place labels live; the map can never drift */
#tab-home .home-dir { margin-top: 2rem; border-top: 1px solid var(--hairline);
  padding-top: 1.1rem; display: flex; flex-wrap: wrap; gap: 10px 22px; }
#tab-home .hd-h { flex: 0 0 100%; font-family: var(--mono); font-size: 9.5px;
  letter-spacing: .13em; text-transform: uppercase; color: var(--mut); }
#tab-home .hd-col { flex: 1 1 0; min-width: 0; }
#tab-home .hd-g { font-family: var(--mono); font-size: 9.5px; letter-spacing: .13em;
  text-transform: uppercase; color: var(--mut2); padding: 0 0 5px 2px; }
#tab-home .hd-sec { display: flex; flex-direction: column; gap: 1px; }
#tab-home .hd-col button { text-align: left; width: 100%; height: auto;
  background: none; border: none; border-left: 2px solid transparent;
  border-radius: 0 6px 6px 0; padding: 4px 6px 4px 8px; font-family: var(--sans);
  font-size: 12.5px; color: var(--ink2); cursor: pointer; }
#tab-home .hd-col button:hover { color: var(--ink); background: var(--wash06);
  border-left-color: var(--acc); }
@media (max-width: 900px) {
  #tab-home .hd-col { flex: 1 1 45%; }
}

/* flatten: every tab always on screen, group names are quiet captions */
#tabs { width: 212px; }
body { padding-left: 212px; }
#tabs .sg { padding-top: .3rem; }
#tabs .sg-lbl { padding: .5rem .55rem .35rem; font-size: .62rem; }
#tabs .sg-body button[data-tab] { font-size: .9rem; padding: .38rem .5rem .38rem .9rem;
  border-radius: 0 6px 6px 0; }

/* polish: pill rows — the active tab is a tinted pill, hover a whisper of
   fill */
#tabs { padding: .85rem .7rem 1rem; }
#wordmark { padding: .15rem .65rem .95rem; }
#tabs .sg-lbl { padding: .9rem .7rem .3rem; font-size: .6rem; letter-spacing: .2em; }
#tabs .sg:first-of-type .sg-lbl { padding-top: .35rem; }
#tabs .sg-body { gap: 1px; }
#tabs .sg-body button[data-tab] { font-size: .93rem; padding: .42rem .7rem;
  margin: 0 .1rem; border-left-color: transparent; border-radius: 7px;
  color: var(--ink); }
#tabs .sg-body button[data-tab]:hover:not(.on) {
  background: color-mix(in srgb, var(--ink) 6%, transparent); }
#tabs .sg-body button[data-tab].on { background: var(--accfaint); box-shadow: none;
  border-left-color: transparent; color: var(--acc); font-weight: 600; }

#tab-home .home-card.home-hero { grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center; column-gap: 2.2rem; }
#tab-home .home-hero .hc-board { grid-row: 1 / span 5; grid-column: 3; width: 208px;
  border-radius: 8px; overflow: hidden; cursor: pointer; line-height: 0;
  box-shadow: 0 10px 28px rgba(0,0,0,.38);
  transition: transform .16s ease, box-shadow .16s ease; }
#tab-home .home-hero .hc-board:hover { transform: translateY(-3px);
  box-shadow: 0 16px 38px rgba(0,0,0,.5); }
#tab-home .home-hero .hc-board svg { display: block; width: 100%; height: auto; }
#tab-home .hstat b { font-size: 2.1rem; line-height: 1.1; }
#tab-home .hstat { min-width: 7rem; }
@media (max-width: 1100px){
  #tab-home .home-hero .hc-board { width: 150px; }
}
@media (max-width: 900px){
  #tab-home .home-card.home-hero { grid-template-columns: 1fr; }
  #tab-home .home-hero .hc-board { grid-row: auto; grid-column: 1; width: 170px;
    margin-top: 1rem; }
}


/* the frame: command bar · [sources | strip + view | rail] · status. Every
   legacy tab lives inside #wbView — the ONLY thing that scrolls; the
   sidebar is the frame's left column, not fixed chrome. */
/* THE FRAME IS THE VIEWPORT, INCLUDING ITS ONE COLUMN (2026-07-30 pm2).
   #wb is fixed at inset:0, but its implicit column was `auto` — sized to the
   widest ROW. Below ~1000px #wbBody's own tracks (26 edge + 250 register +
   board + 330 rail) exceed the viewport, so every row stretched with it:
   measured 1139px of chrome inside a 900px frame, which put the coverage
   readout, the bell and the settings gear off-screen with nothing to scroll
   them back — document.scrollWidth stayed 900. minmax(0,1fr) is a no-op at
   any width where the content fits; below that, #wbView goes on being the
   one scroller, which is the design. */
#wb { position: fixed; inset: 0; display: grid;
  grid-template-columns: minmax(0, 1fr);
  /* two rows since the doorframe (2026-08-10): the room, then the strip.
     The 34px header row is retired — #wbCmd is display:none and #hrBar is
     never mounted, so the first child that generates a track is #wbBody. */
  grid-template-rows: minmax(0, 1fr) auto; background: var(--paper); }
body { padding-left: 0 !important; }
#wbBody { position: relative; display: grid; min-height: 0;
  grid-template-columns: var(--wb-left, 208px) minmax(0, 1fr) var(--wb-rail, 252px); }
#wbView { grid-area: auto; overflow: auto; overscroll-behavior: contain;
  scrollbar-gutter: stable; min-height: 0; background: var(--paper); }
/* auto, not a fixed 28px: when a full-frame view hides the strip the row
   must collapse to nothing instead of stealing the viewport's height */
#wbMain { display: grid; grid-template-rows: auto minmax(0, 1fr); min-width: 0; min-height: 0; }


/* left rail: ONE tree — the nav's five captions with the collections
   rendered under DATABASE (#sgColl) */
#wbLeft { overflow: auto; overscroll-behavior: contain; background: var(--surface);
  border-right: 1px solid var(--hairline2); min-width: 0; }
.wb-src { display: flex; align-items: center; gap: 8px; width: 100%; height: 24px;
  padding: 0 12px; background: none; border: none; border-left: 2px solid transparent;
  font-family: var(--chrome); font-size: 12px; color: var(--ink2); cursor: pointer;
  text-align: left; }
.wb-src:hover { background: var(--wash06); color: var(--ink); }
.wb-src.on { background: var(--wash06); border-left-color: var(--acc); color: var(--ink); }
.wb-src-g { width: 12px; text-align: center; color: var(--mut); font-size: 11px; }
.wb-src-l { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wb-src-n { font-family: var(--mono); font-size: 10px; color: var(--mut2);
  font-variant-numeric: tabular-nums; }
.wb-src.on .wb-src-n { color: var(--acc); }

/* the nav becomes the tree's lower half — no fixed positioning, no wordmark */
#tabs { position: static !important; width: auto !important; height: auto !important;
  border: none !important; background: none !important; padding: 0 0 14px !important;
  overflow: visible !important; box-shadow: none !important; }
#tabs #wordmark, #tabs #loglink, #tabs .side-sp { display: none !important; }

/* board screens size against the PANE, not the viewport — inside the frame
   the centre is (100vw − tree − rail), and a 100vh-wide board column would
   run straight under the control card */
/* height budgets carry the doorframe (2026-08-10): the 34px header row is
   gone and the strip is 26px, so every chrome constant here dropped 28px */
#wbView .solve-grid {
  grid-template-columns: minmax(260px, min(calc(100dvh - 162px), calc(100% - 380px)))
                         minmax(280px, 350px) !important; }
#wbView #artPlayer .solve-grid {
  grid-template-columns: minmax(280px, min(calc(100dvh - 102px), calc(100% - 340px)))
                         minmax(280px, 310px) !important; }
#wbView .wrap, #wbView .solve-grid { margin-right: 0 !important; }
/* --bd (solve-session.css) is the one source of board size, and it
   is a BOARD-SCREEN variable: every consumer is gated on body.svpage. On
   those screens the frame recedes — tree, rail, strip and command bar are
   display:none ("immersive board screens", solve-session.css) —
   so the pane IS the viewport and the only thing beside the board is the
   control card. Subtracting a tree and a rail that are not on screen cost
   the board ~460px: invisible at 1600px, ruinous at 1180px (an iPad in
   landscape held a 300px board in a 630px track). One budget: card 400 +
   gap and padding 30. The track follows --bd (+28 = rank strip + mat) so
   board and column can't disagree. (No !important on --bd: that used to
   leave room for the splitter's inline write, and the splitter is gone —
   the frame does not resize.) */
@media (min-width: 1000px) {
  /* the height budget is measured, not guessed: solve-top 45 + mat 14 +
     files 15 + row gaps 19 + slack, plus the 26px strip — which is ALWAYS
     on since the doorframe (it carries the way home), so the old stb-on
     split died with the 34px header row: (124 − 34) + 26 = 116. */
  body.svpage { --sv-chrome: 116px; --sv-side: 430px; }
  body.svpage #wbView .solve-grid {
    --bd: min(calc(100dvh - var(--sv-chrome)), calc(100vw - var(--sv-side)));
    grid-template-columns: calc(var(--bd) + 28px) minmax(280px, 400px) !important; }
  #wbView #svBoard svg, #wbView #tab-solve .sv-card #svBoard svg { max-width: 100% !important; }
  #wbView .sv-files { max-width: 100%; }
}

/* ---- portrait: the control card goes UNDER the board -----------------
   A tall window has width to spare in one direction only. Beside the
   board, the card costs 400px of the 834 an iPad has in portrait and the
   board keeps 370; under it, the board takes the full column (~780) and
   the card reads at eye level below — the same two panes, stacked. The
   height cap keeps the whole board plus its files and status line on
   screen, so the card starts just below the fold and scrolls up.
   The framed players make the same call further down. */
@media (orientation: portrait) and (max-width: 1180px) {
  body.svpage #wbView .solve-grid {
    --bd: min(calc(100vw - 56px), calc(100dvh - 182px));   /* −28: doorframe */
    grid-template-columns: minmax(0, 1fr) !important;
    gap: 18px !important; }
  body.svpage #wbView .solve-side, body.svpage #wbView .solve-side.v2 {
    width: auto !important; max-height: none !important; }
}
/* below the tablet gate the mobile card layout still dresses the board, so it
   never learned --bd. It used to subtract 14px for the content-box mat; the
   mat is gone (THE BOARD'S ONE EDGE) and the hairline is border-box, so the
   board takes the whole measure. One column, one measure. */
@media (orientation: portrait) and (max-width: 699px) {
  body.svpage #wbView #tab-solve .sv-card #svBoard svg {
    width: var(--bd) !important; max-width: none !important; }
}
/* stacked, the card is no longer a column of its own — it takes the board's
   measure so board, files and panel share one left edge and one right edge,
   and the engine pane never stretches to a 1000px eval bar */
@media (orientation: portrait) and (min-width: 700px) and (max-width: 1180px) {
  body.svpage #wbView .solve-side, body.svpage #wbView .solve-side.v2 {
    margin-left: 21px; max-width: var(--bd) !important; }
}

/* ---- the framed players on a tablet ---------------------------------
   Article / player-database / Super GM boards keep the frame (tree, rail,
   strip) around them, so their board is what is left of the pane after the
   scoresheet. At 1180 that is 532px of a 690px height budget, and the
   difference is entirely desktop page padding: 32px gutters and a 36px gap
   written for a 1600px window. Trim the gutters, hold the scoresheet at
   its readable minimum, and the board takes the rest. */
@media (max-width: 1280px) {
  #wbView .solve-grid { padding-left: 12px !important; padding-right: 12px !important;
    gap: 20px !important; }
  /* the minimums come down with the gutters: with the tree AND the rail
     open a 1024 landscape leaves 564px of pane, and 260+280 tracks plus
     desktop gutters cannot fit in it without overflowing the pane */
  #wbView .solve-grid {
    grid-template-columns: minmax(220px, min(calc(100dvh - 190px), calc(100% - 320px)))
                           minmax(240px, 300px) !important; }
  #wbView #artPlayer .solve-grid {
    grid-template-columns: minmax(220px, min(calc(100dvh - 130px), calc(100% - 320px)))
                           minmax(240px, 300px) !important; }
}
/* Portrait, or a tablet-width frame with the rail open — both are the same
   condition: the pane is too narrow to seat a board and a scoresheet side
   by side (1024 landscape with tree + rail leaves 564px, which squeezed the
   board to its 220px minimum). Stack instead: the scoresheet reads directly
   under the board, which is where it reads on a tablet anyway. The rail
   state is a body class, so this needs no container query. */
@media (orientation: portrait) and (max-width: 1180px) {
  #wbView .solve-grid, #wbView #artPlayer .solve-grid {
    grid-template-columns: minmax(0, 1fr) !important; }
  #wbView .solve-side { width: auto !important; max-height: none !important; }
}
@media (max-width: 1280px) {
  body:not(.wb-norail):not(.svpage) #wbView .solve-grid,
  body:not(.wb-norail):not(.svpage) #wbView #artPlayer .solve-grid {
    grid-template-columns: minmax(0, min(calc(100dvh - 190px), 100%)) !important; }
  body:not(.wb-norail):not(.svpage) #wbView .solve-side {
    width: auto !important; max-height: none !important; }
}


/* right rail: panes */
#wbRail { overflow: auto; overscroll-behavior: contain; background: var(--surface);
  border-left: 1px solid var(--hairline2); min-width: 0; }
#wbRail[data-empty] { background: var(--surface); }
.wb-pane { border-bottom: 1px solid var(--hairline2); }
.wb-pane-h { display: flex; align-items: baseline; gap: 8px; margin: 0;
  padding: 9px 10px 7px; font-family: var(--mono); font-size: 9px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--mut2); font-weight: 400; }
.wb-pane-hint { margin-left: auto; font-style: normal; font-size: 9.5px;
  letter-spacing: .04em; text-transform: none; color: var(--mut2); }
.wb-pane-b { padding: 0 10px 11px; }
.wb-pos-idle { margin: 0; font-size: 11.5px; color: var(--mut); line-height: 1.5; }
.wb-posrow { display: grid; grid-template-columns: 1fr 44px 46px 30px; gap: 8px;
  align-items: center; height: 22px; font-size: 11.5px; color: var(--ink2); }
.wb-pos-s { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wb-pos-n { font-family: var(--mono); font-size: 11px; text-align: right; color: var(--ink);
  font-variant-numeric: tabular-nums; }
.wb-pos-p { font-family: var(--mono); font-size: 10px; color: var(--mut); text-align: right; }
.wb-bar { display: flex; height: 7px; background: var(--hairline2); border-radius: 1px;
  overflow: hidden; }
.wb-bar i { display: block; height: 100%; }
.wb-bar .w { background: var(--ink2); }
.wb-bar .d { background: var(--mut2); }
.wb-cliprow { display: flex; align-items: baseline; gap: 8px; width: 100%; padding: 3px 0;
  background: none; border: none; text-align: left; cursor: pointer;
  font-family: var(--chrome); font-size: 11.5px; color: var(--ink2); }
.wb-cliprow:hover { color: var(--ink); }
.wb-cliprow span { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wb-cliprow em { font-style: normal; font-family: var(--mono); font-size: 10px; color: var(--mut2); }
.wb-clipall { margin-top: 6px; background: none; border: none; padding: 0;
  font-family: var(--mono); font-size: 10px; color: var(--acc); cursor: pointer; }

/* status line */
/* the chat rail is a fixed 30px tab on the right edge — the frame keeps
   that lane clear instead of letting it sit on top of the rail's numbers */
#wbRail { padding-right: 30px; }
#labChat { top: 0 !important; bottom: 26px !important; }   /* no header row; the strip is 26px */
#svAppBar { position: static !important; display: flex !important; align-items: center;
  height: 22px; padding: 0 34px 0 10px; border-top: 1px solid var(--hairline2);
  border-bottom: none; background: var(--surface); font-family: var(--mono);
  font-size: 10px; color: var(--mut); width: auto !important; left: auto !important;
  right: auto !important; bottom: auto !important; }
#svAppBar .svapp-l, #svAppBar .svapp-r { display: flex; align-items: center; gap: 12px; }
#svAppBar .svapp-r { margin-left: auto; }
#svAppBar.wb-bar { position: static !important; display: flex !important; align-items: center;
  gap: 0; height: 22px; padding: 0 10px; border-top: 1px solid var(--hairline2);
  background: var(--surface); font-family: var(--mono); font-size: 10px; color: var(--mut);
  width: auto !important; }
.wb-st-l, .wb-st-r { display: flex; align-items: center; gap: 12px; }
.wb-st-r { margin-left: auto; }

/* grips */
.wb-grip { position: absolute; top: 0; bottom: 0; width: 7px; cursor: col-resize; z-index: 3; }
.wb-grip-l { left: calc(var(--wb-left, 208px) - 3px); }
.wb-grip-r { right: calc(var(--wb-rail, 252px) - 3px); }
.wb-grip:hover { background: var(--accfaint); }
body.wb-dragging { cursor: col-resize; user-select: none; }

/* the solve page inside the frame: it already manages its own height */
body.svpage { height: auto; overflow: visible; }
#wbView > #tab-solve { min-height: 100%; }

@media (max-width: 1000px) {
  #wb { position: static; display: block; height: auto; }
  #wbBody { display: block; }
  #wbLeft { position: fixed; inset: 0 auto 0 0; width: 214px; z-index: 60;
    transform: translateX(-100%); transition: transform .16s ease;
    padding-top: 34px; }                        /* clear the ☰ */
  body.sideopen #wbLeft { transform: none; }
  #wbRail, .wb-grip, #wbCmd { display: none; }
  #wbView { overflow: visible; }
  #svAppBar { position: fixed !important; left: 0 !important; right: 0 !important;
    bottom: 0 !important; z-index: 40; padding-right: 10px; }
}

.wb-bd { line-height: 0; }   /* the svg owns the edge — see THE BOARD'S ONE EDGE */
.wb-bd svg { display: block; width: 100%; height: auto; }
.wb-bd-meta { display: flex; align-items: center; gap: 8px; padding: 6px 0 2px;
  font-family: var(--chrome); font-size: 11.5px; color: var(--ink2); }
.wb-bd-l { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wb-bd-flip { background: none; border: none; color: var(--mut); cursor: pointer;
  font-size: 12px; padding: 0 2px; }
.wb-bd-flip:hover { color: var(--ink); }
.wb-bd-open { width: 100%; margin-top: 4px; padding: 4px 6px; background: none;
  border: 1px solid var(--hairline3); border-radius: 5px; color: var(--acc);
  font-family: var(--mono); font-size: 10px; cursor: pointer; }
.wb-bd-open:hover { background: var(--wash06); }

.db-verbhost { display: flex; }
.db-verbs { display: flex; gap: 6px; }
.db-verb { display: flex; align-items: baseline; gap: 5px; font-family: var(--mono);
  font-size: 10px; letter-spacing: .04em; color: var(--ink2); background: none;
  border: 1px solid var(--hairline3); border-radius: 5px; padding: 4px 8px; cursor: pointer; }
.db-verb:hover:not([disabled]) { border-color: var(--accdim); color: var(--ink);
  background: var(--wash06); }
.db-verb[disabled] { opacity: .4; cursor: default; }
.db-verb em { font-style: normal; color: var(--mut); }

/* --- the heroes come down (inside the frame only) --- */
#wbView .hero { display: block; padding: 14px 0 12px; border-bottom: 1px solid var(--hairline);
  margin-bottom: 14px; }
#wbView .hero > div { display: block; }
#wbView .hero h1 { font-size: 19px !important; font-weight: 600; letter-spacing: -.005em;
  margin: 2px 0 4px !important; }
#wbView .hero .eyebrow { font-size: 9px; letter-spacing: .16em; margin: 0 0 2px; }
#wbView .hero .lede { font-size: 12.5px; line-height: 1.5; color: var(--mut);
  max-width: 74ch; margin: 0; }
#wbView .hero .sv-chips, #wbView .hero .ex-stats { margin-top: 8px !important; }
#wbView .hero .hero-brd, #wbView .hero .brd-cap { display: none; }
#wbView .wrap { padding-top: 12px; }
#wbView .pos-head h1 { font-size: 21px; }
#tab-home .home-dir { margin-top: 1.4rem; }

/* saved searches in the tree + the keep dialog (move 03's last piece) */
.wb-q .wb-src-l { font-style: italic; }
.wb-q-x { color: var(--mut2); font-size: 10px; opacity: 0; padding-left: 4px; }
.wb-src:hover .wb-q-x { opacity: 1; }
.wb-q-x:hover { color: var(--bad); }
.db-verb-save { border-style: dashed; }
#labDialog .ld-h { font-size: 15px; margin: 0 0 6px; }
#labDialog .ld-p { font-size: 12.5px; color: var(--ink2); margin: 0 0 10px; }
#labDialog .ld-p em { font-style: normal; font-family: var(--mono); font-size: 11.5px; }
#labDialog .db-q { width: 100%; }
#labDialog .ld-row { display: flex; justify-content: flex-end; margin-top: 10px; }

/* the player database uses the one grid now — its bespoke table is gone */
.ndb-grid { margin-top: .6rem; }
.ndb-grid .side-dot { width: 7px; height: 7px; vertical-align: baseline; margin-right: 2px; }
.ndb-grid .ndb-res.ok { color: var(--ok); font-style: normal; }
.ndb-grid .ndb-res.bad { color: var(--bad); font-style: normal; }
.ndb-grid .ndb-res { font-family: var(--mono); font-size: 11.5px; font-style: normal; }
.ndb-empty { font-family: var(--chrome); font-size: 12.5px; color: var(--mut); padding: 16px 12px; }

/* one ground: everything shares --paper, separators are 1px lines, and the
   only tinted surfaces are things you can act on */
#wbLeft, #wbRail, #svAppBar, #wbView { background: var(--paper); }
#wbLeft { border-right: 1px solid var(--hairline2); }
#wbRail { border-left: 1px solid var(--hairline2); }

/* group separation is the row contract's call (see THE TREE ROW CONTRACT) —
   the mono captions carry it, so no hairlines here */

/* data views fill the pane; a fixed page width inside a frame is page
   thinking, and it cut the last columns off the player database */
#wbView #tab-nihal .wrap, #wbView #tab-elite .wrap, #wbView #tab-sync .wrap,
#wbView #tab-explorer .wrap { max-width: none !important; }
.ndb-filters { flex-wrap: wrap; }

/* a rail with nothing to say gives its column back to the work */
body.wb-norail #wbBody { grid-template-columns: var(--wb-left, 208px) minmax(0, 1fr); }
body.wb-norail #wbRail, body.wb-norail .wb-grip-r { display: none; }
/* the chat rail is a fixed 30px lane on the right edge; with the pane rail
   gone the view has to keep that lane clear itself or the last column of
   every grid sits under it */
body.wb-norail #wbView { padding-right: 30px; }

/* ---- every header is a title row --------------------------------
   .pos-head kept its 46px serif masthead (home) and clamp(2.4rem) page
   headlines (nihal, structures, explorer). Inside the frame a headline
   is one row: mono eyebrow, 17px chrome name, one-line lede. */
#wbView .pos-head { padding: 10px 0 10px !important; margin: 0 0 12px !important;
  border-bottom: 1px solid var(--hairline); }
#wbView .pos-head h1, #wbView .wrap header.pos-head h1 {
  font-family: var(--chrome) !important; font-size: 17px !important; font-weight: 600;
  letter-spacing: -.005em !important; margin: 2px 0 3px !important; }
#wbView .pos-head .eyebrow { font-family: var(--mono) !important; font-size: 9px !important;
  letter-spacing: .16em !important; color: var(--mut2) !important; margin: 0; }
#wbView .pos-head .lede { font-family: var(--chrome) !important; font-style: normal !important;
  font-size: 12.5px !important; line-height: 1.5 !important; color: var(--mut) !important;
  max-width: 74ch; margin: 2px 0 0 !important; }

/* ---- the work hugs the pane --------------------------------------
   A centered 62rem column inside a frame is page thinking; the one
   exception is the reading room, where prose keeps a measure. */
#wbView .wrap { max-width: none; padding-left: 20px; padding-right: 24px; }
#wbView #tab-articles .wrap { max-width: 68rem; }

/* ---- home: a register, not a dashboard ---------------------------
   The today numbers stop being a serif folio and become the readout
   strip every instrument has: label · value · label · value. */







/* the piles are rows in one register: name, where you stand, how far,
   a verb. Nothing is a card, nothing casts a shadow, nothing lifts. */
















/* the resume row is the same register row — plus the one preview on the
   page, the next position itself. The filled yellow CTA was the last
   marketing button on the site; it is a verb now. */









@media (max-width: 1100px){
  #wbView #tab-home .home-hero .hc-board { width: 72px; }
}

/* the tree is the directory — printing the sitemap under the piles was
   the last piece of website thinking on the page */
#wbView #homeDir { display: none; }

/* ---- the chat rail docks ------------------------------------------
   A bubble floating at mid-height over the numbers is a website
   affordance; the lane keeps its width but its cargo sits on the floor,
   above the status line, like every other docked panel. */
#wb .lc-rail { justify-content: flex-end; padding-bottom: 8px; }

/* ---- follow-ups: one title size, a packed resume row ---------------
   move 06 left .hero at 19px, .pos-head came down to 17px — one size.
   The player-database head is the same row in the same size. */
#wbView .hero h1 { font-size: 17px !important; }
#wbView .ndb-head { padding: 10px 0 4px; }
#wbView .ndb-titlerow h1 { font-family: var(--chrome); font-size: 17px;
  letter-spacing: -.005em; }

/* the resume row is taller than the others because the board previews
   beside it — pack its two text lines around the seam so they read as
   one centred block instead of drifting to the corners */



/* one hairline above the register, not two (the head already rules off) */


/* ---- phone: the register collapses to stacked rows ----------------- */


/* a window is a toolbar, a work surface and a status line — no headlines,
   ledes, cards or primary buttons inside the frame; controls are small,
   flat, in the toolbar next to what they act on */
.wb-tb { display: flex; align-items: center; gap: 8px; min-height: 30px;
  padding: 0 2px; border-bottom: 1px solid var(--hairline2); flex-wrap: wrap; }
.wb-tb-t { font-family: var(--chrome); font-size: 12.5px; font-weight: 600;
  color: var(--ink); letter-spacing: -.005em; white-space: nowrap; }
.wb-tb-m { font-family: var(--mono); font-size: 10px; color: var(--mut);
  white-space: nowrap; }
.wb-tb-sep { width: 1px; height: 14px; background: var(--hairline2); }
.wb-tb-grow { flex: 1; }
.wb-tb-b { font-family: var(--mono); font-size: 10px; letter-spacing: .03em;
  color: var(--ink2); background: none; border: 1px solid transparent;
  border-radius: 4px; padding: 3px 7px; cursor: pointer; white-space: nowrap; }
.wb-tb-b:hover:not([disabled]) { background: var(--wash06); color: var(--ink);
  border-color: var(--hairline3); }
.wb-tb-b[disabled] { opacity: .35; cursor: default; }
.wb-tb-b.on { color: var(--acc); border-color: var(--accdim); }
.wb-tb-b em { font-style: normal; color: var(--mut); margin-left: 4px; }
.wb-tb-q { flex: 1 1 15rem; min-width: 8rem; font-family: var(--chrome);
  font-size: 11.5px; color: var(--ink); background: none;
  border: 1px solid var(--hairline2); border-radius: 4px; padding: 3px 7px; }
.wb-tb-q:focus { outline: none; border-color: var(--accdim); }
.wb-tb-s { font-family: var(--mono); font-size: 10px; color: var(--ink2);
  background: none; border: 1px solid var(--hairline2); border-radius: 4px;
  padding: 2px 4px; max-width: 9rem; }
.wb-tb-s:focus { outline: none; border-color: var(--accdim); }

/* page furniture does not exist inside the frame */
/* ONE title row for every view. The rooms use two different header classes
   (.hero and .pos-head) for the same job; rather than delete one and style
   the other they get the identical treatment — mono eyebrow, chrome name,
   one-line lede, hairline under. A view whose header is pure duplication of
   its toolbar (the databases) drops it entirely. */
#wbView .hero { display: block !important; padding: 10px 0 !important;
  margin: 0 0 12px !important; border-bottom: 1px solid var(--hairline);
  border-radius: 0 !important; background: none !important; }
#wbView .hero > div { display: block; }
#wbView .hero h1 { font-family: var(--chrome) !important; font-size: 17px !important;
  font-weight: 600 !important; letter-spacing: -.005em !important;
  margin: 2px 0 3px !important; }
#wbView .hero .eyebrow { font-family: var(--mono) !important; font-size: 9px !important;
  letter-spacing: .16em !important; color: var(--mut2) !important; margin: 0 !important; }
#wbView .hero .lede { font-family: var(--chrome) !important; font-style: normal !important;
  font-size: 12.5px !important; line-height: 1.5 !important; color: var(--mut) !important;
  max-width: 78ch; margin: 2px 0 0 !important; }
#wbView .hero .sv-chips { margin-top: 8px !important; }
#wbView .ndb-head, #wbView .ndb-titlerow, #wbView .ndb-lede,
#wbView .db-hero { display: none !important; }
#wbView .wrap { padding-top: 0; }
.ndb-players { display: flex; gap: 4px; flex-wrap: nowrap; }
.ndb-players button { font-family: var(--mono); font-size: 10px; color: var(--mut);
  background: none; border: 1px solid transparent; border-radius: 4px;
  padding: 3px 7px; cursor: pointer; white-space: nowrap; }
.ndb-players button:hover { color: var(--ink); background: var(--wash06); }
.ndb-players button.on { color: var(--acc); border-color: var(--accdim); }
.db-read { display: flex; gap: 5px; }
.db-read em { font-style: normal; font-family: var(--mono); font-size: 9.5px;
  color: var(--mut); border: 1px solid var(--hairline2); border-radius: 3px;
  padding: 2px 5px; }
.db-verbhost { display: flex; gap: 4px; }

/* ---- the star: save a game from any list (js/15-database.js) ---------
   A row in a games list already answers "open" on double-click and "clip"
   on c; keeping it is the third verb, and on a tablet — no keyboard, no
   right-click — the star in the row is the only one of the three you can
   reach. So it is a tap target first and a marker second: 24px of column,
   the whole cell hit-testable, muted until it is yours. */
.db-grid .db-star { text-align: center; cursor: pointer; color: var(--mut2);
  font-size: 12px; line-height: 1; overflow: visible; user-select: none;
  -webkit-user-select: none; }
.db-grid .db-star:hover { color: var(--ink); }
.db-grid .db-star.on { color: var(--acc); }
@media (pointer: coarse) {
  /* the finger version: the cell keeps its 24px column but takes the row's
     full height as its target */
  .db-grid .db-star { font-size: 15px; }
}

.ac-wrap { max-width: 900px; }
.ac-hero { display: flex; flex-direction: column; gap: 8px; padding: 26px 0 22px;
  border-bottom: 1px solid var(--hairline2); }
.ac-mark { width: 34px; height: 34px; display: flex; align-items: center;
  justify-content: center; font-size: 17px; border-radius: 8px; color: var(--acc);
  background: color-mix(in srgb, var(--acc) 12%, transparent);
  border: 1px solid var(--accdim); }
.ac-hero h1 { margin: 0; font-family: var(--chrome); font-size: 21px; font-weight: 600;
  letter-spacing: -.01em; color: var(--ink); }
.ac-lede { margin: 0; max-width: 54ch; font-family: var(--chrome); font-size: 13px;
  line-height: 1.6; color: var(--ink2); }
.ac-lede a { color: var(--acc); }
.ac-dot { display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  background: var(--ok, #7fd18c); margin-right: 7px; vertical-align: middle; }
.ac-dot.warn { background: var(--btn, #c9a86a); }

.ac-cols { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 34px; padding: 22px 0 40px; align-items: start; }
@media (max-width: 780px) { .ac-cols { grid-template-columns: minmax(0, 1fr); gap: 24px; } }

.ac-form { display: flex; flex-direction: column; gap: 7px; max-width: 380px; }
.ac-seg { display: flex; gap: 2px; margin-bottom: 10px;
  border-bottom: 1px solid var(--hairline2); }
#tab-account .ac-seg button { appearance: none; background: none; border: none; cursor: pointer;
  padding: 6px 10px 8px; border-bottom: 2px solid transparent;
  font-family: var(--mono); font-size: 10px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--mut); }
#tab-account .ac-seg button:hover { color: var(--ink); }
#tab-account .ac-seg button.on { color: var(--ink); border-bottom-color: var(--acc); }
.ac-lab { font-family: var(--mono); font-size: 9.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--mut); margin-top: 6px; }
#tab-account .ac-form input { width: 100%; box-sizing: border-box; font-family: var(--chrome);
  font-size: 14px; color: var(--ink); background: var(--card);
  border: 1px solid var(--hairline3); border-radius: 7px; padding: 9px 11px; }
#tab-account .ac-form input:focus { outline: none; border-color: var(--acc); }
#tab-account .ac-go { appearance: none; cursor: pointer; margin-top: 14px; align-self: flex-start;
  background: var(--acc); color: #0a1622; border: 1px solid var(--acc);
  border-radius: 7px; padding: 9px 18px; font-family: var(--chrome);
  font-size: 13px; font-weight: 600; }
#tab-account .ac-go:hover { filter: brightness(1.08); }
#tab-account .ac-go:disabled { opacity: .55; cursor: wait; }
#tab-account .ac-go-quiet { background: none; color: var(--ink); border-color: var(--hairline3);
  font-weight: 500; }
#tab-account .ac-go-quiet:hover { background: var(--wash06); filter: none; border-color: var(--acc); }
#tab-account .ac-ghost { appearance: none; cursor: pointer; background: none; color: var(--mut);
  border: 1px solid transparent; border-radius: 7px; padding: 9px 14px;
  font-family: var(--chrome); font-size: 13px; }
#tab-account .ac-ghost:hover { color: var(--bad, #d98b8b); border-color: var(--hairline3); }
.ac-btnrow { display: flex; align-items: center; gap: 8px; margin-top: 6px; }
.ac-msg { min-height: 1.1em; font-family: var(--mono); font-size: 11px;
  color: var(--mut); }
.ac-msg.bad { color: var(--bad, #d98b8b); }
.ac-fine { margin: 12px 0 0; font-family: var(--chrome); font-size: 11.5px;
  line-height: 1.65; color: var(--mut); max-width: 44ch; }
.ac-fine b { color: var(--ink2); font-weight: 600; }
.ac-warn { color: var(--btn, #c9a86a); }

.ac-side-h { font-family: var(--mono); font-size: 9.5px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--mut2); padding-bottom: 8px;
  border-bottom: 1px solid var(--hairline2); }
.ac-stores { display: flex; flex-direction: column; }
.ac-store { display: flex; align-items: baseline; gap: 10px; padding: 8px 0;
  border-bottom: 1px solid var(--hairline); }
.ac-store-n { min-width: 3.4em; text-align: right; font-family: var(--mono);
  font-size: 13px; color: var(--ink); font-variant-numeric: tabular-nums lining-nums; }
.ac-store-l { font-family: var(--chrome); font-size: 12.5px; color: var(--ink2); }


/* ====== THE WALL (owner, 2026-08-22: "hide the screen behind a wall unless
   u already have a log in") =============================================
   One attribute, html[data-wall], stamped at parse by the skeleton's head
   script and resolved by 19b pwApply — this file paints everything off it:
   the curtain, and the hiding of every other body child (the site is
   still there, inert, for the moment the wall lifts). The curtain wears
   the door voice — the strip's pine, buff ink, Caslon word, mono verbs in
   the band-cell form (ONE BUTTON VOICE: a segment of one row on the lifted
   pine ground, .26 dividers, .34 rules, open cell, red inversion on hover,
   the armed cell's ink the flag-light). --dv-* are reads of door-frame's
   tokens with raw fallbacks (the body-class-gate law). The form inside is
   the room's own markup (.ac-*), re-dressed under #plWall so the house
   layers that later dress .ac-go for the room lose on specificity, not on
   a shout. The wall is the one scroll organ of its own plate (the page
   never scrolls; a 320px landscape phone still reaches the verb). */
#plWall{ display:none; }
html[data-wall] #plWall{
  display:flex; position:fixed; inset:0; z-index:100000;
  align-items:center; justify-content:center;
  overflow:auto; padding:24px;
  background:var(--dv-pine,#24382d); color:var(--dv-buff-ink,#efe9d6);
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
}
html[data-wall] body > :not(#plWall){ visibility:hidden; }
.pw-card{
  display:flex; flex-direction:column; gap:8px;
  width:min(380px, 100%); margin:auto;
}
.pw-mark{
  width:34px; height:34px; display:flex; align-items:center; justify-content:center;
  font-size:17px; color:var(--dv-flag-lt,#e0906c);
  border:1px solid rgba(233,225,204,.26); border-radius:0;
}
.pw-title{
  margin:14px 0 0;
  font-family:var(--serif,'Libre Caslon Text',Georgia,serif);
  font-size:26px; font-weight:400; letter-spacing:.01em; line-height:1.15;
  color:var(--dv-buff-ink,#efe9d6);
}
.pw-lede{
  margin:0 0 14px; max-width:44ch; font-size:13px; line-height:1.6;
  color:var(--dv-sage,#a9b8a6);
}
/* the mode row is a band: two cells, the armed one in the flag-light */
#plWall .ac-form{ max-width:none; gap:7px; }
#plWall .ac-seg{
  display:flex; gap:0; margin:0 0 10px; align-items:stretch; height:44px;
  background:var(--dv-pine-hi,#2b4336);
  border-top:1px solid rgba(233,225,204,.34);
  border-bottom:1px solid rgba(233,225,204,.34);
}
#plWall .ac-seg button{
  appearance:none; flex:1 1 auto; min-width:0; height:100%; cursor:pointer;
  border:0; border-right:1px solid rgba(233,225,204,.26); border-radius:0;
  background:none; color:var(--dv-buff-ink,#efe9d6); padding:0 12px;
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:12px; font-weight:500; letter-spacing:.1em; line-height:1;
  text-transform:none;
  transition:color .15s ease, border-color .15s ease, background-color .15s ease;
}
#plWall .ac-seg button:last-child{ border-right:0; }
#plWall .ac-seg button:hover{
  background:var(--dv-flag,#a8402c); color:#f2e8d8; border-color:transparent;
}
#plWall .ac-seg button.on{ color:var(--dv-flag-lt,#e0906c); }
#plWall .ac-lab{
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace);
  font-size:10px; letter-spacing:.1em; text-transform:uppercase;
  color:var(--dv-moss,#5d6b5f); margin-top:6px;
}
#plWall .ac-form input{
  width:100%; box-sizing:border-box; border-radius:0;
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace); font-size:13px;
  color:var(--dv-buff-ink,#efe9d6); background:rgba(233,225,204,.04);
  border:1px solid rgba(233,225,204,.22); padding:9px 11px;
}
#plWall .ac-form input::placeholder{ color:var(--dv-moss,#5d6b5f); }
#plWall .ac-form input:focus{ outline:none; border-color:var(--dv-flag-lt,#e0906c); }
/* the verb: a one-cell band, the flag-light standing, the inversion on hover */
#plWall .pw-go{
  appearance:none; cursor:pointer; margin-top:14px; align-self:stretch;
  display:flex; align-items:center; justify-content:center; height:44px;
  background:var(--dv-pine-hi,#2b4336); color:var(--dv-flag-lt,#e0906c);
  border:0; border-top:1px solid rgba(233,225,204,.34);
  border-bottom:1px solid rgba(233,225,204,.34); border-radius:0;
  padding:0 12px; box-shadow:none; filter:none;
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:12px; font-weight:500; letter-spacing:.1em; line-height:1;
  transition:color .15s ease, background-color .15s ease;
}
#plWall .pw-go:hover{ background:var(--dv-flag,#a8402c); color:#f2e8d8; filter:none; }
#plWall .pw-go:disabled{ opacity:.55; cursor:wait; }
#plWall .pw-go:focus-visible, #plWall .ac-seg button:focus-visible{
  outline:2px solid var(--dv-flag-lt,#e0906c); outline-offset:-2px;
}
#plWall .ac-msg{
  min-height:1.1em; font-family:var(--mono,'Spline Sans Mono',Menlo,monospace);
  font-size:11px; color:var(--dv-sage,#a9b8a6);
}
#plWall .ac-msg.bad{ color:var(--dv-flag-lt,#e0906c); }
#plWall .ac-fine{ margin:12px 0 0; font-size:11.5px; line-height:1.65; color:var(--dv-moss,#5d6b5f); max-width:44ch; }
/* the graphite token block re-points --chrome, --mono and the --g-* grid
   tokens — it must stay after the token/theme files it re-points */

:root[data-lab-theme="graphite"]{
  /* ---- palette: the graphite greys turned to the landing's PINE
     (owner call 2026-08-10, "ignore the theme — pave your own road").
     Every stop keeps its old lightness and swaps hue toward the rank's
     tournament green, so every contrast relationship the longform measured
     survives the re-ground by construction. Brass stays: club brass on
     green baize is the material this palette was always reaching for. ---- */
  --paper:#0f130f;  --paper2:#0c100c;  --surface:#131a14;  --surface2:#171e17;
  --cardsolid:#171e17; --card:#0f130f;  --panelbg:#0f130f;  --chatbg:#0c100c;
  --chrome-bg:#0a0d0a; --surface3:#1e261e;
  --ink:#e0e4dd;    --ink2:#a8b1a3;    --mut:#71806e;      --mut2:#5e6b5c;
  --mut3:#4c5849;   --mut4:#3b473a;
  --hairline:#181f18;  --hairline2:#1a221a;  --hairline3:#253025;  --hairline4:#2e3a2e;
  --panelline:#253025; --btnline:#253025;   --btnlineh:#2e3a2e;
  --acc:#d0aa72;    --brass:#d0aa72;   --accborder:#3a3327;
  --acc-wash:rgba(208,170,114,.12);
  --acc-wash2:rgba(208,170,114,.07);
  --acc-line:rgba(208,170,114,.75);
  /* accfaint/accdim were never redeclared for graphite, so the bare-:root
     OCEAN blues (line ~14) leaked in: the tree contract's active row and
     the cmd-K selection painted slate-blue. Brass, one step over --acc-wash. */
  --accfaint:rgba(208,170,114,.18); --accdim:rgba(208,170,114,.55);
  --wash06:rgba(208,170,114,.07);
  --off:#c98b6a;    --off-ring:#8a6a52;   --off-line:#6b4f3c;
  --green:#8fae74;  --green2:#a7c48c;     --wine:#c98b6a;   --sea:#a5afb5;
  --star-off:#1f261f;
  --bar:#253025;    --bar-w:#c8ccc4;      --bar-d:#4c5849;
  --eval-dark:#2b352b; --eval-light:#c8ccc4;
  --hl:#ffe14d;                         /* board highlight — stamped at build
                                          from generate_report HL_FILL       */
  --acc-hi:#e0bd8a;                    /* accent hover / pressed (00-palette) */
  --hl-line:rgba(255,225,77,.45);                /* the same wash at board opacity —
                                          stamped from HL_FILL + HL_OP       */
  --hover:rgba(228,232,222,.04);

  /* ---- type: Schibsted Grotesk for UI, Spline Sans Mono for every figure.
     Both faces are already embedded at the top of this file. Overriding
     --chrome is what retires system-ui everywhere, including .vg and the
     later ":root { --sans: var(--chrome) }" rule. ---- */
  --chrome:'Schibsted Grotesk', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --sans:var(--chrome);
  --mono:'Spline Sans Mono', ui-monospace, Menlo, monospace;

  /* ---- dense grid: the existing .vg tokens carry the whole redesign.
     20px rows, no zebra, one warm selection, hairlines that do not glow. ---- */
  --row-h:20px;
  --g-rowh:20px;  --g-px:7px;  --g-fs:11.5px;
  --g-hair:1px solid #181f18;
  --g-zebra:transparent;
  --g-hover:rgba(228,232,222,.04);
  --g-sel:rgba(208,170,114,.12);
  --g-selbar:inset 2px 0 0 #d0aa72;

  /* ---- motion: near zero. one 140ms move, nothing else animates. ---- */
  --mo-fast:70ms; --mo-move:140ms; --mo-enter:120ms; --mo-exit:80ms; --mo-bar:240ms;
}
:root[data-lab-theme="graphite"] body.dense,
:root[data-lab-theme="graphite"][data-dense="1"]{ --g-rowh:18px; }

/* ---- the frame ------------------------------------------------------- */
.pf{
  position:fixed; inset:0;
  display:grid; grid-template-rows:22px minmax(0,1fr) var(--drawer-h,200px) 20px;
  background:var(--paper); color:var(--ink);
  font-family:'Schibsted Grotesk',system-ui,-apple-system,sans-serif;
  overflow:hidden; user-select:none;
}

/* edge nav + hover overlay */

/* panel + section headers */

/* board area */

/* dense tables (drawer + collections) */
.pf-tbl{ overflow-y:auto; min-height:0; }
.pf-tbl .hd{ position:sticky; top:0; background:var(--paper);
  border-bottom:1px solid var(--hairline3); display:grid; }
.pf-tbl .hd > *{ font-family:var(--mono); font-size:8.5px; letter-spacing:.14em;
  text-transform:uppercase; color:var(--mut3); padding:0 8px; line-height:21px;
  white-space:nowrap; overflow:hidden; }
.pf-tbl .r{ display:grid; align-items:stretch; height:22px;
  border-bottom:1px solid var(--hairline); font-size:11.5px; color:var(--ink);
  cursor:default; }
.pf-tbl .r:hover{ background:var(--hover); }
.pf-tbl .r[aria-selected="true"]{ background:var(--acc-wash,rgba(208,170,114,.12));
  box-shadow:inset 2px 0 0 var(--acc); }
.pf-tbl .r > *{ padding:0 8px; line-height:22px; white-space:nowrap;
  overflow:hidden; text-overflow:ellipsis; }
.pf-tbl .n{ font-family:var(--mono); font-size:10.5px; color:var(--mut);
  font-variant-numeric:tabular-nums lining-nums; text-align:right; }
.pf-tbl .eco{ font-family:var(--mono); font-size:10.5px; color:var(--mut3); }
.pf-tbl .star{ text-align:center; font-size:10px; color:var(--star-off); }
.pf-tbl .star.on{ color:var(--acc); }

/* W/D/L bar */

/* drawer */

/* status bar */

/* ---- coverage ------------------------------------------------------- */
/* the board's own frame: a hairline just outside the squares */
/* one number, in the titlebar and the status bar */
.cov-chip{ display:flex; align-items:center; gap:7px; white-space:nowrap; }
.cov-chip .cov-dot{ width:5px; height:5px; border-radius:50%; background:currentColor; }
.cov-chip .cov-word{ font-weight:400; }
.cov-chip .cov-num{ font-style:normal; color:var(--mut);
  font-variant-numeric:tabular-nums; }
.cov-chip .cov-gaps{ font-style:normal; color:var(--off,#c98b6a);
  font-variant-numeric:tabular-nums; }
.cov-chip.cov-in,   .cov-chip.cov-edge{ color:var(--acc); }
.cov-chip.cov-off{ color:var(--off,#c98b6a); }

/* the line carries its history: an underline per ply */

/* move-level dots */
.cov-m-in, .cov-m-edge, .cov-m-gap, .cov-m-leak{ color:var(--acc); }
.cov-m-off{ color:var(--off,#c98b6a); }
.cov-m-rare{ color:var(--mut4,#39444a); }

/* the uncovered state offers the fix, not a warning */
.cov-add{ display:flex; align-items:center; gap:10px; height:24px; margin-bottom:7px;
  padding:0 9px; border:1px solid var(--accborder); background:var(--acc-wash2);
  font-family:var(--mono); font-size:10px; color:var(--acc); }
.cov-add em{ margin-left:auto; font-style:normal; color:var(--mut); }

/* drill prompt */
.cov-drill{ display:flex; align-items:center; gap:10px; height:26px; margin-top:8px;
  padding:0 10px; border:1px solid var(--accborder);
  background:rgba(208,170,114,.08); font-family:var(--mono); font-size:10.5px;
  color:var(--acc); }
.cov-drill em{ margin-left:auto; font-style:normal; color:var(--mut); }

/* ---- tree ------------------------------------------------------------ */

/* coverage footer under the tree */



/* every board is a 360-viewBox svg — one rule reaches #svBoard and .wb-bd
   alike. The ring is a keyline drawn INSET on the board's own edge
   (never clipped, adds no layout): `off` draws NOTHING — silence is the
   common case; solid brass = inside a line, half-weight = a line's end. */
[data-cov] svg[viewBox="0 0 360 360"]{ outline-offset:-2px; }
[data-cov="in"] svg[viewBox="0 0 360 360"]{ outline:2px solid var(--acc); }
[data-cov="edge"] svg[viewBox="0 0 360 360"]{
  outline:2px solid color-mix(in srgb, var(--acc) 52%, transparent); }
[data-cov="off"] svg[viewBox="0 0 360 360"]{ outline:none; }

/* the coverage pane's book list */
.cov-row{ display:grid; grid-template-columns:12px 52px 1fr 40px; gap:8px;
  align-items:center; height:21px; font-family:var(--mono); font-size:10.5px;
  color:var(--ink2); }
.cov-row.dim{ color:var(--mut); }
.cov-row .cov-m{ font-size:9px; line-height:1; text-align:center; }
.cov-row .cov-san{ color:var(--ink); }
.cov-row.dim .cov-san{ color:var(--mut); }
.cov-row .cov-n,
.cov-row .cov-pc{ text-align:right; color:var(--mut2);
  font-variant-numeric:tabular-nums; }

/* the chip in the command bar: a readout, so no hover and no cursor */
.wb-cmd-read{ display:flex; align-items:center; padding:0 10px;
  font-family:var(--mono); font-size:9.5px; cursor:default; }
.wb-cmd-read:empty{ display:none; }


/* skeleton: #wbMain > #wbStage[ #wbBoard  main#wbView ] + #wbDrawer.
   Heights come from --wb-drawer (04h-shell-kit owns the three states) —
   the board is the only elastic thing in the frame. */

:root{ --wb-drawer:208px; }


/* the stage */
#wbMain{ display:grid; grid-template-rows:minmax(0,1fr) auto; min-height:0; }
#wbStage{ display:grid; grid-template-columns:minmax(0,1fr); min-height:0; min-width:0; }
body.wb-stage #wbStage{ grid-template-columns:auto minmax(0,1fr); }
#wbStage > *{ min-width:0; min-height:0; }
#wbBoard{
  display:flex; align-items:center; justify-content:center;
  padding:11px 14px; background:var(--paper2);
  border-right:1px solid var(--hairline2);
}
#wbBoard[hidden]{ display:none; }
/* THE SVG BOX IS THE BOARD (2026-07-30). This used to pin the stage svg to
   `height:100%`, which letterboxes: a 360-viewBox svg in a box that is not
   square draws the board centred and leaves the rest of the element empty.
   Harmless while nothing was painted on the element's edge — and a bug the
   moment something is, because the board's edge and its coverage ring are
   both CSS on this element. Measured in the narrow-stage rooms (articles,
   elite, nihal): a 283 x 718 element around a 281px board, so the edge drew a
   tall rectangle with 219px of dead space above and below the board.

   `height:auto` makes an svg with a viewBox size itself off its own aspect
   ratio, so the element IS the board in every room and at every stage shape,
   and anything drawn on its edge lands on the board's edge. The host keeps
   its own rule below; it may be taller than the board, but nothing is painted
   on the host any more. */
#wbBoard .wb-bd{ height:min(100%, 780px); aspect-ratio:1; }
#wbBoard .wb-bd svg[viewBox="0 0 360 360"]{
  box-sizing:border-box; width:100%; height:auto; max-height:100%;
}
#wbBoard .wb-bd-meta{ padding-top:6px; }

/* the drawer */
#wbDrawer{
  height:var(--wb-drawer); display:grid; grid-template-rows:22px minmax(0,1fr);
  min-height:0; overflow:hidden; padding:0;
  border-top:1px solid var(--hairline3); background:var(--paper);
  /* padding:0 is load-bearing, not cosmetic: #wbDrawer is a <section>, and
     the content-era `section` padding rule (css/tokens-base.css) otherwise pads
     it 54.4px — and since a box can never be smaller than its own padding,
     the SHUT state measured 56px against the design's 22 at every width. */
}
#wbDrawer[hidden]{ display:none; }
#wbDrawer[data-state="0"] #wbDrawerBody{ display:none; }
#wbDrawerBar{
  display:flex; align-items:center; gap:14px; padding:0 12px; cursor:default;
  border-bottom:1px solid var(--hairline2);
  font-family:var(--mono); font-size:9px; letter-spacing:.16em;
  text-transform:uppercase; color:var(--mut2);
}
#wbDrawerTicks{ display:flex; align-items:center; gap:3px; }
#wbDrawerTicks i{ display:block; width:7px; height:2px; background:var(--hairline3); }
#wbDrawerTicks i.on{ background:var(--acc); }
#wbDrawerLbl{ display:flex; align-items:baseline; gap:12px; }
#wbDrawerLbl b{ font-weight:400; color:var(--ink2); }
#wbDrawerLbl em{ font-style:normal; color:var(--mut);
  font-variant-numeric:tabular-nums; }
#wbDrawerLbl .wb-dr-a{
  background:none; border:0; padding:0; font:inherit; letter-spacing:.04em;
  text-transform:none; color:var(--acc); cursor:default;
}
#wbDrawerSp{ flex:1; }
#wbDrawerHint{ letter-spacing:.04em; text-transform:none; color:var(--mut4,#39444a); }
#wbDrawerBody{ overflow-y:auto; min-height:0; }
.wb-drtbl .hd,
.wb-drtbl .r{
  grid-template-columns:24px minmax(0,340px) 42px minmax(0,340px) 42px 36px 44px 46px minmax(0,1fr);
}

/* answers where a pre-existing rule outranks the drop-in, in the theme's
   own scope — gated on the graphite attribute; later layer wins, no
   !important */

/* the status bar's block moved to door-frame.css with the doorframe
   (2026-08-10) — the strip is the one chrome row and that file owns it */

/* The drawer's height IS --wb-drawer — say so in the track. #wbMain sized its
   drawer row `auto`, and an auto track takes the item's content contribution,
   so the shut state measured 56px instead of the 22px header the design
   specifies (peek and full happened to agree because their content is taller
   than the declared height). With the track explicit, the drawer is exactly
   its declared state and the stage above takes the rest — which is what the
   frame claims: the board is the only elastic thing in it. */
:root[data-lab-theme="graphite"] #wbMain{
  grid-template-rows:minmax(0,1fr) var(--wb-drawer);
}
:root[data-lab-theme="graphite"] #wbMain:has(> #wbDrawer[hidden]){
  grid-template-rows:minmax(0,1fr) 0;
}

/* SHUT-DRAWER 56px — CLOSED 2026-07-28 (pm). The measured 56.375px was
   never the track and never the cascade: `section{padding:1.7rem 0}` padded
   the drawer 54.4px, and a border-box can never shrink below its own
   padding, so any 22px state rendered at 55.4px+. `#wbDrawer{padding:0}`
   above is the fix; verified 22.00 used at 924px and 1600px. */

/* page furniture leaves: the h1 STAYS as the room's name, the lede goes.
   Markup untouched — the template blocks keep <header class="hero">, so
   this is one gated layer to revert. */

/* the header becomes a row, not a block */
:root[data-lab-theme="graphite"] #wbView .hero{
  display:flex !important; align-items:center; gap:12px; flex-wrap:wrap;
  min-height:22px; padding:0 !important; margin:0 0 8px !important;
  border-bottom:1px solid var(--hairline2);
}
/* the wrapper div stops being a column so its children join the row */
:root[data-lab-theme="graphite"] #wbView .hero > div{ display:contents; }

/* the room's name: one line of chrome text, the size of a tab label */
:root[data-lab-theme="graphite"] #wbView .hero h1,
:root[data-lab-theme="graphite"] #wbView > .wrap > h1,
:root[data-lab-theme="graphite"] #wbView .wrap > h1{
  font-family:var(--chrome) !important; font-size:11.5px !important;
  font-weight:600 !important; letter-spacing:0 !important;
  line-height:22px !important; color:var(--ink) !important;
  margin:0 !important; white-space:nowrap;
}

/* prose is not room furniture */
:root[data-lab-theme="graphite"] #wbView .hero .eyebrow,
:root[data-lab-theme="graphite"] #wbView .hero .lede,
:root[data-lab-theme="graphite"] #wbView > .wrap > .lede,
:root[data-lab-theme="graphite"] #wbView .wrap > .lede,
:root[data-lab-theme="graphite"] #wbView #homeLede,
:root[data-lab-theme="graphite"] #wbView #exLede{ display:none !important; }

/* chips that were under the lede ride in the bar instead */
:root[data-lab-theme="graphite"] #wbView .hero .sv-chips{
  display:flex; align-items:center; gap:6px;
  margin:0 !important; margin-left:auto !important;
}

/* a room whose header only repeats its toolbar drops the header outright —
   and a door room's name is on the strip's chip, so its header is the room
   named twice (puzzles joined 2026-08-10 with the doorframe) */
:root[data-lab-theme="graphite"] #tab-database .hero,
:root[data-lab-theme="graphite"] #tab-nihal .hero,
:root[data-lab-theme="graphite"] #tab-puzzles .hero,
:root[data-lab-theme="graphite"] #tab-openings .hero{ display:none !important; }

/* (the .ot-actions verb-strip block died 2026-08-11: no module or markup
   has emitted .ot-actions / #exgOpen since the explorer landing was cut
   2026-08-01, and the openings page — its other tenant — is gone) */

/* rooms sit against the frame, not inside a page's gutter */
:root[data-lab-theme="graphite"] #wbView .wrap{
  max-width:none; padding:8px 14px 0 !important; margin:0;
}


/* a narrow window gets the SAME frame with one pane: the room over a shut
   drawer over the strip — nothing is dismantled. The doorframe rules here
   (2026-08-10): no header row, no nav column; the strip carries the chip
   and the way home, and ☰ (#sideTgl, body.sideopen) summons the same map
   sheet the home strip's "everything" opens (door-frame.css). */
@media (max-width:1000px){
  :root[data-lab-theme="graphite"] #wb{
    position:fixed; inset:0; display:grid;
    grid-template-rows:minmax(0,1fr) 26px; height:auto;   /* room · strip */
  }
  :root[data-lab-theme="graphite"] #wbBody{
    /* nav-grid pins #wbMain to column 2 at every width — the map column
       track stays declared and empty (0px), or the room lands in an
       implicit auto track and renders 0 wide (found on the 375px landing) */
    display:grid; grid-template-columns:0 minmax(0,1fr); min-height:0;
  }
  :root[data-lab-theme="graphite"] #wbRail,
  :root[data-lab-theme="graphite"] .wb-grip{ display:none; }
  /* the map column renders only as the summoned sheet (door-frame.css owns
     body.dv-map / body.sideopen); at rest it does not exist */
  :root[data-lab-theme="graphite"] body:not(.dv-map):not(.sideopen) #wbLeft{ display:none; }
  /* board over view, not beside it */
  :root[data-lab-theme="graphite"] #wbStage,
  :root[data-lab-theme="graphite"] body.wb-stage #wbStage{
    grid-template-columns:minmax(0,1fr); grid-template-rows:auto minmax(0,1fr);
  }
  /* the NO-BOARD rooms (home, database): the two-row template above parks
     the view in the auto row — sized to min-content — and leaves the 1fr
     row empty under it. One row; the view IS the stage. (2026-08-10,
     found by the landing, latent for the database.) */
  :root[data-lab-theme="graphite"] body:not(.wb-stage) #wbStage{
    grid-template-rows:minmax(0,1fr);
  }
  :root[data-lab-theme="graphite"] #wbBoard{
    border-right:0; border-bottom:1px solid var(--hairline2); padding:8px;
  }
  :root[data-lab-theme="graphite"] #wbBoard .wb-bd{ height:min(46vh,420px); }
  /* the drawer shuts itself out of the way rather than eating the board —
     by VAR, so the declared state and the used height can never disagree
     (the stored state is untouched; widening the window brings it back) */
  :root[data-lab-theme="graphite"]{ --wb-drawer:22px !important; }
  :root[data-lab-theme="graphite"] #wbDrawer #wbDrawerBody{ display:none; }
  :root[data-lab-theme="graphite"] #wbMain{ grid-template-rows:minmax(0,1fr) 22px; }
}
/* the rooms use TWO header classes for one job (.hero and .pos-head) — both
   get the identical 22px row. .primary is flattened globally; .go must
   not re-fill it. */

:root[data-lab-theme="graphite"] #wbView .pos-head{
  display:flex !important; align-items:center; gap:12px; flex-wrap:wrap;
  min-height:22px; padding:0 !important; margin:0 0 8px !important;
  border-bottom:1px solid var(--hairline2); background:none !important;
}
:root[data-lab-theme="graphite"] #wbView .pos-head.col{ flex-direction:row !important; }
:root[data-lab-theme="graphite"] #wbView .pos-head > div{ display:contents; }
:root[data-lab-theme="graphite"] #wbView .pos-head h1,
:root[data-lab-theme="graphite"] #wbView .pos-head #homeHello{
  font-family:var(--chrome) !important; font-size:11.5px !important;
  font-weight:600 !important; letter-spacing:0 !important;
  line-height:22px !important; color:var(--ink) !important;
  margin:0 !important; white-space:nowrap;
}
/* an eyebrow over a room name is the room named twice */
:root[data-lab-theme="graphite"] #wbView .eyebrow{ display:none !important; }
/* 5a: "75 words of lede" LEAVE — a room does not explain itself in a
   paragraph. The .hero rule above missed the second header class; the
   lede-more "about ↗" affordance stays, it is a control. */
:root[data-lab-theme="graphite"] #wbView .pos-head .lede{ display:none !important; }

/* ---- the register: a frame has no cards ----------------------------
   Rounded containers on a flat ground are the last page tell. The
   register keeps its grid and its numbers; it loses the card. */
:root[data-lab-theme="graphite"] #wbView .home-card{
  border-radius:0 !important; background:none !important;
  border:1px solid var(--hairline2) !important;
}
:root[data-lab-theme="graphite"] #wbView .home-card.home-hero{
  border-radius:0 !important;
}

/* ---- the register's action: the one accent, not a pill ---- */
:root[data-lab-theme="graphite"] #wbView .home-cta .primary,
:root[data-lab-theme="graphite"] #wbView .home-cta .primary.go,
:root[data-lab-theme="graphite"] #wbView .primary.go{
  background:none !important; color:var(--acc) !important;
  border:1px solid var(--accdim) !important; border-radius:0 !important;
  font-family:var(--mono) !important; font-size:11px !important;
  font-weight:400 !important; letter-spacing:.03em !important;
  padding:4px 10px !important; box-shadow:none !important;
  text-transform:none !important;
}
:root[data-lab-theme="graphite"] #wbView .primary.go:hover{
  background:var(--acc-wash,rgba(208,170,114,.12)) !important; color:var(--ink) !important;
}

/* the overlay leaves the flow only because #wbBody's three columns are
   placed EXPLICITLY — under auto-placement, removing #wbLeft from flow
   slides #wbMain into the 26px track (measured: room 1574px → 30px) */
:root[data-lab-theme="graphite"] body.wb-lean #wbLeft{ grid-column:1; grid-row:1; }
:root[data-lab-theme="graphite"] body.wb-lean #wbMain{ grid-column:2; grid-row:1; }
:root[data-lab-theme="graphite"] body.wb-lean #wbRail{ grid-column:3; grid-row:1; }
:root[data-lab-theme="graphite"] body.wb-lean.wb-norail #wbMain{ grid-column:2; }


/* the LANDING is gated on body.hroom-on. (The room bar #hrBar retired with
   the doorframe, 2026-08-10 — the strip's chip is the way home now; see
   door-frame.css.) The old #tab-home markup is HIDDEN, never deleted —
   hdBuild still writes into it and ⌘K still reads the nav it mirrors. */

/* ---- THE LANDING IS A RANK OF THE BOARD (owner call, 2026-08-10) ----
   Three squares — a dark, b light, c dark — meeting edge to edge with NO
   hairlines, because adjacent squares of a board touch. Each square is
   wholly a door; hover inverts it to its opposite colour and its piece
   changes sides, the way a square reads mid-move. The palette is the
   landing's OWN (tournament-vinyl green and buff, a clock-flag red for the
   one live fact) — deliberately not the frame's graphite: the landing is
   the cover, not a page. Tokens are --hl-* / --sq-* so nothing shadows the
   site's --ink family. Fonts ride the inlined faces with per-use fallbacks
   (the body-class-gate law: a theme token used bare can paint black). */

body.hroom-on #wbView{ overflow:hidden; padding:0 !important;
  scrollbar-gutter:auto; border-right:0; }
body.hroom-on #tab-home{ display:flex; height:100%; min-height:0; }
/* the page the landing replaces stays in the DOM — hdBuild writes it and
   the map reads the same nav — it simply is not the room any more */
body.hroom-on #tab-home > *:not(#hrLand){ display:none; }

#hrLand{
  --hl-dk: #24382d;
  --hl-dk-ink: #efe9d6;
  --hl-dk-mut: #a9b8a6;
  --hl-dk-flag: #e0906c;
  --hl-lt: #e9e1cc;
  --hl-lt-ink: #24342b;
  --hl-lt-mut: #5d6b5f;
  --hl-lt-flag: #a8402c;
  flex:1; min-width:0; min-height:0;
  display:grid; grid-template-columns:repeat(3, minmax(0,1fr));
}

/* the square: one element, wholly a door. container-type:size so the type
   and the piece scale to the square itself, not the viewport. */
.hl-sq{
  position:relative; overflow:hidden; container-type:size;
  display:block; text-decoration:none; cursor:pointer;
  background:var(--sq); color:var(--sq-ink);
  transition:background-color .18s ease, color .18s ease;
}
.hl-sq.hl-dk{ --sq:var(--hl-dk); --sq-ink:var(--hl-dk-ink);
  --sq-mut:var(--hl-dk-mut); --sq-flag:var(--hl-dk-flag); }
.hl-sq.hl-lt{ --sq:var(--hl-lt); --sq-ink:var(--hl-lt-ink);
  --sq-mut:var(--hl-lt-mut); --sq-flag:var(--hl-lt-flag); }
/* hover inverts THE RANK, not one square — a lone flip would leave two
   adjacent squares the same colour, which a board never allows. Every
   piece changes sides with its ground (legibility follows the square);
   the cursor and the focus ring say which door is armed. :has() is the
   gate — a browser without it keeps the static rank, fully usable. */
#hrLand:has(.hl-sq:is(:hover, :focus-visible)) .hl-sq.hl-dk{
  --sq:var(--hl-lt); --sq-ink:var(--hl-lt-ink);
  --sq-mut:var(--hl-lt-mut); --sq-flag:var(--hl-lt-flag); }
#hrLand:has(.hl-sq:is(:hover, :focus-visible)) .hl-sq.hl-lt{
  --sq:var(--hl-dk); --sq-ink:var(--hl-dk-ink);
  --sq-mut:var(--hl-dk-mut); --sq-flag:var(--hl-dk-flag); }
.hl-sq:focus-visible{ outline:3px solid var(--sq-ink); outline-offset:-8px; }

/* the plate: word, offer, fact — left-set like a book plate, never centred.
   It carries its own ink: the anchor's inherited colour is link-rule
   territory (the page-era `#wbView a` rules ride an id and win). */
.hl-plate{
  position:absolute; left:9cqi; right:6cqi; top:11cqh;
  display:flex; flex-direction:column; align-items:flex-start;
  color:var(--sq-ink); transition:color .18s ease;
}
.hl-word{
  font-family:var(--serif, 'Libre Caslon Text', Georgia, serif);
  font-weight:400; font-size:clamp(24px, 11.2cqi, 54px);
  letter-spacing:.12em; text-transform:uppercase; line-height:1.04;
  white-space:nowrap;
}
.hl-line{
  margin-top:1.1em; max-width:30ch;
  font-family:var(--serif, 'Libre Caslon Text', Georgia, serif);
  font-style:italic; font-size:clamp(13px, 3.3cqi, 15.5px);
  line-height:1.5; color:var(--sq-mut);
  transition:color .18s ease;
}
.hl-fact{
  margin-top:2em;
  font-family:var(--mono, 'Spline Sans Mono', Menlo, monospace);
  font-size:clamp(10.5px, 2.5cqi, 12px); letter-spacing:.14em;
  text-transform:uppercase; color:var(--sq-flag);
  font-variant-numeric:tabular-nums lining-nums;
  transition:color .18s ease;
}

/* the piece: monumental, anchored past the floor like a demo-board piece
   being set down. Both sides are painted; the square's state picks one. */
.hl-pc{
  position:absolute; right:-7cqi; bottom:-16cqh;
  width:min(74cqi, 72cqh); height:auto; aspect-ratio:1;
  pointer-events:none;
}
/* each glyph carries its mass differently in the 45-box: the queen is all
   crown up top, so an even crop leaves her as spikes — she alone rises
   higher and slimmer, showing head and crown */
.hl-sq:nth-child(2) .hl-pc{ width:min(56cqi, 58cqh); bottom:-6cqh; right:22cqi; }
.hl-pc use{ transition:opacity .22s ease; }
.hl-sq .pc-b{ opacity:0; }
#hrLand:has(.hl-sq:is(:hover, :focus-visible)) .pc-a{ opacity:0; }
#hrLand:has(.hl-sq:is(:hover, :focus-visible)) .pc-b{ opacity:1; }

/* the coordinate: the file letter in the square's own corner, set exactly
   like the board sets its own — quiet, mono, one per square */
.hl-file{
  position:absolute; left:13px; bottom:9px;
  font-family:var(--mono, 'Spline Sans Mono', Menlo, monospace);
  font-size:11px; color:var(--sq-mut); transition:color .18s ease;
}

/* one orchestrated arrival: the pieces rise into their squares, the plates
   follow — once, briefly, and never for reduced-motion */
@media (prefers-reduced-motion: no-preference){
  .hl-pc{ animation:hl-rise .7s cubic-bezier(.22,.9,.3,1) backwards; }
  .hl-plate, .hl-file{ animation:hl-fade .55s ease backwards; }
  .hl-sq:nth-child(1) .hl-pc{ animation-delay:.05s; }
  .hl-sq:nth-child(2) .hl-pc{ animation-delay:.13s; }
  .hl-sq:nth-child(3) .hl-pc{ animation-delay:.21s; }
  .hl-sq:nth-child(1) .hl-plate{ animation-delay:.12s; }
  .hl-sq:nth-child(2) .hl-plate{ animation-delay:.20s; }
  .hl-sq:nth-child(3) .hl-plate{ animation-delay:.28s; }
  .hl-sq .hl-file{ animation-delay:.34s; }
}
@keyframes hl-rise{ from{ transform:translateY(7cqh); opacity:0; } }
@keyframes hl-fade{ from{ opacity:0; } }

/* narrow: the rank turns on its side — three full-width squares stacked,
   the piece cropped by the right edge, the plate vertically centred */
@media (max-width:860px){
  #hrLand{ grid-template-columns:1fr;
    grid-auto-rows:minmax(170px, 1fr); overflow-y:auto; }
  .hl-sq{ display:flex; align-items:center; }
  .hl-plate{ position:static; padding:22px 20px; flex:1; min-width:0; }
  .hl-word{ font-size:clamp(24px, 6.4cqi, 44px); }
  .hl-line{ margin-top:.7em; }
  .hl-fact{ margin-top:1.1em; }
  .hl-pc{ right:-4cqi; bottom:-24cqh; width:min(34cqi, 150cqh); }
  /* the queen's centred-in-her-square placement is a portrait-square fact;
     in a stacked row she takes the same right-edge crop as the others */
  .hl-sq:nth-child(2) .hl-pc{ right:-4cqi; bottom:-24cqh; width:min(34cqi, 150cqh); }
}

/* THE BOARD NEVER EATS THE ROOM (2026-07-28).
   body.wb-stage sizes the board track `auto`. Once the board went
   full-height (the 4A refinement) its aspect ratio made that track ~1100px,
   and in the list rooms that do not declare their own column — nihal,
   database, elite, articles — the list was left 143px. Measured: nihal stage
   "1100.52px 143.484px". The reference for those rooms is the opposite: the
   LIST is the room and the board is furniture beside it. Cap the board
   column and guarantee the list a workable minimum.

   A ROOM THAT DECLARES ITS OWN COLUMN MUST JOIN THIS :not() CHAIN BY NAME
   (2026-07-29, learned from the explorer). This note used to claim such
   rooms "are more specific and win" — they are not and they do not: this
   selector carries an id, an attribute, three classes and outranks a plain
   `body.<room> #wbStage` from ANY stylesheet, source order be damned. The
   explorer declared 236px, was never added to the chain, and therefore
   never got it: measured 504px at 1096 wide, which is exactly min(46vw,
   760px) — the board's cap, handed to the POSITION column because exroom
   also flips `#wbView{order:1}`. Invisible for a release because a fat
   column reads as a design choice. Every room here is excluded by NAME.
   (.hroom-on stays in the chain although home now has no stage at all —
   the term is inert for home and load-bearing for the selector's weight;
   .labone joined it 2026-08-18 when the openings study room left the
   stage for the solve page — same reasoning, kept for the weight.) */
:root[data-lab-theme="graphite"] body.wb-stage:not(.labone):not(.hroom-on):not(.exroom) #wbStage{
  grid-template-columns:minmax(0,min(46vw,760px)) minmax(420px,1fr);
}
/* the marks are children of the board's own <svg> (viewBox 0 0 360 360) so
   they scale with it; nothing here draws a board. Gated on body.cov-
   board (28-cov-board.js): removing the class reverts the whole screen. */

/* ---- the two columns the screen adds to the frame -----------------
   #cbPanel (the squares, in words) and #cbRail (the line and how deep the
   book runs) are children of #wbBody. solve-session.css collapses
   #wbBody to ONE column on any board session (body.svpage), and it is the
   later stylesheet, so the placement has to answer it in the theme's own
   scope rather than hope to out-order it. */
:root[data-lab-theme="graphite"] body.cov-board.svpage #wbBody{
  grid-template-columns:430px minmax(0,1fr) 330px;
}
body.cov-board.svpage #cbPanel{ grid-column:1; grid-row:1; }
body.cov-board.svpage #wbMain{ grid-column:2; grid-row:1; }
body.cov-board.svpage #cbRail{ grid-column:3; grid-row:1; }
#cbPanel:empty, #cbRail:empty{ display:none; }
body:not(.cov-board) #cbPanel, body:not(.cov-board) #cbRail{ display:none; }
body.cov-board.svpage #cbPanel{
  overflow:auto; min-height:0; padding:12px 14px 0 12px;
  background:var(--paper2); border-right:1px solid var(--hairline2);
}
body.cov-board.svpage #cbRail{
  display:flex; flex-direction:column; min-height:0; overflow:hidden;
  padding:0 14px 0 12px;
  background:var(--paper2); border-left:1px solid var(--hairline2);
}
/* the room between them is the board and nothing else: the explorer's side
   card is a second, contradicting answer to the same question */
body.cov-board.svpage #tab-solve .solve-side{ display:none; }
body.cov-board.svpage #tab-solve .solve-grid{
  grid-template-columns:minmax(0,1fr) !important; max-width:none; padding:0 14px;
}
body.cov-board.svpage #tab-solve .sv-card{ width:auto; }
body.cov-board.svpage #wbMain{ min-width:0; overflow:hidden; }
body.cov-board.svpage #wbView{ overflow:auto; }
/* the frame does not scroll: body.svpage hands the document its own height
   (height:auto/overflow:visible), which puts a scrollbar on the page and takes
   34px off the columns the three-column screen is measured for — the rail is
   the piece that falls off the edge. The board is sized to the pane, so there
   is nothing to scroll to. */
body.cov-board.svpage{ height:100%; overflow:hidden; }
body.cov-board.svpage #tab-solve .solve-top{ padding-left:14px; }
body.cov-board.svpage #tab-solve #svBoard svg{
  width:var(--bd); max-width:100%; max-height:calc(100dvh - 162px); margin:0 auto;
}

/* ---- the squares -------------------------------------------------
   v2 (2026-07-29): one rule — YOUR move is the only paint on the board;
   holes are dashed hollows; the only words are one share pill per hole.
     cb-in   yours — luminous brass wash, solid 2.5px edge, solid rounded
             connector, no label (solid brass IS the label)
     cb-gap  theirs, ≥5%, unanswered — hollow, dashed terracotta edge +
             faint dashed connector, one dark share pill ("37%")
     cb-off  played, not yours — hollow dotted grey, pill only, quietest
   Dashed means missing everywhere: the off-book ring speaks the same way. */
/* the vocabulary's palette belongs to the component, not the theme: under
   ocean/scoresheet the graphite globals do not exist and every var() fell
   to SVG-black (the 2026-07-29 ocean covered board — black squares, black
   words). Chrome forks with the theme; the answer's colours may not. */
.cb-marks, .cb-labels, #cbPanel, #cbRail{
  --cv-acc:#d0aa72; --cv-acc-hi:#e0bd8a; --cv-hl:#f4dda6; --cv-off:#c98b6a;
  --cv-mut3:#4a555c; --cv-mut4:#39444a; --cv-bar:#232b31; --cv-accborder:#3a3327;
  --cv-accwash:rgba(208,170,114,.12); --cv-accwash2:rgba(208,170,114,.07);
  --cv-halo:#0b0e10;
}
.cb-marks, .cb-labels{ pointer-events:none; }
.cb-marks .cb-cold{ fill:var(--mut2, #727169); opacity:.3; }
.cb-marks .cb-cn{ stroke-linecap:round; }
.cb-labels .cb-hit{ fill:transparent; pointer-events:all; cursor:pointer; }
.cb-labels .cb-pcbg{ fill:var(--cv-halo); opacity:.76; }
.cb-labels text{
  text-anchor:middle; font-family:var(--mono);
  font-variant-numeric:tabular-nums; font-size:8.5px;
}
/* yours — the one solid answer on the board, and the only brass */
.cb-marks .cb-in .cb-cn{ stroke:var(--cv-acc); stroke-width:3; opacity:.9; }
.cb-marks .cb-in .cb-sq{ fill:color-mix(in srgb, var(--cv-acc) 44%, transparent);
  stroke:var(--cv-acc); stroke-width:3; }
/* theirs, unanswered — a hollow the dashes admit to */
.cb-marks .cb-gap .cb-cn{ stroke:var(--cv-off); stroke-width:2; stroke-dasharray:5 4; opacity:.7; }
.cb-marks .cb-gap .cb-sq{ fill:none; stroke:var(--cv-off); stroke-width:2.25; stroke-dasharray:5 4; }
.cb-labels .cb-gap .cb-pc{ fill:#f0c8ad; }
/* played, not yours — barely there on purpose */
.cb-marks .cb-off .cb-sq{ fill:none; stroke:var(--cv-mut3); stroke-width:1.5; stroke-dasharray:1.5 3.5; }
.cb-labels .cb-off .cb-pc{ fill:#b9c2c6; }

/* ---- the panel: the same four moves, in words --------------------- */
#cbPanel .cb-card{
  border-left:2px solid var(--cv-acc); background:var(--surface);
  border-top:1px solid var(--hairline3); border-right:1px solid var(--hairline3);
  border-bottom:1px solid var(--hairline3);
}
#cbPanel .cb-card.cov-off{ border-left-color:var(--cv-off); }
#cbPanel .cb-card.cov-edge{ border-left-color:var(--mut2); }
#cbPanel .cb-h{
  display:flex; align-items:center; gap:10px; height:30px; padding:0 11px 0 12px;
}
#cbPanel .cb-h-g{
  flex:none; background:none; border:0; padding:0; line-height:1;
  font-size:13px; color:var(--cv-acc); cursor:pointer;
}
#cbPanel .cb-h h2{
  flex:1; margin:0; font-family:var(--mono); font-size:11.5px; font-weight:400;
  letter-spacing:.18em; text-transform:uppercase; color:var(--cv-acc);
}
#cbPanel .cb-card.cov-off .cb-h h2{ color:var(--cv-off); }
#cbPanel .cb-card.cov-edge .cb-h h2{ color:var(--ink2); }
#cbPanel .cb-num{
  font-family:var(--mono); font-size:11.5px; font-weight:400; color:var(--cv-acc);
  font-variant-numeric:tabular-nums;
}
#cbPanel .cb-card.cov-off .cb-num{ color:var(--cv-off); }
#cbPanel .cb-lede{
  margin:0; padding:0 12px 11px; font-size:11.5px; line-height:1.4; color:var(--ink2);
}
#cbPanel .cb-sec{
  display:flex; align-items:center; height:20px; padding:0 12px;
  border-top:1px solid var(--hairline2); border-bottom:1px solid var(--hairline2);
  background:var(--cv-halo);
  font-family:var(--mono); font-size:9px; letter-spacing:.2em;
  text-transform:uppercase; color:var(--mut2);
}
#cbPanel .cb-sec em{ margin-left:auto; font-style:normal; color:var(--cv-mut3); }
/* the two headings are the two answers, so they carry the two colours */
#cbPanel .cb-sec.mine span{ color:var(--cv-acc); }
#cbPanel .cb-sec.theirs span{ color:var(--cv-off); }
#cbPanel .cb-row{
  display:flex; align-items:center; gap:9px; width:100%; height:20px;
  padding:0 12px; background:none; border:0; border-radius:0; cursor:pointer;
  border-bottom:1px solid var(--hairline2);
  font-family:var(--mono); font-size:11px; color:var(--ink2); text-align:left;
}
#cbPanel .cb-row:hover{ background:var(--cv-accwash); color:var(--ink); }
#cbPanel .cb-mk{ flex:none; width:11px; height:11px; box-sizing:border-box; }
#cbPanel .cb-row.cb-in .cb-mk{ background:var(--cv-acc); }
#cbPanel .cb-row.cb-gap .cb-mk{ border:1px dashed var(--cv-off); }
#cbPanel .cb-row.cb-off .cb-mk{ border:1px dotted var(--cv-mut3); }
#cbPanel .cb-san{ flex:0 0 62px; font-weight:400; color:var(--ink); }
#cbPanel .cb-row.cb-in .cb-san{ color:var(--cv-acc); }
#cbPanel .cb-n{
  flex:0 0 58px; text-align:right; font-size:10px; color:var(--mut);
  font-variant-numeric:tabular-nums;
}
#cbPanel .cb-bar{ flex:1; height:3px; background:var(--cv-bar); }
#cbPanel .cb-bar i{ display:block; height:100%; background:var(--cv-mut3); }
#cbPanel .cb-row.cb-in .cb-bar i{ background:var(--cv-acc); }
#cbPanel .cb-row.cb-gap .cb-bar i{ background:var(--cv-off); }
#cbPanel .cb-p{
  flex:0 0 38px; text-align:right; font-style:normal; font-size:10px;
  color:var(--ink2); font-variant-numeric:tabular-nums;
}
#cbPanel .cb-row.cb-in .cb-p{ color:var(--cv-acc); }
#cbPanel .cb-empty{ margin:0; padding:9px 11px; font-size:11px; color:var(--mut2); }
#cbPanel .cov-add{ margin:0; }

/* ---- the rail: the line, and how deep the book runs --------------- */
#cbRail .cb-read{
  flex:none; display:flex; align-items:center; gap:10px; height:26px;
  margin:10px 12px 12px; padding:0 10px;
  border:1px solid var(--hairline3); background:var(--surface);
  font-size:11.5px; color:var(--ink2);
}
#cbRail .cb-read-r{
  display:flex; align-items:center; gap:10px; margin-left:auto;
  font-family:var(--mono); font-size:10px; color:var(--mut2);
}
#cbRail .cb-read-r b{ font-weight:400; color:var(--ink); font-variant-numeric:tabular-nums; }
#cbRail .cb-rh{
  flex:none; padding:0 12px 6px;
  font-family:var(--mono); font-size:9px; letter-spacing:.2em;
  text-transform:uppercase; color:var(--mut2);
}
#cbRail .cb-line{ flex:0 1 auto; overflow:auto; min-height:0; padding:0 12px; }
#cbRail .cb-r{
  display:grid; grid-template-columns:26px minmax(0,1fr) minmax(0,1fr);
  align-items:center; height:20px;
  font-family:var(--mono); font-size:11px; color:var(--ink2);
}
#cbRail .cb-r i{ font-style:normal; color:var(--cv-mut3); font-variant-numeric:tabular-nums; }
#cbRail .cb-c{
  display:flex; align-items:center; gap:7px; height:18px; padding:0 6px;
  cursor:pointer;
}
#cbRail .cb-c::before{ content:""; flex:none; width:8px; height:8px; box-sizing:border-box; }
#cbRail .cb-c.cb-g-in::before{ background:var(--cv-acc); border-radius:2px; }
#cbRail .cb-c.cb-g-edge::before{ border:1.5px dashed var(--cv-off); border-radius:2px; }
#cbRail .cb-c.cb-g-off::before{ border:1.5px dotted var(--cv-mut3); border-radius:2px; }
#cbRail .cb-c.cb-g-edge{ color:var(--cv-off); }
#cbRail .cb-c.cb-g-off{ color:var(--mut); }
#cbRail .cb-c.cur{ background:var(--cv-accwash); color:var(--cv-acc); }
#cbRail .cb-c:hover{ background:var(--cv-accwash2); }
#cbRail .cb-c-e{ cursor:default; }
#cbRail .cb-line-e{ padding:4px 0; font-size:11px; color:var(--mut2); }
#cbRail .cb-sp{ flex:1 1 auto; min-height:8px; }
#cbRail .cb-depth{ flex:none; padding:10px 12px 12px; border-top:1px solid var(--hairline2); }
#cbRail .cb-depth .top{
  display:flex; align-items:baseline; gap:10px; margin-bottom:7px;
  font-family:var(--mono); font-size:9px; letter-spacing:.2em;
  text-transform:uppercase; color:var(--mut2);
}
#cbRail .cb-depth .top b{
  margin-left:auto; font-weight:400; font-size:11px; letter-spacing:0;
  text-transform:none; color:var(--ink); font-variant-numeric:tabular-nums;
}
#cbRail .cb-ribbon{ display:flex; align-items:flex-end; gap:2px; height:17px; }
#cbRail .cb-ribbon i{ display:block; flex:1 1 0; height:15px; background:var(--cv-mut4); }
#cbRail .cb-ribbon i.on{ background:var(--cv-acc); }
#cbRail .cb-ribbon i.cur{ background:var(--cv-hl); height:17px; }
#cbRail .cb-ribbon i.ahead{ background:var(--cv-accborder); }
#cbRail .cb-ribbon i.off{ background:var(--cv-off); opacity:.75; }
#cbRail .cb-ends{
  display:flex; justify-content:space-between; margin-top:4px;
  font-family:var(--mono); font-size:9px; color:var(--cv-mut3);
}
#cbRail .cb-leg{ list-style:none; margin:12px 0 0; padding:0; }
#cbRail .cb-leg li{
  display:flex; align-items:center; gap:8px; height:17px;
  font-family:var(--mono); font-size:9.5px; color:var(--mut2);
}
#cbRail .cb-leg li::before{ content:""; flex:none; width:8px; height:8px; box-sizing:border-box; }
#cbRail .cb-leg li.cb-g-in::before{ background:var(--cv-acc); }
#cbRail .cb-leg li.cb-g-edge::before{ border:1px dashed var(--cv-off); }
#cbRail .cb-leg li.cb-g-off::before{ border:1px dotted var(--cv-mut3); }

/* narrow: the frame keeps one pane, so the two added columns stand down and
   the squares carry the whole answer by themselves.
   The #wbMain un-pin MUST carry the theme scope: nav-grid pins #wbMain to
   grid-column 2 at :root[theme] body.wb-lean strength, and the unscoped
   rule that lived here lost to it — the session sat in an IMPLICIT auto
   track (649px) beside an empty 1fr gutter (631px), board clipped at the
   right edge (found 2026-08-11 at exactly 1280w, the media's own
   boundary). Match the scope you answer. */
@media (max-width:1280px){
  :root[data-lab-theme="graphite"] body.cov-board.svpage #wbBody{
    grid-template-columns:minmax(0,1fr);
  }
  body.cov-board.svpage #cbPanel, body.cov-board.svpage #cbRail{ display:none; }
  :root[data-lab-theme="graphite"] body.cov-board.svpage #wbMain{ grid-column:1; }
  /* one column means the wide screen's edge-to-edge grid (line ~31) has
     nothing to butt against — shrink the card to content and centre it */
  :root[data-lab-theme="graphite"] body.cov-board.svpage #tab-solve .solve-grid{
    justify-items:center;
  }
}

/* COVERED — the board overflow fix found by measuring the render (2026-07-28).
   The board overflowed its column — measured 778px of svg in a 736px track,
   so the left files sat at x=-35, off screen, taking their overlays with
   them. Cap the board to the column it is given. (The label-fill half of
   that note went with the old .cb-ovl classes: the marks now carry their
   own family colours from the mock, tokens only, no strays.) */
:root[data-lab-theme="graphite"] #wbBoard .wb-bd{ max-width:100%; overflow:hidden; }
:root[data-lab-theme="graphite"] #wbBoard .wb-bd svg{ max-width:100%; }


/* ---- the corpus rows the explorer renders into #cbArch (2026-08-11) ----
   13c-exgames.js writes .corp-row into this panel, so the rows arrive from
   the explorer but they LIVE here — a covered board is this file's surface.
   (Their old home, explorer-archive-rows.css, was folded away with the four
   other explorer shards; its .ex-arch half went with the explorer room and
   had no emitter left.) */
.cb-arch:empty{ display:none; }
.cb-arch .cb-sec.corp{ display:flex; align-items:center; gap:8px;
  height:20px; padding:0 12px; font-family:var(--mono); font-size:9.5px;
  letter-spacing:.14em; text-transform:uppercase; color:var(--mut, #5d686e); }
.cb-arch .cb-sec.corp em{ margin-left:auto; font-style:normal;
  letter-spacing:0; text-transform:none; color:var(--ink2, #aeb7bc); }
.corp-row{ display:flex; align-items:center; gap:9px; width:100%; height:20px;
  padding:0 12px; background:none; border:0; font:inherit; cursor:pointer;
  font-family:var(--mono); font-size:10px; color:var(--ink2, #aeb7bc); text-align:left; }
.corp-row:hover{ background:var(--hover, rgba(223,228,230,.05)); color:var(--ink, #dfe4e6); }
.corp-row .corp-p{ flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.corp-row em{ flex:none; font-style:normal; color:var(--mut2, #727169);
  font-variant-numeric:tabular-nums; }
/* a hidden drawer pane frees its track — the frame keeps no furniture for a
   room that declined it (database, solve). The graphite #wbMain track is
   var(--wb-drawer), so a HIDDEN drawer still reserved its 208px and clipped
   the board on solve (measured: view cut at 852px, board bottom 994) */
:root[data-lab-theme="graphite"] #wbMain:has(#wbDrawer[hidden]){
  grid-template-rows:minmax(0,1fr) 0px;
}

/* the palette contract: nothing in the frame larger than 11.5px except a
   board or a chart; figures mono and tabular; verbs, not pills.
   Articles' Caslon and the register's serif numerals are content, not
   frame. Type and colour only, no geometry — reverting is deleting it. */
/* ---- sync: the form's buttons take the same face ---- */
:root[data-lab-theme="graphite"] #wbView #tab-sync button{
  font-family:var(--mono); font-size:10px; padding:2px 8px;
  border-radius:0; box-shadow:none; min-height:0;
}
:root[data-lab-theme="graphite"] #wbView #tab-sync button:not(.primary){
  background:none; color:var(--ink2); border:1px solid var(--btnline);
}
:root[data-lab-theme="graphite"] #wbView #tab-sync button.primary,
:root[data-lab-theme="graphite"] #wbView #tab-sync button[type="submit"]{
  background:none !important; color:var(--acc) !important;
  border:1px solid var(--accborder) !important;
}
/* ---- profile: the register numerals stay; the pills do not ---- */
:root[data-lab-theme="graphite"] #wbView #tab-profile :is(.cs-auth-go,.pf-btn){
  font-family:var(--mono); font-size:10px; padding:2px 8px;
  background:none !important; color:var(--ink2) !important;
  border:1px solid var(--btnline) !important; border-radius:0 !important;
  box-shadow:none !important; min-height:0;
}
:root[data-lab-theme="graphite"] #wbView #tab-profile :is(.cs-auth-go,.pf-btn.acc){
  color:var(--acc) !important; border-color:var(--accborder) !important;
}
:root[data-lab-theme="graphite"] #wbView #tab-profile .pf-step{
  font-size:12px; font-family:var(--mono);
}
:root[data-lab-theme="graphite"] #wbView #tab-profile .pf-cardsub{ font-size:10px; }
/* ---- account: the auth room joins the program it signs you into ---- */
:root[data-lab-theme="graphite"] #wbView #tab-account h1{
  font-family:var(--chrome); font-size:11.5px; font-weight:600;
  letter-spacing:0; color:var(--ink);
}
:root[data-lab-theme="graphite"] #wbView #tab-account .ac-mark{ font-size:12px; }
:root[data-lab-theme="graphite"] #wbView #tab-account :is(.ac-lede,.ac-fine){
  font-size:11.5px; color:var(--mut);
}
:root[data-lab-theme="graphite"] #wbView #tab-account :is(.ac-store-n,.ac-store-l,b){
  font-size:11.5px;
}
:root[data-lab-theme="graphite"] #wbView #tab-account .ac-go{
  font-family:var(--mono); font-size:10px; padding:3px 10px;
  background:none !important; color:var(--acc) !important;
  border:1px solid var(--accborder) !important; border-radius:0 !important;
  box-shadow:none !important;
}
/* ---- releases: notes are rows in the register's voice ---- */
:root[data-lab-theme="graphite"] #wbView #tab-releases h3{
  font-family:var(--chrome); font-size:11.5px; font-weight:600; color:var(--ink);
}
:root[data-lab-theme="graphite"] #wbView #tab-releases :is(.home-sub,.sv-sec){
  font-size:10px;
}
/* ---- elite: figures at the frame's size; the charts keep their own ---- */
:root[data-lab-theme="graphite"] #wbView #tab-elite b{ font-size:11.5px; }

/* frame voice, second measure: vision's explainer prose and unclassed
   toggles; profile's ghost verbs. The register numerals (home + profile)
   and the avatar monogram stay — note 01 names them a deliberate design
   call, content rather than frame. */
:root[data-lab-theme="graphite"] #wbView #tab-profile .sv-ghost{
  font-family:var(--mono); font-size:10px; padding:2px 8px;
  border-radius:0; box-shadow:none; min-height:0;
}
:root[data-lab-theme="graphite"] #wbView #tab-profile .pf-step{ font-size:11.5px; }

/* frame voice, third measure: elite figures at the frame's size (the
   positional half of this block moved to the calm-puzzles layer) */
:root[data-lab-theme="graphite"] #wbView #tab-elite :is(b,.el-mut){
  font-size:11.5px;
}

/* one element for every delete surface in the opening lab — 13-openings
   writes it; ⌘Z or a click revives */
#otUndo{
  position:fixed; left:50%; transform:translateX(-50%); bottom:34px; z-index:80;
  display:flex; align-items:center; gap:6px; height:24px; padding:0 12px;
  background:var(--paper2, #14181b); border:1px solid var(--hairline3, #232b31);
  color:var(--ink2, #aeb7bc); font-family:var(--mono); font-size:10px;
  letter-spacing:.03em; cursor:pointer;
}
#otUndo[hidden]{ display:none; }
#otUndo b{ font-weight:400; color:var(--acc, #d0aa72); }
#otUndo i{ font-style:normal; color:var(--mut, #5d686e); }
#otUndo:hover b{ color:var(--acc-hi, #e0bd8a); }

/* (the build board's 💾 save zone — .cb-actzone / #cbSave / .cb-act-hint —
   died with build mode, 2026-08-13, owner answer 1: its emitter cbActPaint
   left 28-cov-board the same day. The engine zone is the covered rail's.) */
.cb-engzone{ padding:2px 6px 6px; border-bottom:1px solid var(--hairline, #171c20); }
.cb-engzone:empty{ display:none; padding:0; border:0; }

/* panes pad their own header and body — the <section> carries nothing (a
   bare section{padding} once landed 27px of dead space on every rail
   pane) */
:root[data-lab-theme="graphite"] #wbRail .wb-pane{ padding:0; }

/* THE DATABASE ROOM — one owner (2026-08-11, T3).

   This file was two half-eras: db-room.css (the 6a geometry, graphite
   tokens) and db-calm.css (the calm reskin that re-decided its type,
   colour and row height without replacing it), with a third slice of the
   room's furniture — the user-database door and verbs — living in
   my-dbs.css. Three files, one room, and the reader had to hold all
   three to know what a row looks like. They are folded here in their
   original cascade sequence: §1 the geometry, §2 the calm dress, §3 the
   user-database furniture. The file sits at db-calm's old manifest slot,
   which is why the dress still lands exactly where it landed.

   The room keeps the HOUSE voice (house-voice.css owns .dbr-chip's face
   and sits after this file, deliberately). It has not taken the door
   voice, so nothing here secedes.

   The calm palette (--cm-*) is READ here and DECLARED once, in
   solve-session.css — it dresses five puzzle tabs, this room and the
   structure popup, and it was stated twice identically until T3. */

/* ================================================================== */
/* §1 · GEOMETRY — the 6a contract                                     */
/* ================================================================== */
/* the LIST is the room, full width: 26px edge · 236px objects · the grid.
   NO rail and NO board (board-first law, 2026-08-10) — a row click opens
   the game on the big board; the room registers no panes, so the frame
   goes wb-norail and the table takes the old rail's 330px. .vg reads
   --g-* from the graphite tokens — this layer re-points row height and
   declares what the room ADDS. Gated on body.dbroom (26-db-room.js). */

/* the room takes the whole view. (The `> *:not(#dbrRoom){display:none}`
   rule that used to follow went with the shelf it hid, 2026-08-11 — the
   skeleton's #tab-database is an empty shell now, like #tab-explorer,
   and a guard that matches nothing is a footgun for the next writer.) */
body.dbroom #wbView{ overflow:hidden; padding:0; scrollbar-gutter:auto; }
body.dbroom #tab-database{ display:flex; height:100%; min-height:0; }
/* 6a geometry: 236px objects · the list · 330px rail (the frame's own).
   The room drops the drawer slot — the list IS the room — but nothing
   moves: every other slot stays where every room keeps it. */
#dbrRoom{ display:grid; grid-template-columns:236px minmax(0,1fr);
  flex:1; min-width:0; min-height:0; }
#dbrRoom > *{ min-width:0; min-height:0; }

/* ---- column 2: the objects ---- */
#dbrLeft{ display:flex; flex-direction:column; overflow:auto;
  border-right:1px solid var(--hairline2); padding-bottom:10px; }
#dbrLeft .dbr-h{ flex:none; display:flex; align-items:center; gap:7px; height:20px;
  padding:0 12px; margin-top:9px; border-bottom:1px solid var(--hairline);
  font-family:var(--mono); font-size:10px; letter-spacing:.18em;
  text-transform:uppercase; color:var(--mut3); }
#dbrLeft .dbr-h:first-child{ margin-top:0; }
#dbrLeft .dbr-h b{ font-weight:400; color:var(--mut3);
  font-variant-numeric:tabular-nums; }
/* a heading that is also a door (columns): same anatomy, plus a chevron */
#dbrLeft button.dbr-htgl{ width:100%; background:none; border:0; border-bottom:1px solid var(--hairline);
  text-align:left; cursor:default; }
#dbrLeft .dbr-htgl i{ font-style:normal; margin-left:auto; font-size:9px;
  color:var(--mut4,#39444a); transition:transform .12s; }
#dbrLeft .dbr-htgl.open i{ transform:rotate(180deg); }
#dbrLeft .dbr-htgl:hover{ color:var(--mut); }
#dbrLeft .dbr-none{ padding:6px 12px; font-size:11px; color:var(--mut3); }

/* one row language for collections, kept searches and column toggles:
   [2px spine][12px glyph][8px][label ……][figure] — the tree row contract,
   restated for this column because #dbrLeft is not #wbLeft */
#dbrLeft button{ display:flex; align-items:center; gap:8px; width:100%; height:21px;
  padding:0 10px 0 8px; background:none; border:0; border-left:2px solid transparent;
  font:inherit; font-size:11.5px; color:var(--ink2); text-align:left; cursor:default; }
#dbrLeft button:hover{ background:var(--hover); }
#dbrLeft button > span{ flex:1; min-width:0; overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap; }
#dbrLeft button > b{ flex:none; font-weight:400; font-family:var(--mono);
  font-size:9.5px; color:var(--mut2); font-variant-numeric:tabular-nums lining-nums; }
#dbrLeft button > i{ flex:0 0 12px; font-style:normal; font-size:10.5px;
  text-align:center; color:var(--mut3); }
#dbrLeft .dbr-coll.on{ background:var(--acc-wash,rgba(208,170,114,.12)); border-left-color:var(--acc);
  color:var(--ink); }
#dbrLeft .dbr-coll.on > i{ color:var(--acc); }
#dbrLeft .dbr-coll.on > b{ color:var(--acc); }
#dbrLeft .dbr-kept{ padding-left:22px; }
#dbrLeft .dbr-kept:active{ background:var(--acc-wash,rgba(208,170,114,.12)); }
#dbrLeft .dbr-colrow .bx{ color:var(--acc); }
#dbrLeft .dbr-colrow:not(.on) .bx{ color:var(--star-off); }
#dbrLeft .dbr-colrow:not(.on) > span{ color:var(--mut2); }
#dbrLeft .dbr-colrow.na{ color:var(--mut4,#39444a); }
#dbrLeft .dbr-colrow.na > span{ color:var(--mut4,#39444a); }
#dbrLeft .dbr-colrow.na .bx{ color:var(--mut4,#39444a); }

/* ---- column 3: query bar · facets · grid ---- */
/* full-width room: the old rail was the right margin; 12px keeps the last
   column (and the qbar's count) off the glass */
#dbrMain{ display:grid; grid-template-rows:22px auto minmax(0,1fr); min-height:0;
  padding-right:12px; }
#dbrQbar{ display:flex; align-items:center; gap:7px; padding:0 10px;
  border-bottom:1px solid var(--hairline2); overflow:hidden; }
#dbrQbar .grow{ flex:1; }
.dbr-qi{ display:flex; align-items:center; gap:6px; flex:0 0 190px; height:18px;
  padding:0 7px; border:1px solid var(--hairline3); background:var(--paper2); }
.dbr-qi i{ font-style:normal; font-size:10px; color:var(--mut3); }
.dbr-qi input{ flex:1; min-width:0; height:16px; background:none; border:0;
  outline:none; font:inherit; font-size:11px; color:var(--ink); }
.dbr-qi input::placeholder{ color:var(--mut3); }
.dbr-qi input::-webkit-search-cancel-button{ display:none; }
#dbrChips{ display:flex; align-items:center; gap:6px; overflow:hidden; }
/* the chip is a predicate, not an accent: surface2 ground, hairline3 border,
   ink2 text, the × at mut4 — brass on every chip is no accent anywhere */
.dbr-chip{ display:flex; align-items:center; gap:7px; height:18px; padding:0 6px;
  background:var(--surface2); border:1px solid var(--hairline3);
  font:inherit; font-family:var(--mono); font-size:10px; color:var(--ink2);
  white-space:nowrap; cursor:default; }
.dbr-chip i{ font-style:normal; font-size:9px; color:var(--mut4,#39444a); }
.dbr-chip.any{ background:none; color:var(--mut); }
#dbrPlus{ width:18px; height:18px; background:none; border:0;
  font:inherit; font-size:11px; color:var(--mut4,#39444a); cursor:default; padding:0; }
/* the one door to the histograms — a quiet mono word that lights when open */
#dbrFacetTgl{ height:18px; padding:0 7px; background:none;
  border:1px solid var(--hairline3); font:inherit; font-family:var(--mono);
  font-size:10px; color:var(--mut); cursor:default; white-space:nowrap; }
#dbrFacetTgl.on{ color:var(--ink); border-color:var(--hairline2); }
#dbrFacetTgl:hover{ color:var(--ink2); }
#dbrFacets[hidden]{ display:none; }
#dbrCount{ align-self:stretch; display:flex; align-items:center; gap:7px;
  padding:0 11px; border-left:1px solid var(--hairline2);
  font-family:var(--mono); font-size:10px; color:var(--ink2);
  font-variant-numeric:tabular-nums lining-nums; white-space:nowrap; }
#dbrCount b{ font-weight:400; color:var(--ink); }

/* three facet panels, side by side: the same query with one dimension left
   out, so a bar's height and the count above it are the same computation.
   The mass is mut4, the selected span is acc, hover is acc-hi — the filter
   IS the visualisation. */
#dbrFacets{ display:grid; grid-template-columns:repeat(3, minmax(0,1fr));
  border-bottom:1px solid var(--hairline2); }
.dbr-facet{ display:flex; flex-direction:column; gap:3px; padding:5px 0 4px;
  border-right:1px solid var(--hairline); }
.dbr-facet:last-child{ border-right:0; }
.dbr-fh{ display:flex; align-items:baseline; padding:0 10px;
  font-family:var(--mono); font-size:8.5px; letter-spacing:.16em;
  text-transform:uppercase; color:var(--mut3); }
.dbr-fh b{ margin-left:auto; font-weight:400; letter-spacing:.04em;
  text-transform:none; font-size:9px; color:var(--acc); }
.dbr-fbars{ display:flex; align-items:flex-end; gap:1px; height:24px;
  padding:0 10px; }
.dbr-bar{ flex:1; min-width:2px; background:var(--mut4); cursor:default; }
.dbr-bar:hover{ background:var(--acc-hi); }
.dbr-bar.on{ background:var(--acc); }
.dbr-facet[data-facet="res"] .dbr-fbars{ gap:3px; }
.dbr-flab{ display:flex; justify-content:space-between; padding:0 10px;
  font-family:var(--mono); font-size:8px; color:var(--mut4,#39444a);
  font-variant-numeric:tabular-nums; }

/* the grid: no card, hairline separators — every other value is already a
   graphite token. Row height belongs to §2 below (body.dbroom --g-rowh:30px,
   the redesign's breathing room) — never re-point it here, the kit reads
   the var per render. */
#dbrGrid{ min-height:0; }
#dbrGrid.vg{ border:0; border-radius:0; background:var(--paper); }
#dbrGrid .vg-head{ border-bottom:1px solid var(--eval-dark); background:var(--surface); }
#dbrGrid .vg-h{ font-family:var(--mono); font-size:8.5px; letter-spacing:.12em;
  text-transform:uppercase; padding:0 7px; line-height:20px; color:var(--mut3); }
#dbrGrid .vg-h.dbr-na{ color:var(--mut4,#39444a); }
#dbrGrid .vg-c{ font-size:11.5px; }
#dbrGrid .vg-c.num, #dbrGrid .vg-c.dbr-res{ font-family:var(--mono);
  font-size:10.5px; color:var(--ink2); }
#dbrGrid .vg-c.dbr-na{ color:var(--mut4,#39444a); }
#dbrGrid .dbr-star{ text-align:center; padding:0; font-size:9.5px;
  color:var(--star-off); }
#dbrGrid .dbr-star.on{ color:var(--acc); }
#dbrGrid .res-pill{ background:none; border:0; padding:0; font-size:10.5px;
  color:var(--ink2); }
.dbr-empty{ padding:14px 10px; font-size:11.5px; color:var(--mut2); }

/* the ⋯ cell: the row menu's visible left-click door (the DO panel's heir).
   Quiet until the row is under the pointer — an action column that shouts
   on every row is a toolbar stamped 26,783 times. */
/* a puzzle row's ✓ (26-db-room DBR_PZCOLS): the solver's own verdict, read
   off passSolved — empty says nothing, solved takes the accent */
#dbrGrid .dbr-ok{ text-align:center; padding:0; font-size:11px; }
#dbrGrid .dbr-ok.on{ color:var(--acc); }
#dbrGrid .dbr-dots{ text-align:center; padding:0; font-size:11px;
  color:transparent; cursor:default; }
#dbrGrid .vg-row:hover .dbr-dots{ color:var(--mut2); }
#dbrGrid .vg-row .dbr-dots:hover{ color:var(--ink); }
.dbr-none{ font-size:11.5px; color:var(--mut3); }

/* the status line's own dot */
#svAppBar .dbr-dot{ color:var(--mut4,#39444a); }
#svAppBar .dbr-dot.ok{ color:var(--green); }

/* the pill is the site's, but a 48px cell is not a pill's habitat */
#dbrGrid .res-pill{ min-width:0; border-radius:0; }

/* ================================================================== */
/* §2 · THE CALM DRESS (was db-calm.css)                               */
/* ================================================================== */
/* ⚠ THE THEME IS THE DELIVERABLE (HANDOFF-DATABASE.md §0): do not re-skin
   with the graphite tokens or shrink type back to 11.5px — the lifted
   values ARE the redesign. Inside body.dbroom and .sm-pop use only the
   --cm-* tokens (declared in solve-session.css, the calm era's one
   declarer since T3).
   CSS-ONLY layer: no markup, no module, no second grid — the one object
   model (gdbRegister/GameRef/gdbOpen/gdbQuery/vgrid) ships untouched.
   INTEGRATED against the live DOM (a re-drop would undo these): the left
   column's rows carry the #dbrLeft scope + height:auto (§1 pins
   21px/11.5px at ID strength); row selection is [aria-selected="true"]
   (the kit stamps .sel + aria, never .on) and kills the old --g-selbar
   shadow; facet bars use .on; numeric cells are .num; the popup's live
   classes are .sm-tab/.sm-title; verb .on and [disabled] states are
   restated here because §1's base face outranks the 6A state rules. */

/* ---- room surfaces ---- */
body.dbroom #wbView{ background:var(--cm-paper); }
body.dbroom .dbr-h{
  font:11px var(--cm-mono); letter-spacing:.08em; text-transform:uppercase;
  color:var(--cm-mut); padding:12px 16px 8px;
}
body.dbroom .dbr-none{ font-size:12px; color:var(--cm-mut); padding:6px 0; }

/* ---- sources / kept / columns ---- */
body.dbroom #dbrLeft .dbr-coll{
  display:flex; align-items:center; gap:10px; width:100%; height:auto; text-align:left;
  border:0; border-left:2px solid transparent; background:none; cursor:pointer;
  padding:9px 16px; font-size:13px; color:var(--cm-ink2);
}
body.dbroom #dbrLeft .dbr-coll:hover{ background:var(--cm-surface2); }
body.dbroom #dbrLeft .dbr-coll.on{
  background:var(--cm-brass-wash); border-left-color:var(--cm-brass);
  color:var(--cm-brass-hi); font-weight:600;
}
body.dbroom #dbrLeft .dbr-coll .g{ font-style:normal; color:var(--cm-mut); }
body.dbroom #dbrLeft .dbr-coll.on .g{ color:var(--cm-brass); }
body.dbroom #dbrLeft .dbr-coll b{
  margin-left:auto; font:11.5px var(--cm-mono); font-weight:400; color:var(--cm-mut);
}
body.dbroom #dbrLeft .dbr-coll.on b{ color:var(--cm-brass-hi); }
body.dbroom #dbrLeft .dbr-kept{
  display:flex; align-items:baseline; gap:8px; width:100%; height:auto; text-align:left;
  border:0; background:none; cursor:pointer; padding:8px 16px;
  font-size:12.5px; color:var(--cm-ink2);
}
body.dbroom #dbrLeft .dbr-kept:hover{ background:var(--cm-surface2); color:var(--cm-brass-hi); }
body.dbroom #dbrLeft .dbr-kept b{ margin-left:auto; font:11px var(--cm-mono); font-weight:400; color:var(--cm-mut2); }
body.dbroom #dbrLeft .dbr-colrow{
  display:flex; align-items:center; gap:9px; width:100%; height:auto; text-align:left;
  border:0; background:none; cursor:pointer; padding:6px 16px;
  font-size:12.5px; color:var(--cm-ink2);
}
body.dbroom #dbrLeft .dbr-shape{
  flex:none; display:flex; align-items:flex-end; gap:1px;
  width:44px; height:11px; opacity:.75;
}
body.dbroom #dbrLeft .dbr-shape b{
  flex:1; background:#39434c; border-radius:1px 1px 0 0;
}
body.dbroom #dbrLeft .dbr-coll.on .dbr-shape{ opacity:1; }
body.dbroom #dbrLeft .dbr-coll.on .dbr-shape b{ background:var(--cm-brass); }
body.dbroom #dbrLeft .dbr-colrow .bx{ font-style:normal; color:var(--cm-mut); }
body.dbroom #dbrLeft .dbr-colrow.on .bx{ color:var(--cm-brass); }
body.dbroom #dbrLeft .dbr-colrow.na{ opacity:.4; }

/* ---- the query line, chips, facets ----
   chips ARE the query object; the skin only makes them look like it */
body.dbroom .dbr-qi{
  display:flex; align-items:center; gap:9px; background:var(--cm-surface);
  border:1px solid rgba(255,255,255,.09); border-radius:9px; padding:8px 13px;
}
body.dbroom .dbr-qi i{ font-style:normal; color:var(--cm-mut); }
body.dbroom .dbr-qi input{
  background:none; border:0; outline:0; color:var(--cm-ink);
  font:12.5px var(--cm-mono); width:100%;
}
body.dbroom .dbr-chip{
  display:inline-flex; align-items:center; gap:6px; cursor:pointer;
  background:var(--cm-brass-wash); border:1px solid rgba(216,176,120,.3);
  border-radius:99px; padding:5px 11px;
  font:11.5px var(--cm-mono); color:var(--cm-brass-hi);
}
body.dbroom .dbr-chip:hover{ border-color:var(--cm-brass); }
body.dbroom .dbr-facet{
  background:var(--cm-surface); border:1px solid var(--cm-line);
  border-radius:10px; padding:10px 14px;
}
body.dbroom .dbr-fh{
  display:flex; justify-content:space-between;
  font:10.5px var(--cm-mono); letter-spacing:.08em; text-transform:uppercase;
  color:var(--cm-mut);
}
body.dbroom .dbr-fh b{ color:var(--cm-ink2); font-weight:400; }
body.dbroom .dbr-fbars{ display:flex; align-items:flex-end; gap:2px; height:26px; margin-top:6px; }
body.dbroom .dbr-fbars > *{ background:#39434c; border-radius:1px 1px 0 0; cursor:pointer; }
body.dbroom .dbr-fbars > *:hover{ background:var(--cm-slate); }
body.dbroom .dbr-fbars > .on{ background:var(--cm-brass); }
body.dbroom .dbr-flab{
  display:flex; justify-content:space-between;
  font:10px var(--cm-mono); color:var(--cm-mut2); margin-top:4px;
}

/* ---- the one grid ----
   row height rides the kit's own CSS variable (--g-rowh) — never a JS
   constant here. 22 -> 30px is the redesign's breathing room. */
body.dbroom{ --g-rowh:30px; }
body.dbroom .vg-head{
  background:var(--cm-paper); border-bottom:1px solid rgba(255,255,255,.08);
}
body.dbroom .vg-h{
  font:10.5px var(--cm-mono); letter-spacing:.06em; text-transform:uppercase;
  color:var(--cm-mut); background:none; border:0;
}
body.dbroom .vg-h:hover{ color:var(--cm-brass-hi); }
body.dbroom .vg-h[aria-sort="ascending"], body.dbroom .vg-h[aria-sort="descending"]{
  color:var(--cm-brass-hi);
}
body.dbroom .vg-row{
  font-size:12.5px; color:var(--cm-ink2);
  border-bottom:1px solid rgba(255,255,255,.04); border-left:2px solid transparent;
}
body.dbroom .vg-row:hover{ background:var(--cm-surface2); }
body.dbroom .vg-row[aria-selected="true"]{
  background:var(--cm-brass-wash); border-left-color:var(--cm-brass);
  color:var(--cm-brass-hi); box-shadow:none;
}
body.dbroom .vg-row .num{
  font-family:var(--cm-mono); font-variant-numeric:tabular-nums; color:var(--cm-mut);
}
body.dbroom .dbr-empty{ color:var(--cm-mut); font-size:12.5px; }

/* (the rail card rules died with the rail — board-first law, 2026-08-10:
   this room registers no panes; a row click opens the game full size) */

/* ---- the structure / master-games popup (explorer) ---- */
.sm-pop{
  background:var(--cm-surface); border:1px solid var(--cm-line);
  border-radius:14px; box-shadow:0 30px 80px rgba(0,0,0,.55);
  color:var(--cm-ink2); font-size:12.5px;
}
.sm-pop .sm-title{
  font:italic 400 16px 'Libre Caslon Text',serif; color:var(--cm-ink);
}
.sm-pop .sm-tab{
  border:0; background:none; cursor:pointer; padding:6px 12px;
  font-size:12.5px; color:var(--cm-mut); border-radius:7px;
}
.sm-pop .sm-tab.on{
  background:var(--cm-brass-wash); color:var(--cm-brass-hi);
}

/* ================================================================== */
/* §3 · THE USER DATABASES' FURNITURE (was my-dbs.css)                 */
/* ================================================================== */
/* 16b's dialogs are labDialog content and stay in my-dbs.css; what a
   user database puts INSIDE this room — the create door and the open
   database's verb line — is the room's, and lives here. Every var still
   carries its fallback literal (the covered-palette rule): #dbrNewDb's
   last rule fires outside body.dbroom too. */
body.dbroom #dbrNewDb{
  display:block; width:calc(100% - 16px); margin:6px 8px 2px; height:26px;
  background:none; border:1px dashed var(--cm-line,rgba(255,255,255,.10));
  border-radius:6px; color:var(--cm-mut,#808b94); font-size:12px;
  cursor:pointer; text-align:center;
}
body.dbroom #dbrNewDb:hover{
  color:var(--cm-brass,#d8b078); border-color:var(--cm-brass,#d8b078);
}
/* the open database's verbs: ONE quiet line indented under its row —
   proximity is ownership (they used to render orphaned after Clip) */
body.dbroom .dbr-mine{
  display:flex; flex-wrap:wrap; gap:2px 3px; padding:2px 8px 6px 26px;
}
body.dbroom .dbr-mine button{
  background:none; border:1px solid transparent;
  border-radius:4px; color:var(--cm-mut,#808b94); font-size:11px;
  padding:2px 6px; cursor:pointer;
}
/* one hairline between the LIBRARY and what is YOURS */
body.dbroom .dbr-cut{
  height:1px; margin:7px 10px;
  background:var(--cm-line,rgba(255,255,255,.07));
}
body.dbroom .dbr-mine button:hover{
  color:var(--cm-brass-hi,#e6c391); border-color:var(--cm-brass,#d8b078);
}
body.dbroom .dbr-mine button[data-udb="delete"]:hover{
  color:var(--cm-terra,#cf8f6d); border-color:var(--cm-terra,#cf8f6d);
}
/* outside the calm room (a stray render) the door still reads */
#dbrNewDb{ font-family:var(--chrome,inherit); }
/* THE TREE ROW CONTRACT — one block, BOTH renderers, two row kinds: .wb-src
   (collections, rendered into #sgColl) and #tabs button[data-tab].
   Anatomy: [2px spine][12px glyph][8px][label][count], every label on
   x=34. The !important shield STAYS for the recorded reason (a skin's
   `button` rule once banded half the tree). Declare tree-row look HERE
   and nowhere else.
   THE GROUND IS THE SHEET now (doorframe, 2026-08-10): the tree renders
   only inside the summoned map — buff paper — so the row inks are the
   sheet's: pine ink, moss figures, the clock-flag red for where you are. */
#wbLeft #tabs .sg-lbl, #wbLeft #tabs .sg-head{
  display:flex !important; align-items:baseline; gap:6px;
  font-family:var(--mono) !important; font-size:9.5px !important;
  letter-spacing:.17em !important; text-transform:uppercase;
  color:var(--dv-moss,#5d6b5f) !important; padding:14px 12px 6px 34px !important;
}
#wbLeft .wb-src,
#wbLeft #tabs button[data-tab]{
  display:flex !important; align-items:center !important; gap:8px !important;
  width:100% !important; height:28px !important; min-height:0 !important;
  margin:0 !important; padding:0 12px !important; box-sizing:border-box !important;
  font-family:var(--chrome) !important; font-size:12.5px !important;
  font-weight:400 !important; border-radius:0 !important;
  border:none !important; border-left:2px solid transparent !important;
  background:none !important; color:var(--dv-ink,#24342b) !important;
  text-align:left !important; cursor:pointer;
}
#wbLeft .wb-src-g,
#wbLeft #tabs button[data-tab]::before{
  flex:0 0 12px !important; width:12px !important; text-align:center !important;
  color:var(--dv-moss,#5d6b5f) !important; font-size:11.5px !important; line-height:1 !important;
}
#wbLeft #tabs button[data-tab]::before{ content:"·"; }
#wbLeft #tabs button[data-glyph]::before{ content:attr(data-glyph); }
#wbLeft .wb-src-l{ flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
#wbLeft .wb-src-n{
  font-family:var(--mono); font-size:10.5px; color:var(--dv-moss,#5d6b5f);
  font-variant-numeric:tabular-nums;
}
#wbLeft .wb-src:hover,
#wbLeft #tabs button[data-tab]:hover:not(.on){
  background:rgba(36,56,45,.07) !important;
  color:var(--dv-ink,#24342b) !important;
}
#wbLeft .wb-src:hover .wb-src-g,
#wbLeft #tabs button[data-tab]:hover:not(.on)::before{ color:var(--dv-ink,#24342b) !important; }
#wbLeft .wb-src.on,
#wbLeft #tabs button[data-tab].on{
  background:rgba(36,56,45,.08) !important;
  border-left-color:var(--dv-flag,#a8402c) !important;
  color:var(--dv-ink,#24342b) !important; font-weight:500 !important; box-shadow:none !important;
}
#wbLeft .wb-src.on .wb-src-g,
#wbLeft #tabs button[data-tab].on::before{ color:var(--dv-flag,#a8402c) !important; }
#wbLeft .wb-src.on .wb-src-n{ color:var(--dv-flag,#a8402c); }
#wbLeft .wb-src:focus-visible,
#wbLeft #tabs button[data-tab]:focus-visible{
  outline:2px solid var(--dv-flag,#a8402c) !important; outline-offset:-2px !important;
}
#wbLeft #tabs .sg-body{ padding:0 !important; display:flex !important; flex-direction:column; }
#wbLeft #tabs .sg + .sg{ border-top:none !important; }
/* the puzzles and database LANDING rows stay in the markup for their
   readers (hdBuild, ⌘K, hrDoorLabel) but never render in the tree —
   their interiors are their rows, and the strip's chip owns the door */
#wbLeft #tabs button[data-tab="puzzles"],
#wbLeft #tabs button[data-tab="database"]{ display:none !important; }
/* the one claim on your attention: the due count rides the Opening Lab
   row as an attribute (22 stamps data-n), never as label text */
#wbLeft #tabs button[data-tab="openings"][data-n]:not([data-n=""])::after{
  content:attr(data-n); margin-left:auto;
  font-family:var(--mono); font-size:10.5px; color:var(--dv-flag,#a8402c);
  font-variant-numeric:tabular-nums;
}
/* THE USER-DATABASE DIALOGS (16b-my-dbs) — the create/edit/import/pick
   forms. They are labDialog content: body children OUTSIDE every --cm
   scope, so every var here carries its fallback literal (the covered-
   palette rule).

   2026-08-11 (T3): the room-side furniture this file used to hold — the
   ＋ create door and the open database's verb line — went home to
   db-room.css, which is the room that renders them. This file is the
   dialogs, and `udb-` is machine-guarded to it. */
.udb-form{ display:flex; flex-direction:column; gap:8px; margin:12px 0 2px; min-width:min(440px,72vw); }
.udb-form input[type="text"], .udb-form select, #udbNameIn{
  width:100%; box-sizing:border-box; background:#10151a;
  border:1px solid rgba(255,255,255,.10); border-radius:6px;
  color:#e7ecf0; font-size:13px; padding:7px 9px;
}
.udb-form input[type="text"]:focus, .udb-form select:focus{
  outline:none; border-color:var(--cm-brass,#d8b078);
}
.udb-grid{ display:grid; grid-template-columns:1fr 96px; gap:7px 8px; }
.udb-f{ display:flex; flex-direction:column; gap:3px; }
.udb-f span{
  font-size:10px; letter-spacing:.09em; text-transform:uppercase; color:#808b94;
}
/* the create dialog's two kinds — games · puzzles — are ghosts side by
   side at the footer's right (neither is the filled brass `save`: a
   choice is not a submit), the first pushed over by the message slot */
.udb-kind{
  font-size:13px; padding:6px 12px; cursor:pointer; border-radius:0;
  color:#c9d0d6; letter-spacing:.02em;
}
.udb-kind:hover{ color:var(--cm-brass,#d8b078); }
.udb-kind + .udb-kind{ margin-left:2px; }
#labDialog input[type="file"]{ font-size:12px; color:#808b94; margin:8px 0 2px; max-width:min(440px,72vw); }
.udb-picklist{ gap:3px; }
.udb-pick{
  display:flex; align-items:center; gap:8px; width:100%; box-sizing:border-box;
  background:none; border:1px solid rgba(255,255,255,.07); border-radius:6px;
  color:#e7ecf0; font-size:12.5px; padding:7px 10px; cursor:pointer; text-align:left;
}
.udb-pick i{ font-style:normal; color:#808b94; }
.udb-pick b{ margin-left:auto; font-weight:400; font-size:11px; color:#808b94;
  font-variant-numeric:tabular-nums; }
.udb-pick:hover, .udb-pick.on{ border-color:var(--cm-brass,#d8b078); }
.udb-pick:hover i, .udb-pick.on i{ color:var(--cm-brass,#d8b078); }
.udb-picknew{ border-style:dashed; color:#808b94; }
.udb-del{
  margin-left:auto; background:none; cursor:pointer; font-size:12.5px;
  color:var(--cm-terra,#cf8f6d) !important;
  border:1px solid var(--cm-terra,#cf8f6d) !important;
  border-radius:8px; padding:7px 13px;
}
/* THE HOUSE VOICE — part 1 of 2. The site's ONE voice, three rules:
   LANGUAGE IS CASLON — names, titles, ledes, and every verb.
   MEASUREMENT IS MONO — every figure, count, eyebrow; tabular.
   PAGES, NOT PANELS — air and one hairline separate sections.
   And the owner's law (2026-08-03): EVERY CLICKABLE VERB IS VISIBLY A
   BUTTON — a Caslon word inside a sleek 1px hairline that warms to brass.
   No filled slabs anywhere. Rows, tabs and list items that happen to be
   <button> are NOT verbs and are never boxed; instruments (engine pane,
   status bar, steppers) keep mono — the second voice, not a leftover.
   Part 2 lives at the end of solve-session.css and carries every rule
   that must outrank the instrument layers over the solver. */

/* ---- 1 · the palette steps to the calm values, in the same scope the  */
/*        graphite block declares (same specificity + later = this wins).*/
/*        --hl is board law and is NOT touched; board inks live in the   */
/*        payload and are NOT touched.                                   */
:root[data-lab-theme="graphite"]{
  /* the calm step turned to the landing's PINE (owner call 2026-08-10,
     "ignore the theme — pave your own road"): every stop keeps its old
     lightness and rotates hue to the rank's tournament green, hairlines
     warm from white-alpha to buff-alpha. Contrast pairs survive by
     construction; brass stays — club brass on green baize. */
  --paper:#131a14;  --paper2:#101610;  --surface:#19221a;  --surface2:#1d2a1e;
  --cardsolid:#19221a; --card:#131a14; --panelbg:#131a14;  --chatbg:#101610;
  --chrome-bg:#0f150f; --surface3:#222f23;
  --ink:#e6ebe2;    --ink2:#b3bfae;   --mut:#7f8d7c;      --mut2:#697a68;
  --mut3:#5c695a;   --mut4:#394639;
  --hairline:rgba(233,225,204,.055); --hairline2:rgba(233,225,204,.07);
  --hairline3:rgba(233,225,204,.09); --hairline4:rgba(233,225,204,.13);
  --panelline:rgba(233,225,204,.09); --btnline:rgba(233,225,204,.12);
  --btnlineh:rgba(216,176,120,.55);
  --acc:#d8b078;    --brass:#d8b078;  --accborder:rgba(216,176,120,.32);
  --acc-wash:rgba(216,176,120,.12);  --acc-wash2:rgba(216,176,120,.07);
  --acc-line:rgba(216,176,120,.75);
  --accfaint:rgba(216,176,120,.16);  --accdim:rgba(216,176,120,.55);
  --wash06:rgba(216,176,120,.07);
  --acc-hi:#e6c391;
  --off:#cf8f6d;    --off-ring:#96683f; --off-line:#7a5a45;
  --green:#8fd6a0;  --green2:#a9e2b6;  --wine:#cf8f6d;    --sea:#9db0bf;
  --bar:rgba(233,225,204,.10);
  --hover:rgba(230,235,226,.04);
  --g-hair:1px solid rgba(233,225,204,.055);
  --serif:'Libre Caslon Text', Georgia, 'Times New Roman', serif;
}

/* ---- 2 · ground truths ---- */
::selection{ background:rgba(216,176,120,.25); }
#wbView::-webkit-scrollbar{ width:9px; height:9px; }
#wbView::-webkit-scrollbar-thumb{
  background:rgba(255,255,255,.10); border-radius:5px;
  border:2px solid transparent; background-clip:content-box; }
#wbView::-webkit-scrollbar-thumb:hover{ background:rgba(216,176,120,.35);
  border:2px solid transparent; background-clip:content-box; }

/* ---- 3 · THE VERB ---------------------------------------------------
   A Caslon word in a hairline. The roster is EXPLICIT — a blanket
   button{} rule would box the nav tree, the lines list and every games
   row, because half this site's buttons are rows. A button not on the
   roster keeps its room's row voice.
   2026-08-11: every .lr- entry seceded to the door voice — lab-one.css
   at the cascade tail owns the Opening Lab's verbs and chips now, the
   same secession the puzzles hub made on 2026-08-10.
   2026-08-11 (T3): .dbr-pb dropped — no writer anywhere in patterns/js
   or patterns/build. The database room's verbs that DO exist stay on
   this roster; it has not taken the door voice.                       */
.primary, .solvebtn, .sv-sec, .ot-ldrill, .pf-btn, .el-linkbtn, .sm-act, .udb-go, .udb-pick, .ac-go, .ac-ghost, .lc-primary, .exg-more {
  font-family:var(--serif) !important;
  font-size:13.5px !important; font-weight:400 !important;
  letter-spacing:.01em !important; text-transform:none !important;
  color:var(--ink2) !important;
  background:none !important;
  border:1px solid var(--btnline) !important;
  border-radius:3px !important;
  padding:6px 14px !important;
  line-height:1.25 !important;
  cursor:pointer;
  transition:color .12s ease, border-color .12s ease, background .12s ease;
}
.primary:hover, .solvebtn:hover, .sv-sec:hover, .ot-ldrill:hover, .pf-btn:hover, .el-linkbtn:hover, .sm-act:hover, .udb-go:hover, .udb-pick:hover, .ac-go:hover, .ac-ghost:hover, .lc-primary:hover, .exg-more:hover {
  color:var(--acc-hi) !important;
  border-color:var(--btnlineh) !important;
  background:var(--acc-wash2) !important;
}
/* THE PRIMARY VERB — the one brass object on its screen */
.primary, .pf-btn.acc, .ac-go, .lc-primary {
  color:var(--acc) !important;
  border-color:var(--accborder) !important;
}
.primary:hover, .pf-btn.acc:hover, .ac-go:hover, .lc-primary:hover {
  color:var(--acc-hi) !important;
  border-color:var(--acc) !important;
  background:var(--acc-wash2) !important;
}
.ac-go.ac-go-quiet{ color:var(--ink2) !important;
  border-color:var(--btnline) !important; }
/* keyboard focus is part of "still clickable" */
.primary:focus-visible, .solvebtn:focus-visible, .sv-sec:focus-visible, .pf-btn:focus-visible, .ac-go:focus-visible, .sm-act:focus-visible {
  outline:1px solid var(--acc); outline-offset:2px; }
button:disabled{ opacity:.4; cursor:default; }

/* ---- 4 · THE CHIP AND THE STEPPER — instrument controls stay mono,
   and get the same hairline so they read as touchable ---- */
.res-pill, .dbr-chip, .sf-mpv-btn, .ac-seg {
  border:1px solid var(--hairline3) !important; border-radius:3px !important;
  background:none !important;
}
.res-pill:hover, .dbr-chip:hover, .sf-mpv-btn:hover, .ac-seg:hover {
  border-color:var(--btnlineh) !important; }
.res-pill.on, .dbr-chip.on, .ac-seg.on{
  color:var(--acc) !important; border-color:var(--accborder) !important;
  background:var(--acc-wash2) !important; }

/* ---- 5 · WHAT IS WRITTEN gets the writing voice ---- */
#wbView input[type="text"], #wbView input[type="search"],
#wbView input[type="password"], #wbView input[type="number"],
#wbView input:not([type]), #wbView textarea, #wbView select,
#ovl input, #ovl textarea, #ovl select{
  background:var(--paper2); color:var(--ink);
  border:1px solid var(--hairline3); border-radius:3px;
  padding:6px 10px; font-size:13px;
  transition:border-color .12s ease;
}
#wbView input:focus, #wbView textarea:focus, #wbView select:focus,
#ovl input:focus, #ovl textarea:focus{
  outline:none; border-color:var(--accborder); }
#wbView textarea{ font-family:var(--mono); font-size:12px; }

/* ---- 6 · sheets, dialogs, toasts: one lifted surface, one hairline,
   6px — the room's own sheet radius, not the 14px app pillow ---- */
.sm-pop, dialog, .lab-dlg{
  background:var(--surface); border:1px solid var(--hairline4);
  border-radius:6px;
}

/* ---- 7 · the reading ledger: shared table voices ---- */
.ndb-table th{
  font-family:var(--mono); font-size:9.5px; font-weight:400;
  letter-spacing:.14em; text-transform:uppercase; color:var(--mut3);
  border-bottom:1px solid var(--hairline3);
}
.ndb-table td{ font-variant-numeric:tabular-nums; }

@media (prefers-reduced-motion:reduce){
  .primary, .sv-sec, .pf-btn, .ac-go, .sm-act, .res-pill, .dbr-chip { transition:none !important; }
}


/* ---- 8 · the tokens the graphite block never re-declared. --line is the
   one that mattered: 44 rules borrow it, and it has been OCEAN NAVY
   (#1b2740) on every graphite screen since the theme shipped — the same
   leak class as the documented --accfaint story. --ok/--bad/--mid are the
   verdict colours (right, wrong, partial) and were ocean's green-blue,
   dusty red and gold; they become the calm green, the terracotta and the
   brass, so every verdict on the site speaks the room's own language. */
:root[data-lab-theme="graphite"]{
  --line:rgba(233,225,204,.09);
  --ok:#8fd6a0; --bad:#cf8f6d; --mid:#d8b078;
  --ghost1:#171f18; --ghost1l:#1d271e; --ghost2:#151c16; --ghost2l:#202a21;
}
#wbView ::placeholder, #ovl ::placeholder{ color:var(--mut3); opacity:1; }
input[type="checkbox"], .set-chk{ accent-color:var(--acc); }

/* ---- 9 · THE MINI-VERB (retired, kept as the record) — compact actions
   in rails and rows, same voice as the verb, smaller body, !important
   because a room layer could otherwise fill it. Its roster emptied one
   secession at a time: .pz-act left 2026-08-10 (the puzzles hub is a
   door-voice room, puzzles-door.css owns its verbs); .dbr-verb left
   2026-08-11 (T3, no writer anywhere); .exg-varre left 2026-08-18 — the
   explorer SESSION took the door voice, its variation offers are
   in-prose words dressed by explorer-session.css, and an !important box
   here would have re-boxed them from a file the room cannot see. The
   master-games popup's .exg-more still answers roster 6 above. */

/* ---- 10 · NAMES ARE LANGUAGE, room by room. Each of these is a title a
   person reads, verified against the live DOM before being written:
   pile names, theme names, technique names, article titles, the player-
   databases masthead, release notes, the settings sheet. Dense grids
   (vgrid, scoresheets, engine PVs) deliberately stay in the chrome face —
   they are instruments, and mono/sans is the instrument voice. */
/* (.pz-l left this list 2026-08-11 — the ownership test's first catch:
   puzzles-door.css owns every pz- class, and this rule had been silently
   overridden since the hub seceded) */
.ch-name{ font-family:var(--serif); font-size:16px; font-weight:400;
  letter-spacing:0; }
.unit{ align-items:baseline; }
.unit > span:not(.uid):not(.ct){
  font-family:var(--serif); font-size:14.5px; color:var(--ink2); }
.unit:hover > span:not(.uid):not(.ct){ color:var(--ink); }
.art-title{ font-family:var(--serif) !important; font-style:italic;
  font-weight:400 !important; font-size:27px !important;
  letter-spacing:-.01em; }
#ndbHero{ font-family:var(--serif); font-style:italic; font-weight:400;
  font-size:17px; }
.rel-card h3{ font-family:var(--serif); font-weight:400; font-size:17px; }
.rel-card h3 small{ font-family:var(--mono); font-size:10px;
  letter-spacing:.1em; color:var(--mut3); }
/* older notes fold to their title line; the title is the door */
.rel-card .rel-h{ cursor:pointer; display:flex; align-items:baseline; gap:8px; }
.rel-card .rel-h:hover{ color:var(--acc); }
.rel-card .rel-cv{ font-style:normal; font-size:10px; margin-left:auto;
  color:var(--mut4,var(--mut3)); transition:transform .12s; }
.rel-card:not(.rel-fold) .rel-cv{ transform:rotate(180deg); }
.rel-card.rel-fold .home-sub, .rel-card.rel-fold .home-cta{ display:none; }
.rel-card.rel-fold{ margin-bottom:0; }
#setPanel h3, #setPanel > header, .set-panel h3{
  font-family:var(--serif); font-style:italic; font-weight:400;
  font-size:18px; }
.home-card{ background:none; border:0; border-radius:0;
  border-top:1px solid var(--line); box-shadow:none; }
.lc-send{ background:none !important; border:1px solid var(--btnline) !important;
  color:var(--acc) !important; }
.lc-send:hover{ border-color:var(--btnlineh) !important;
  background:var(--acc-wash2) !important; }



/* the structure-cart verb takes the reading voice too (2026-08-03; moved
   here from the overrides layer 2026-08-11 — this file is .sm-act's owner) */
.sm-act{ font-family:var(--serif) !important; }
/* THE ARCHIVE — 176 years on one screen. The century ribbon is the
   signature: one bar per year, height = how much held history that year
   carries. House voice; honesty as material — "we hold none of them yet"
   is a standing line, and a dedup twin is shown, never folded. */
#hyWrap{ max-width:1100px; padding:18px 26px 60px; }

/* ---- the century ribbon ---- */
#hyRibbon{ margin:2px 0 8px; }
.hy-rail{ display:flex; align-items:flex-end; gap:1px; height:34px;
  overflow-x:auto; scrollbar-width:none; padding-bottom:2px;
  border-bottom:1px solid var(--line); }
.hy-rail::-webkit-scrollbar{ display:none; }
.hy-yr{ flex:0 0 5px; height:100%; display:flex; align-items:flex-end;
  background:none; border:0; padding:0; cursor:pointer; }
.hy-yr i{ display:block; width:100%; background:var(--mut4);
  border-radius:1px 1px 0 0; transition:background .1s ease; }
.hy-yr:hover i{ background:var(--mut); }
.hy-yr.on i{ background:var(--acc); }
.hy-yr:focus-visible{ outline:1px solid var(--acc); outline-offset:1px; }
.hy-caption{ display:flex; align-items:center; gap:14px; margin-top:7px;
  position:relative; }
.hy-era{ font-family:var(--mono); font-size:11px; letter-spacing:.08em;
  color:var(--mut); font-variant-numeric:tabular-nums; white-space:nowrap; }
#hyFind{ margin-left:auto; width:230px; background:none;
  border:0; border-bottom:1px solid var(--line); border-radius:0;
  padding:3px 2px; font-family:var(--serif); font-size:13.5px;
  color:var(--ink); }
#hyFind:focus{ outline:none; border-bottom-color:var(--accborder); }
.hy-hits{ position:absolute; right:0; top:26px; z-index:30; display:flex;
  flex-direction:column; min-width:230px; max-width:330px;
  background:var(--surface); border:1px solid var(--hairline4);
  border-radius:6px; overflow:hidden; }
.hy-hits:empty{ display:none; }
.hy-hits button{ text-align:left; background:none; border:0;
  border-top:1px solid var(--line); padding:7px 12px; cursor:pointer;
  font-family:var(--serif); font-size:13.5px; color:var(--ink2); }
.hy-hits button:first-child{ border-top:0; }
.hy-hits button:hover{ background:var(--acc-wash2); color:var(--ink); }
.hy-hits button s{ text-decoration:none; margin-left:8px;
  font-family:var(--mono); font-size:10px; color:var(--mut3); }

/* ---- the shelf and the page ---- */
#hyBody{ display:grid; grid-template-columns:295px minmax(0,1fr);
  gap:0 38px; align-items:start; }
#hyList{ border-top:1px solid var(--line); max-height:calc(100vh - 210px);
  overflow-y:auto; scrollbar-width:thin; }
.hy-sec{ font-family:var(--mono); font-size:9.5px; letter-spacing:.16em;
  color:var(--mut3); padding:14px 2px 5px; }
.hy-row{ display:block; width:100%; text-align:left; background:none;
  border:0; border-bottom:1px solid var(--line); border-left:2px solid transparent;
  padding:7px 8px 8px; cursor:pointer; }
.hy-row:hover{ background:var(--hover); }
.hy-row.on{ border-left-color:var(--acc); background:var(--acc-wash2); }
.hy-row .nm{ display:block; font-family:var(--serif); font-size:14px;
  line-height:1.3; color:var(--ink2);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.hy-row.on .nm, .hy-row:hover .nm{ color:var(--ink); }
.hy-row .site{ font-size:11px; color:var(--mut3); margin-right:8px; }
.hy-row .meta{ font-family:var(--mono); font-size:10px; color:var(--mut3);
  font-variant-numeric:tabular-nums; }

/* ---- the event page (the approved comp, verbatim voice) ---- */
#hyPage{ padding-top:12px; min-height:420px; }
.hy-idle{ font-family:var(--serif); font-size:14px; color:var(--mut3);
  padding:40px 0; }
.hy-eyebrow{ margin:0 0 10px; font-family:var(--mono); font-size:10px;
  letter-spacing:.16em; text-transform:uppercase; color:var(--mut3); }
.hy-eyebrow .pk u{ text-decoration:none; color:var(--mut2); margin:0 3px 0 8px; }
.hy-name{ margin:0; font-family:var(--serif); font-style:italic;
  font-weight:400; font-size:38px; line-height:1.04; letter-spacing:-.015em;
  color:var(--ink); }
.hy-lede{ margin:14px 0 0; max-width:54ch; font-family:var(--serif);
  font-size:15.5px; line-height:1.6; color:var(--mut); }
.hy-lede b{ font-weight:400; color:var(--ink2); }
.hy-twin{ margin:12px 0 0; font-family:var(--serif); font-size:13px;
  color:var(--mut3); }
.hy-twin button{ background:none; border:0; padding:0; cursor:pointer;
  font:inherit; color:var(--acc); }
.hy-twin button:hover{ color:var(--acc-hi); }

.hy-field{ margin:26px 0 0; max-width:560px;
  border-top:1px solid var(--hairline3); }
.hy-prow{ display:grid; grid-template-columns:36px 1fr 118px 52px;
  align-items:center; height:34px; border-bottom:1px solid var(--line); }
.hy-prow:hover{ background:var(--hover); }
.hy-prow .rk{ font-family:var(--mono); font-size:10.5px; color:var(--mut4);
  text-align:right; padding-right:14px; font-variant-numeric:tabular-nums; }
.hy-prow .nm{ text-align:left; background:none; border:0; padding:0;
  cursor:pointer; font-family:var(--serif); font-size:16px; color:var(--ink2);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.hy-prow .nm:hover{ color:var(--acc-hi); }
.hy-prow .nm s{ text-decoration:none; margin-left:9px;
  font-family:var(--mono); font-size:10px; color:var(--mut4); }
.hy-prow .mv{ position:relative; height:34px; }
.hy-prow .mv::before{ content:""; position:absolute; left:50%; top:8px;
  bottom:8px; width:1px; background:var(--mut4); opacity:.55; }
.hy-prow .mv i{ position:absolute; top:50%; height:3px; margin-top:-1.5px;
  border-radius:1px; }
.hy-prow .mv i.up{ left:50%; background:var(--acc); }
.hy-prow .mv i.dn{ right:50%; background:var(--sea); opacity:.5; }
.hy-prow .mv i.flat{ left:50%; width:3px; margin-left:-1.5px;
  background:var(--mut4); }
.hy-prow .sc{ font-family:var(--mono); font-size:13px; color:var(--ink2);
  text-align:right; font-variant-numeric:tabular-nums; }
.hy-prow.win .rk, .hy-prow.win .sc{ color:var(--acc); }
.hy-prow.win .nm{ color:var(--ink); }
.hy-more{ display:block; width:100%; text-align:center; background:none;
  border:0; border-bottom:1px solid var(--line); padding:9px 0;
  font-family:var(--serif); font-size:13px; color:var(--mut2);
  cursor:pointer; }
.hy-more:hover{ color:var(--acc-hi); }
.hy-say{ margin:18px 0 0; max-width:560px; min-height:20px;
  font-family:var(--serif); font-size:14px; line-height:1.5;
  color:var(--mut3); }
.hy-say b{ font-weight:400; color:var(--ink2); }
.hy-foot{ margin:34px 0 0; max-width:560px; padding-top:15px;
  border-top:1px solid var(--line); font-family:var(--mono); font-size:10px;
  letter-spacing:.08em; color:var(--mut3); }
.hy-foot u{ text-decoration:none; color:var(--acc); }
/* THE GAMES ARE THE PAGE (2026-08-03 pm, owner's inversion): when an
   event's games are here they open WITH the page — rounds caption the
   story, the winner carries the ink, the loser recedes, and the opening
   code + length sit at the edge in the measurement voice. No boxes. */
.hy-glist{ max-width:560px; margin:26px 0 0; }
.hy-seccap{ margin:26px 0 4px; font-family:var(--mono); font-size:10px;
  letter-spacing:.14em; color:var(--mut3); }
.hy-seccap .n{ margin-left:10px; color:var(--acc); }
.hy-gcap{ margin:16px 0 2px; font-family:var(--mono); font-size:9.5px;
  letter-spacing:.12em; color:var(--mut4, var(--mut3)); }
/* a caption that is a door: same voice, a count, a chevron that turns */
button.hy-rtgl{ display:flex; align-items:center; gap:8px; width:100%;
  background:none; border:0; border-radius:0; padding:0; text-align:left;
  cursor:pointer; }
.hy-rtgl .n{ color:var(--mut3); letter-spacing:0; }
.hy-rtgl i{ font-style:normal; font-size:9px; color:var(--mut4,var(--mut3));
  transition:transform .12s; }
.hy-rtgl.open i{ transform:rotate(180deg); }
.hy-rtgl:hover{ color:var(--mut2); }
.hy-rbody[hidden]{ display:none; }
.hy-grow{ display:grid; grid-template-columns:1fr 40px 1fr 34px 28px;
  gap:8px; padding:4px 0; border-bottom:1px solid var(--hairline4);
  font-family:var(--mono); font-size:11.5px; color:var(--mut2);
  width:100%; background:none; border-left:0; border-right:0; border-top:0;
  border-radius:0; text-align:left; cursor:pointer; }
.hy-grow:hover .rs{ color:var(--ink); }
.hy-grow:hover{ border-bottom-color:var(--accborder); }
.hy-grow .win{ color:var(--ink); }
.hy-grow .lose{ color:var(--mut3); }
.hy-grow .rs{ text-align:center; color:var(--acc); }
.hy-grow .ec{ text-align:right; color:var(--mut3); }
.hy-grow .pl{ text-align:right; color:var(--mut3); }
.hy-row .held{ color:var(--acc); margin-right:8px; }
/* the year's tier bands: the caption is the tier, T1 carries the brass */
.hy-sec.hy-tier{ letter-spacing:.14em; }
.hy-sec.hy-tier.t1{ color:var(--acc); }

/* ---- the year page: the top fifty in five views ---- */
.hy-chips{ display:flex; gap:8px; flex-wrap:wrap; margin:20px 0 0; }
.hy-chip{ background:none; border:1px solid var(--hairline3);
  border-radius:3px; padding:4px 11px; cursor:pointer;
  font-family:var(--mono); font-size:10px; letter-spacing:.08em;
  text-transform:uppercase; color:var(--mut); }
.hy-chip:hover{ border-color:var(--btnlineh); color:var(--ink2); }
.hy-chip.on{ color:var(--acc); border-color:var(--accborder);
  background:var(--acc-wash2); }
.hy-list50 .nm.unk{ font-family:var(--serif); font-size:16px;
  color:var(--mut3); white-space:nowrap; overflow:hidden;
  text-overflow:ellipsis; }
.hy-prow .mv i.new{ left:50%; width:4px; height:4px; margin-top:-2px;
  border-radius:50%; background:var(--acc); position:absolute; top:50%; }
.hy-worldrow .nm{ color:var(--acc); }
.hy-worldrow.on{ border-left-color:var(--acc); }

/* ---- the odds ladder: band dividers inside the year list ---- */
.hy-band{ display:flex; align-items:center; gap:10px; padding:13px 0 5px; }
.hy-band span{ font-family:var(--mono); font-size:9px; letter-spacing:.16em;
  color:var(--mut3); white-space:nowrap; }
.hy-band::after{ content:""; flex:1; height:1px; background:var(--line); }
.hy-band.empty span{ color:rgba(216,176,120,.75); }
.hy-band.empty::after{ background:rgba(216,176,120,.18); }
.hy-lrow.tie .rk{ color:var(--mut3); }

/* ---- the chart: fifty careers in gap-space ---- */
#hyChartBox{ position:relative; margin:22px 0 0; height:430px;
  border-top:1px solid var(--hairline3); }
#hyChartBox canvas{ position:absolute; inset:0; display:block; }
#hyCover{ cursor:crosshair; }
#hyAxis{ position:relative; height:22px; }
#hyAxis button{ position:absolute; top:3px; transform:translateX(-50%);
  background:none; border:0; padding:2px 4px; cursor:pointer;
  font-family:var(--mono); font-size:9.5px; letter-spacing:.06em;
  color:var(--mut3); font-variant-numeric:tabular-nums; }
#hyAxis button:hover{ color:var(--acc); }
.hy-chipgap{ flex:1; }

/* ---- the duel ---- */
.hy-duel{ margin:30px 0 0; max-width:560px; }
.hy-duel .side{ display:grid; grid-template-columns:1fr 76px;
  align-items:baseline; padding:10px 0; }
.hy-duel .who{ text-align:left; background:none; border:0; padding:0;
  cursor:pointer; font-family:var(--serif); font-size:25px;
  color:var(--ink2); line-height:1.15; }
.hy-duel .who:hover{ color:var(--acc-hi); }
.hy-duel .who s{ text-decoration:none; margin-left:11px;
  font-family:var(--mono); font-size:11px; color:var(--mut4); }
.hy-duel .pts{ font-family:var(--mono); font-size:25px; color:var(--ink2);
  text-align:right; font-variant-numeric:tabular-nums; }
.hy-duel .side.won .who, .hy-duel .side.won .pts{ color:var(--acc); }
.hy-duel .split{ display:flex; height:5px; margin:8px 0 11px;
  background:var(--line); overflow:hidden; }
.hy-duel .split i{ height:100%; }
.hy-duel .split i.a{ background:var(--acc); }
.hy-duel .split i.b{ background:var(--sea); opacity:.45; }

/* ---- a career ---- */
.hy-career{ margin:24px 0 0; max-width:620px;
  border-top:1px solid var(--hairline3); }
.hy-erow{ display:grid; grid-template-columns:52px 1fr 150px;
  align-items:center; width:100%; text-align:left; height:33px;
  background:none; border:0; border-bottom:1px solid var(--line);
  cursor:pointer; }
.hy-erow:hover{ background:var(--hover); }
.hy-erow .yr{ font-family:var(--mono); font-size:10.5px; color:var(--mut3);
  font-variant-numeric:tabular-nums; }
.hy-erow .nm .site{ font-family:var(--chrome); font-size:11px;
  color:var(--mut3); }
.hy-erow .nm{ font-family:var(--serif); font-size:14.5px; color:var(--ink2);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  padding-right:12px; }
.hy-erow:hover .nm{ color:var(--ink); }
.hy-erow .res{ font-family:var(--mono); font-size:11px; color:var(--mut);
  text-align:right; font-variant-numeric:tabular-nums; }
.hy-erow.win .yr, .hy-erow.win .res{ color:var(--acc); }

@media (max-width:1000px){
  #hyBody{ grid-template-columns:1fr; }
  #hyList{ max-height:280px; margin-bottom:20px; }
}
@media (prefers-reduced-motion:reduce){ .hy-yr i{ transition:none; } }

/* house voice: names in Caslon, measurement in mono, pages not panels — no
   boxes, no filled slabs. The dex cells are DEPICTIONS (state = fill),
   never buttons; the year bars are doors into the Archive. Data:
   war_room.json. */
#wrWrap{ max-width:1180px; margin:0 auto; padding:18px 22px 40px; }
.wr-idle{ font-family:var(--serif); font-style:italic; color:var(--mut2);
  font-size:14px; }

#wrTop{ display:flex; gap:44px; flex-wrap:wrap; padding:10px 0 16px;
  border-bottom:1px solid var(--hairline3); }
.wr-count b{ display:block; font-family:var(--mono); font-weight:500;
  font-size:26px; letter-spacing:.5px; color:var(--ink);
  font-variant-numeric:tabular-nums; }
.wr-count i{ font-family:var(--serif); font-style:italic; font-size:12.5px;
  color:var(--mut2); }

#wrRibbon{ padding:16px 0 6px; border-bottom:1px solid var(--hairline3); }
.wr-lbl{ font-family:var(--mono); font-size:10px; letter-spacing:.6px;
  text-transform:uppercase; color:var(--mut3); margin-bottom:8px; }
.wr-bars{ display:flex; align-items:flex-end; gap:2px; height:40px;
  overflow-x:auto; scrollbar-width:none; }
.wr-bars::-webkit-scrollbar{ display:none; }
.wr-yr{ flex:0 0 4px; min-width:4px; padding:0; margin:0; border:0;
  border-radius:0; background:var(--hairline4); position:relative;
  cursor:pointer; }
.wr-yr:hover{ background:var(--mut3); }
.wr-yr i{ position:absolute; left:0; right:0; bottom:0; display:block;
  background:var(--acc); }

#wrDex{ padding:16px 0 12px; border-bottom:1px solid var(--hairline3); }
.wr-dexhead{ display:flex; justify-content:space-between; gap:16px;
  align-items:baseline; flex-wrap:wrap; margin-bottom:10px; }
.wr-dext{ font-family:var(--serif); font-style:italic; font-size:15px;
  color:var(--ink); }
.wr-leg{ font-family:var(--mono); font-size:10.5px; color:var(--mut2);
  display:inline-flex; align-items:center; gap:6px;
  font-variant-numeric:tabular-nums; }
.wr-leg .wr-c{ margin-left:10px; }
.wr-dec{ display:flex; align-items:center; flex-wrap:wrap; gap:3px;
  margin:0 0 7px; }
.wr-decl{ font-family:var(--mono); font-size:10px; color:var(--mut3);
  letter-spacing:.5px; width:42px; flex:0 0 42px; }
.wr-c{ display:inline-block; width:10px; height:10px; flex:0 0 10px;
  border:1px solid var(--hairline3); box-sizing:border-box; }
.wr-c.s3{ background:var(--acc); border-color:var(--acc); }
.wr-c.s2{ background:linear-gradient(to top, var(--acc) 50%,
  transparent 50%); border-color:var(--acc); }
.wr-c.s1{ background:
  radial-gradient(circle 2px at center, var(--mut2) 98%, transparent); }
.wr-c.s0{ background:none; }

#wrCols{ display:grid; grid-template-columns:1fr 1fr; gap:44px;
  padding:16px 0; border-bottom:1px solid var(--hairline3); }
.wr-h{ font-family:var(--serif); font-style:italic; font-size:15px;
  color:var(--ink); margin-bottom:8px; }
.wr-h .wr-sub{ font-family:var(--mono); font-style:normal; font-size:10px;
  letter-spacing:.4px; text-transform:uppercase; color:var(--mut3);
  margin-left:8px; }
.wr-h.wr-gap{ margin-top:18px; }
.wr-row{ display:flex; align-items:baseline; gap:10px; padding:3px 0;
  font-size:12.5px; }
.wr-name{ color:var(--ink2, var(--ink)); min-width:120px; }
.wr-fig{ font-family:var(--mono); font-size:11.5px; color:var(--mut);
  font-variant-numeric:tabular-nums; min-width:72px; text-align:right; }
.wr-bar{ flex:1; height:2px; background:var(--hairline4);
  align-self:center; }
.wr-bar i{ display:block; height:2px; background:var(--acc); }
.wr-pct{ font-family:var(--mono); font-size:11px; color:var(--mut2);
  font-variant-numeric:tabular-nums; width:38px; text-align:right; }
.wr-site{ font-family:var(--mono); font-size:10.5px; color:var(--mut3);
  margin-left:auto; }

#wrFoot{ padding:14px 0 0; display:flex; flex-direction:column; gap:6px; }
.wr-built{ font-family:var(--mono); font-size:10.5px; letter-spacing:.4px;
  color:var(--mut2); font-variant-numeric:tabular-nums; }
.wr-honest{ font-family:var(--serif); font-style:italic; font-size:12.5px;
  color:var(--mut2); }

@media (max-width:1000px){
  #wrCols{ grid-template-columns:1fr; gap:20px; }
  #wrTop{ gap:24px; }
  .wr-count b{ font-size:20px; }
}

/* THE WAR ROOM — the year roll call (click a ribbon year) */
#wrYear{ padding:14px 0 16px; border-bottom:1px solid var(--hairline3); }
.wr-yhead{ display:flex; align-items:baseline; gap:14px; flex-wrap:wrap;
  margin-bottom:10px; }
.wr-arch{ margin-left:auto; font-family:var(--serif); font-style:italic;
  font-size:12.5px; color:var(--mut2); background:none;
  border:1px solid var(--hairline3); border-radius:3px; padding:3px 10px;
  cursor:pointer; }
.wr-arch:hover{ color:var(--acc); border-color:var(--acc); }
.wr-ycols{ display:grid; grid-template-columns:1fr 1fr; gap:44px; }
.wr-ev{ display:flex; align-items:baseline; gap:10px; width:100%;
  padding:2px 0; margin:0; border:0; border-radius:0; background:none;
  text-align:left; font-size:12.5px; color:var(--ink2, var(--ink));
  cursor:pointer; }
.wr-ev .wr-fig{ min-width:84px; }
.wr-ev .wr-name{ min-width:0; overflow:hidden; text-overflow:ellipsis;
  white-space:nowrap; flex:1; }
.wr-ev:hover .wr-name{ color:var(--acc); }
.wr-ev.miss{ color:var(--mut2); }
.wr-ev.miss .wr-fig{ color:var(--mut3); }
.wr-more{ font-family:var(--serif); font-style:italic; font-size:12px;
  color:var(--mut2); background:none; border:1px solid var(--hairline3);
  border-radius:3px; padding:3px 10px; margin-top:8px; cursor:pointer; }
.wr-more:hover{ color:var(--acc); border-color:var(--acc); }
.wr-yr.on{ outline:1px solid var(--acc); outline-offset:1px; }
@media (max-width:1000px){ .wr-ycols{ grid-template-columns:1fr; gap:18px; } }
/* ====== THE DOORFRAME — one strip of chrome, in the landing's material ====
   (owner call 2026-08-10: "when we click into one of the 3, the UI should
   have no mention of the other … you click back to the homepage" — and
   "ignore the theme, pave your own road".)

   Structure: the frame's ONLY chrome is the bottom strip (#svAppBar), three
   lanes declared in the skeleton:

     [#dvDoor]   the door you came through — a landing square carrying the
                 room's word. Hover flips it to its opposite colour and it
                 reads "today" (the landing's own mid-move inversion); click
                 goes home. Hidden on home: the rank IS the chrome there.
     [#svAppBody] the room's own facts — plStatus / wbStatus / the rep
                 writer all paint THIS lane and never touch the other two.
     [#dvUtil]   search(⌘K) · bell · settings, moved in by wbCmdWire —
                 same elements, same wiring.

   The 34px top bar and the 26px nav edge are RETIRED: one-row-chrome.css
   and nav-edge.css died with them and this file is their one successor.
   #tabs stays in the DOM as the one place a room is named — visible only
   as THE MAP, a buff sheet summoned by the home strip's "everything" word
   (body.dv-map) or ☰ on narrow, never resident. Inside a room the frame
   names exactly two places: the room, and the way home.

   Palette is the landing's own (home-room.css): tournament green, buff,
   clock-flag red. Tokens are --dv-* on :root (raw values, no theme-scoped
   deps) and every use still carries a fallback — the body-class-gate law:
   an undefined var() paints SVG black. */

:root{
  --dv-pine:#24382d;  --dv-pine-hi:#2b4336;
  --dv-buff:#e9e1cc;  --dv-buff-ink:#efe9d6;
  --dv-ink:#24342b;   --dv-sage:#a9b8a6;  --dv-moss:#5d6b5f;
  --dv-flag:#a8402c;  --dv-flag-lt:#e0906c;
  --dv-strip:#131a15; --dv-strip-line:rgba(233,225,204,.13);
}

/* the retired header stays retired at every width (ported from
   one-row-chrome.css, asserted by plAudit) */
#wbCmd{ display:none !important; }

/* ---- the strip ---------------------------------------------------------
   Scoped on the theme attribute: the strip's old owners (workbench.css's
   22px id rule, graphite-integration's 20px theme rule — both retired)
   taught that a bare #svAppBar loses this fight. Match what you answer. */
:root[data-lab-theme="graphite"] #svAppBar,
#svAppBar{
  height:26px; padding:0 34px 0 0;            /* right lane stays clear of the chat tab */
  background:var(--dv-strip,#131a15);
  border-top:1px solid var(--dv-strip-line,rgba(233,225,204,.13));
  color:var(--dv-sage,#a9b8a6);
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace);
  font-size:10px; letter-spacing:.04em;
}
#svAppBody{
  display:flex; align-items:center; gap:12px; min-width:0; flex:1 1 auto;
  padding-left:12px; overflow:hidden; white-space:nowrap;
}
#svAppBody .svapp-l, #svAppBody .wb-st-l{ display:flex; align-items:center; gap:12px; min-width:0; }
#svAppBody .svapp-r, #svAppBody .wb-st-r{ display:flex; align-items:center; gap:12px; margin-left:auto; }
#svAppBody .svapp-l b, #svAppBody .wb-st-c b{ color:var(--dv-buff,#e9e1cc); font-weight:400; }
#svAppBody .stb-ok{ color:var(--dv-sage,#a9b8a6); }

/* ---- the door chip ---------------------------------------------------- */
#dvDoor{
  flex:none; align-self:stretch; position:relative;
  display:flex; align-items:center;
  margin:0; border:0; border-radius:0; padding:0 16px; cursor:pointer;
  font-family:var(--serif,'Libre Caslon Text',Georgia,serif);
  font-size:10.5px; font-weight:400; letter-spacing:.16em; text-transform:uppercase;
  background:var(--dv-pine,#24382d); color:var(--dv-buff-ink,#efe9d6);
  transition:background-color .15s ease, color .15s ease;
}
#dvDoor[data-tone="lt"]{ background:var(--dv-buff,#e9e1cc); color:var(--dv-ink,#24342b); }
#dvDoor[data-tone="nt"]{ background:#1d241e; color:var(--dv-sage,#a9b8a6); }
/* the flip: the same square, its opposite colour, the word "today" —
   exactly how a landing square reads mid-move */
#dvDoor .dv-h{
  position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  opacity:0; transition:opacity .15s ease;
}
#dvDoor .dv-w{ transition:opacity .15s ease; }
#dvDoor:hover, #dvDoor:focus-visible{
  background:var(--dv-buff,#e9e1cc); color:var(--dv-ink,#24342b);
}
#dvDoor[data-tone="lt"]:hover, #dvDoor[data-tone="lt"]:focus-visible{
  background:var(--dv-pine,#24382d); color:var(--dv-buff-ink,#efe9d6);
}
#dvDoor:hover .dv-w, #dvDoor:focus-visible .dv-w{ opacity:0; }
#dvDoor:hover .dv-h, #dvDoor:focus-visible .dv-h{ opacity:1; }
#dvDoor:focus-visible{ outline:2px solid var(--dv-flag-lt,#e0906c); outline-offset:-2px; }

/* the map door on the home strip — a word, not a button-shape */
.dv-all{
  border:0; background:none; padding:0 2px; cursor:pointer; border-radius:0;
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace);
  font-size:10px; letter-spacing:.08em; color:var(--dv-moss,#5d6b5f);
}
.dv-all:hover, body.dv-map .dv-all{ color:var(--dv-buff,#e9e1cc); }
.dv-all:focus-visible{ outline:2px solid var(--dv-flag-lt,#e0906c); outline-offset:2px; }

/* ---- the utility lane -------------------------------------------------- */
#dvUtil{ flex:none; margin-left:auto; align-self:stretch; display:flex; align-items:stretch; }
/* the lane sizes its buttons — the 44px bell and the gear's pill were
   header-era owners, deleted (chrome-redesign, spec-sync), not out-shouted */
#dvUtil button{
  border:0; border-radius:0; background:none; cursor:pointer;
  height:100%; min-height:0;
  display:flex; align-items:center; gap:5px; padding:0 10px;
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace);
  font-size:9.5px; letter-spacing:.06em; color:var(--dv-moss,#5d6b5f);
}
#dvUtil button:hover{ color:var(--dv-buff,#e9e1cc); background:rgba(233,225,204,.05); }
#dvUtil button:focus-visible{ outline:2px solid var(--dv-flag-lt,#e0906c); outline-offset:-2px; }
#dvUtil #wbSearch kbd{
  font:inherit; padding:0 4px; border:1px solid rgba(233,225,204,.18); border-radius:0;
}
#dvUtil #setBtn .btn-l{ display:none; }     /* title + aria-label carry the word */
#dvUtil svg{ width:13px; height:13px; }
#dvUtil #bellBtn{ position:relative; }
#dvUtil #bellDot{
  position:absolute; top:5px; right:6px; width:5px; height:5px; border-radius:50%;
  background:var(--dv-flag-lt,#e0906c);
}
/* the coverage slot keeps its chrome (ported from one-row-chrome.css) */
#svAppBar [data-slot="cov"] .cov-chip{ gap:6px; }
#svAppBar [data-slot="cov"] .cov-word{ color:var(--dv-sage,#a9b8a6); }

/* ---- the frame without its header row ---------------------------------
   workbench.css owns the grid (rows are minmax(0,1fr) auto now); the strip
   states its own height above. The nav column is width 0 (04h sets
   --wb-left:0) and the edge never renders: */
@media (min-width:1000px){
  body:not(.dv-map) #wbLeft{ display:none; }
}
body:is(.dv-map,.sideopen) #wbBody{ position:relative; }
/* the ☰ backdrop keeps its tap-to-close job but paints nothing: it sits in
   the root stacking context ABOVE the fixed #wb, so any tint it carries
   lands on the sheet too — the sheet's shadow is the depth cue instead */
#sideBk{ background:transparent; }

/* ---- THE MAP — a buff sheet over the room, summoned, never resident ----
   Two summons, one sheet: body.dv-map (the home strip's "everything") and
   body.sideopen (☰ on narrow — same #tabs, same rows, wired in 14). */
body:is(.dv-map,.sideopen) #wbLeft{
  display:block; position:absolute; z-index:60; top:0; bottom:0; left:0;
  width:min(264px, 84vw);
  background:var(--dv-buff,#e9e1cc);
  border-right:1px solid var(--dv-pine,#24382d);
  box-shadow:26px 0 60px rgba(8,14,9,.4);
  overflow-y:auto; padding:10px 0 14px;
}
body:is(.dv-map,.sideopen) #wbLeft #tabs{ display:block; }
body:is(.dv-map,.sideopen) #wbLeft .sg{ margin-top:14px; }
/* the rows and captions themselves are THE TREE ROW CONTRACT
   (tree-rows.css) — declared there and nowhere else; this file owns only
   the sheet the tree renders on */
body:is(.dv-map,.sideopen) #wbLeft #bellBtn,
body:is(.dv-map,.sideopen) #wbLeft #setBtn{ display:none; }
body:is(.dv-map,.sideopen) #wbLeft #loglink{
  display:block; margin-top:16px; padding:8px 14px 0;
  border-top:1px solid rgba(36,56,45,.18);
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace); font-size:9.5px;
  letter-spacing:.06em; color:var(--dv-moss,#5d6b5f); text-decoration:none;
}
body:is(.dv-map,.sideopen) #wbLeft #loglink:hover{ color:var(--dv-flag,#a8402c); }

/* ---- the puzzles door opens the LIGHT room -----------------------------
   The landing's b-square is buff, so the room behind it is buff: the hub is
   a scoresheet, not a console. (pzroom is the puzzles tab's registry cls;
   the .wrap override matches room-bar.css's specificity, which it answers.) */
body.pzroom #wbView{ background:var(--dv-buff,#e9e1cc); scrollbar-gutter:auto; }
:root[data-lab-theme="graphite"] body.pzroom #wbView .wrap{
  /* margin-right answers workbench.css's `#wbView .wrap{margin-right:0
     !important}` — match what you answer, or auto-left eats the whole slack */
  max-width:640px; margin:0 auto !important; padding:8px 24px 0 !important;
}
/* room content — the puzzles hub is the LIGHT room (door-frame.css sets the
   buff ground on body.pzroom): the landing's b-square is buff, and the room
   behind a door is made of its square. Four piles on a scoresheet — Caslon
   words, mono counts, hairline verbs, the clock-flag red as the one warm
   ink. Tokens are the --dv-* doorframe set with per-use fallbacks. */
#tab-puzzles .wrap{ max-width:640px; margin:0 auto; }
.pz-list{ display:flex; flex-direction:column; margin:11vh 0 40px; }
.pz-row{
  display:flex; align-items:baseline; gap:18px; width:100%;
  padding:26px 6px; text-align:left; cursor:pointer;
  background:none; border:0; border-radius:0;
  border-bottom:1px solid rgba(36,56,45,.18);
  font-family:var(--chrome,'Schibsted Grotesk',sans-serif);
  color:var(--dv-ink,#24342b);
}
.pz-row:first-child{ border-top:1px solid rgba(36,56,45,.18); }
.pz-row:hover{ background:rgba(36,56,45,.05); }
.pz-row:focus-visible{ outline:2px solid var(--dv-flag,#a8402c); outline-offset:-2px; }
/* the word is the row — the glyph vocabulary belongs to the map, not here */
.pz-row .pz-g{ display:none; }
.pz-row .pz-b{ flex:1; min-width:0; }
.pz-row .pz-l{
  font-family:var(--serif,'Libre Caslon Text',Georgia,serif);
  font-size:21px; font-weight:400; letter-spacing:.01em;
  color:var(--dv-ink,#24342b);
}
.pz-row .pz-n{
  flex:none; font-family:var(--mono,'Spline Sans Mono',Menlo,monospace);
  font-size:10.5px; letter-spacing:.06em;
  font-variant-numeric:tabular-nums; color:var(--dv-moss,#5d6b5f);
}
.pz-row .pz-acts{ flex:none; display:flex; align-items:center; gap:8px; }
.pz-row .pz-act{
  padding:4px 12px; border-radius:0;
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace); font-size:10.5px;
  letter-spacing:.05em; border:1px solid rgba(36,56,45,.3);
  color:var(--dv-ink,#24342b);
}
.pz-row .pz-act:hover{
  border-color:var(--dv-flag,#a8402c); color:var(--dv-flag,#a8402c);
}
/* the row's own verb — the one you'd press — carries the flag standing */
.pz-row .pz-act.pz-go{
  border-color:var(--dv-flag,#a8402c); color:var(--dv-flag,#a8402c);
}
.pz-row:hover .pz-act.pz-go{
  background:var(--dv-flag,#a8402c); color:var(--dv-buff,#e9e1cc);
}
.pz-empty{ padding:24px 6px; color:var(--dv-moss,#5d6b5f); font-size:13px; }
/* THE OPENING LAB'S DOOR-VOICE DRESS — the home's shared furniture and the
   study room's overlay (2026-08-11 → 2026-08-18).

   Until 2026-08-18 this file dressed THE ONE ROOM (body.labone): a
   workbench study room — 300px lab column, stage board, 330px rail — with
   its own strip, candidates in hairline boxes, a scratch banner, an engine
   pane, a games pane and a drawer. That room is DELETED
   (reports/OPENLAB-INSTRUMENT-2026-08-18.md): the study room is the
   explorer session in repertoire dress on the solve page (13-ot-room over
   13c-explorer; solve-session.css block 4c is its plate, explorer-session
   .css its organs' dress), and body.labone no longer exists. What this
   file states now:
     · the --lr-* palette, declared for BOTH surfaces that read it — the
       home (body.othome, the manage panel's lr-io* markup) and the study
       session (body.lrsession — a body class of the solve page, set by
       13c exOpen({study}) and cleared with the session);
     · the home's manage panel, its bands and its focus ring (unchanged);
     · the study dress's few own classes: the fact line's ribbon (.lr-rb)
       and the flex organ's games rows (.lr-game). Nothing else — the head,
       the sheet, the book and the band are the instrument's. (The reading
       rows — gaps · leaks · due, .lr-drow/.lr-dr/.lr-rdx — died with the
       home's plate, 2026-08-18; 66bb3a7 is the last commit with them.)
   ONE OWNER of `lr-` (tests/css-ownership.test.mjs); Square corners, the
   door voice's own inks (--dv-* reads with raw fallbacks); this file sits
   at the cascade TAIL so the door era answers every older layer. */

/* THE PALETTE SERVES BOTH SURFACES (2026-08-11, re-scoped 2026-08-18). The
   manage panel (`lr-io*`, 13-ot-io) is the HOME's — body.othome — and the
   study session's few classes read the same inks on the solve page's pine
   (body.lrsession). `lr-` has ONE owner, which is this file, so the ink is
   declared for both here rather than restated: one fact, one declaration
   site, TOKEN_OWNERS satisfied. */
body.lrsession, body.othome{
  /* THE GROUND IS THE SOLVE ROOM'S PINE, MEASURED THERE (owner 2026-08-13:
     "the whole page needs to have same theme as puzzles/board"). v1 kept
     the graphite ramp's lightness stops (#131a15) — the very ground
     solve-session.css measured and REJECTED: near-black makes the board's
     own edge the loudest contrast on screen (15.00x, above the 14.61x of
     a black piece on a light square, the strongest thing you actually
     read). Pine puts that edge at 10.60x, under the information peak, and
     holds the board boundary at 3.73x (> WCAG 1.4.11's 3:1). Same board,
     same pine — the measurement carries whole. The ink registers are the
     door voice's own on-pine set (solve's plate, the home's .oh-state):
     buff-ink primary, sage secondary, #7f8d7c quiet, moss quietest.
     (--lr-surface died in this re-ground: declared since v1, read by
     nothing. --lr-surface2 is the lifted ground, --dv-pine-hi's value.) */
  --lr-paper:#24382d; --lr-surface2:#2b4336;
  --lr-line:rgba(233,225,204,.14); --lr-ink:#efe9d6; --lr-ink2:#a9b8a6;
  --lr-mut:#7f8d7c; --lr-mut2:#5d6b5f;
  /* the door voice's own colours (door-frame.css --dv-* kin, carried raw):
     buff is the scoresheet ink — coverage, the current ply, the selected
     state; the flag pair is everything LIVE or OFF-BOOK — due counts,
     gaps, scratch, the armed verb. Sage marks the book's edge. */
  --lr-buff:#e9e1cc; --lr-buff-wash:rgba(233,225,204,.07);
  --lr-flag:#a8402c; --lr-flag-lt:#e0906c; --lr-flag-wash:rgba(224,144,108,.07);
  --lr-sage:#a9b8a6;
}
/* ---- the study dress on the plate (body.lrsession) --------------------
   The instrument (solve-session.css 4c) is the geometry, explorer-session
   .css the organs' dress; these are the four things the study session
   draws that the explorer does not. Type is the plate's (T5): Schibsted
   Grotesk, tabular figures, caps only for figures. */
/* the ribbon in the fact line: covered depth in scoresheet ink over a
   faint buff ground — the home's own measure (lrRibbonSpan), inline
   before the count it depicts */
body.lrsession .lr-rb{
  display:inline-block; position:relative; height:7px; border-radius:0;
  vertical-align:middle; margin-right:9px;
  background:repeating-linear-gradient(90deg,rgba(233,225,204,.14) 0 5px,transparent 5px 7px);
}
body.lrsession .lr-rb .fill{
  position:absolute; top:0; bottom:0; left:0;
  background:repeating-linear-gradient(90deg,var(--lr-buff) 0 5px,transparent 5px 7px);
}
/* the games here (13-ot-games lrGamesRender) — the flex organ with no rail:
   the personal-book counts as small figures in the head, then the rows,
   the rows the organ's own scroller (the plate never scrolls) */
body.lrsession #exGames .lr-gchips{ display:inline-flex; gap:12px; margin-left:auto; text-transform:none; letter-spacing:.02em; }
body.lrsession #exGames .lr-gchips .chip{
  font:11px var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif); color:var(--lr-mut);
  font-variant-numeric:tabular-nums; border:0; padding:0; border-radius:0;
}
body.lrsession #exGames .lr-grows{ flex:1 1 auto; min-height:0; overflow-y:auto; overscroll-behavior:contain; scrollbar-width:thin; }
body.lrsession .lr-game{
  display:flex; align-items:baseline; gap:6px; width:100%; text-align:left;
  border:0; border-bottom:1px solid rgba(233,225,204,.10); background:none;
  cursor:pointer; padding:6px 4px; color:var(--lr-ink2);
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif); font-size:12px;
  font-variant-numeric:tabular-nums; letter-spacing:.02em;
}
body.lrsession .lr-game:hover{ background:rgba(233,225,204,.09); }
body.lrsession .lr-game:hover .w, body.lrsession .lr-game:hover .b{ color:var(--lr-buff); }
body.lrsession .lr-game .vs{ color:var(--lr-mut2); }
body.lrsession .lr-game .sp{ flex:1; }
body.lrsession .lr-game .res, body.lrsession .lr-game .yr{ font-size:11px; color:var(--lr-mut); }
/* the elo figure rides between the names and the result — the dimmest ink
   on the row, a number you scan past unless you are picking by strength */
body.lrsession .lr-game .el{ font-size:11px; color:var(--lr-mut2); }

/* segments: square hairline groups; the lit cell is buff, never a pill —
   the manage panel's dials (13-ot-io lrIoReps / lrIoOpp), on the home.
   (Interactive hairlines through this file stepped up with the pine
   ground, 2026-08-13: the same buff alpha reads a step fainter on pine
   than on near-black — .16 blends to 3.0x over #131a15 but 2.1x over
   pine — so they take solve's own weights: .22 quiet controls, .28
   answer chips, matching the door block in engine-pane.css.) */
body.othome .lr-cpick{
  display:flex; border:1px solid rgba(233,225,204,.22); border-radius:0; overflow:hidden;
}
body.othome .lr-col{
  border:0; border-radius:0; background:none; cursor:pointer; padding:3px 10px;
  font:10.5px 'Spline Sans Mono',ui-monospace,monospace; color:var(--lr-mut); letter-spacing:.02em;
  white-space:nowrap;
}
body.othome .lr-col:hover{ color:var(--lr-ink2); }
body.othome .lr-col.on{
  background:var(--lr-buff-wash); color:var(--lr-buff);
}

/* ---- the home's verbs: CELLS of the solve band (owner, 2026-08-13 second
   pass: "the border of the buttons is way different … just take their
   theme directly and make these buttons same") ----
   Solve ships exactly two button forms — the band CELL and the borderless
   ghost — and this voice uses only those. Every `.lr-big` stands in a
   band (the `.lr-band` list AFTER the io rules, so the bands out-order
   .lr-io-row's own gap); this block is the cell: no box of its own, a .26
   divider on its right, filled only by the hover inversion, the armed
   cell's ink the flag-light. --dv-* names are reads of the door voice's
   tokens (door-frame.css declares; reads are legal) with raw fallbacks. */
body.othome .lr-big{
  flex:1 1 auto; min-width:0; height:100%;
  border:0; border-right:1px solid rgba(233,225,204,.26); border-radius:0;
  background:none; color:var(--dv-buff-ink,#efe9d6); cursor:pointer;
  padding:0 12px;
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:12px; font-weight:500; letter-spacing:.1em; line-height:1;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  transition:color .15s ease, border-color .15s ease, background-color .15s ease;
}
body.othome .lr-big:last-child{ border-right:0; }
/* in a band the inversion is the only hover a cell can show */
body.othome .lr-big:hover{
  background:var(--dv-flag,#a8402c); color:#f2e8d8; border-color:transparent;
}
body.othome .lr-big.lr-go{ color:var(--lr-flag-lt); }
body.othome .lr-big.lr-go:hover{
  background:var(--lr-flag); color:#f2e8d8;
}
/* the quiet verb: the ghost. BASE is the in-prose word (the recovery
   offers live inside a sentence — a cell there would break the line);
   the band-scoped cell form rides with the bands below. */
body.othome .lr-ghost{
  border:0; background:none; cursor:pointer; text-align:left; border-radius:0;
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:12px; font-weight:500; letter-spacing:.1em; line-height:1;
  color:var(--dv-moss,#5d6b5f); padding:11px 2px;
}
body.othome .lr-ghost:hover{ color:var(--dv-buff,#e9e1cc); }

/* ---- the io panel (13-ot-io): summoned by `manage`, never resident ----
   Paste PGN, import/export, the two session dials, recovery. Same page-
   section anatomy as every other card; inputs keep the shared writing
   voice (house-voice owns fields), the verbs are the room's own. */
body.othome .lr-io[hidden]{ display:none; }
/* (.lr-io-verbs takes the band form — THE BANDS block below) */
body.othome .lr-io-row{ display:flex; align-items:center; gap:10px; margin-top:10px; }
body.othome .lr-io textarea{
  width:100%; box-sizing:border-box; margin-top:12px; resize:vertical;
  background:rgba(233,225,204,.04); color:var(--lr-ink);
  border:1px solid rgba(233,225,204,.22); border-radius:0;
  font:12px 'Spline Sans Mono',ui-monospace,monospace; line-height:1.5; padding:8px;
}
body.othome .lr-io-lbl{
  font:10.5px 'Spline Sans Mono',ui-monospace,monospace; color:var(--lr-mut);
  letter-spacing:.02em;
}
body.othome .lr-io-lbl input{
  width:3.2em; background:rgba(233,225,204,.04); color:var(--lr-ink);
  border:1px solid rgba(233,225,204,.22); border-radius:0; font:inherit; padding:2px 4px;
}
body.othome .lr-io-meter{
  font:10.5px 'Spline Sans Mono',ui-monospace,monospace; color:var(--lr-mut);
  margin-left:auto; text-align:right;
}
body.othome .lr-io-meter b{ color:var(--lr-buff); }
body.othome .lr-io-msg{ font:11px 'Spline Sans Mono',ui-monospace,monospace; margin-top:8px; min-height:1.1em; }
body.othome .lr-io-msg em.ok{ color:var(--lr-sage); font-style:normal; }
body.othome .lr-io-msg em.bad{ color:var(--lr-flag-lt); font-style:normal; }
body.othome .lr-io-set{ display:flex; align-items:center; justify-content:space-between; gap:10px; margin-top:12px; }
body.othome .lr-io-bak{
  margin-top:12px; padding:10px 12px; font-size:12px; color:var(--lr-ink2);
  border:1px dashed rgba(224,144,108,.5); background:rgba(224,144,108,.06);
}
body.othome .lr-io-bak b{ color:var(--lr-flag-lt); font-weight:400; }
body.othome .lr-io-bak{ margin:12px 16px 0; }
body.othome .lr-io .lr-io-bak{ margin:12px 0 0; }

/* ---- THE BANDS: the solve plate's verb band, taken whole ---------------
   solve-session.css §4 is the reference; the cells are the .lr-big block
   above. Every verb row on the home is one of these: the manage panel's
   verb row and its pgn go/cancel row (13-ot-io), and the empty state's
   three ways in. Placed AFTER the io rules so .lr-io-row's own gap and
   margin lose to the band on ORDER, the way css is supposed to work — not
   on a shout. Solve's band has no bottom rule because the viewport closes
   it; these float, so they close themselves. */
body.othome .lr-band, body.othome .lr-io-verbs, body.othome .lr-io-empty{
  display:flex; flex-wrap:nowrap; gap:0; align-items:stretch;
  height:60px; padding:0;
  background:var(--dv-pine-hi,#2b4336);
  border-top:1px solid rgba(233,225,204,.34);
  border-bottom:1px solid rgba(233,225,204,.34);
}
body.othome .lr-io-row.lr-band{ margin-top:12px; }
body.othome .lr-io-empty{ margin:10px 16px 0; }
body.othome .lr-io .lr-io-empty{ margin:10px 0 0; }
/* the ghost as a CELL when it stands in a band (the pgn row's cancel) —
   the base above keeps it an in-prose word everywhere else */
body.othome .lr-band .lr-ghost{
  flex:0 0 auto; height:100%; padding:0 20px; text-align:center;
}

/* ---- shared idle voice + keyboard focus (the door's flag outline) ---- */
body.othome .lr-idle{ font-size:12px; color:var(--lr-mut); margin:4px 0; }
/* the focus ring roster: the home's three manage-panel surfaces; the
   study session's games rows */
body.othome :is(.lr-big, .lr-ghost, .lr-col):focus-visible,
body.lrsession .lr-game:focus-visible{
  outline:2px solid var(--lr-flag-lt); outline-offset:-2px;
}

/* ---- narrow: LAST in the layer (a media query adds no specificity) ---- */
@media (max-width:1000px){
  /* the bands wrap at the strip's scale — solve's own narrow recipe:
     cells fix at 44px, the band carries one row or two with air around
     them */
  body.othome .lr-band, body.othome .lr-io-verbs, body.othome .lr-io-empty{
    height:auto; min-height:46px; flex-wrap:wrap; align-content:center;
  }
  body.othome .lr-big{ height:44px; }
  body.othome .lr-band .lr-ghost{ height:44px; }
}
/* ====== THE OPENING LAB HOME — #openings, the no-board room ==============
   (owner, 2026-08-11: "take away the board from the #openings landing page,
   and represent current repertoire in a much more elegant way … like our
   landing page theme."; owner, 2026-08-18: "we need to be able to just
   catalog the openings in our repertoire … najdorf should be under
   sicilian, and diff lines of the najdorf inside the najdorf … forget the
   %, due, gaps")

   The openings tab's one view is this home; `#openings/board` (otView's
   `board`) is the study room, a SESSION on the solve page since 2026-08-18
   — the explorer session in repertoire dress (13-ot-room over 13c;
   openings-room.css keeps its few own classes under body.lrsession). A
   view flip is a hash flip, so both are deep-linkable and neither module
   owns the other's state.

   THE FORM IS TWO ADJACENT SQUARES OF A BOARD, full bleed, meeting with NO
   hairline — the landing's own grammar (home-room.css), turned from three
   doors into one room's two halves — and since 2026-08-18 the two halves
   are a book's TITLE PAGE and its CONTENTS:

     [ PINE ]  the title page. The landing's plate exactly — a monumental
               WORD (here the volume: WHITE / BLACK, the live one in ink,
               and it IS the colour switch), one italic line under it (how
               big the book is), the verbs in the solve band, and a
               monumental piece cropped at the edge, wearing YOUR colour.
     [ BUFF ]  the contents. Openings as chapters (Caslon, a rule above
               each), variations as sections beneath, the lines at the
               bottom as mono scoresheet fragments — every heading carries
               the moves that reach it from its parent, every line the
               moves from where it parts from its neighbours; the ECO code
               hangs right as the folio. Indent is the depth (--d), never a
               box: rows are never boxed in this voice.

   The plate — coverage as the word, due/gaps/leaks as facts, the coverage
   ribbon under every row, the recent/due sort — retired 2026-08-18; git
   history keeps it (66bb3a7 is the last commit with it).

   Board-first law (2026-08-10): this room has NO board, so it must have no
   board at all — 31-ot-home calls wbPreview(null), which nulls WB.board
   (the stage hides) and WB.posKey (the rail's one openings pane goes quiet,
   so the frame goes wb-norail and the two squares take the whole view).

   Tokens are --oh-* so nothing shadows --lr-* (the room's) or the site's
   --ink family. Palette law: this layer is gated on a BODY CLASS, not the
   theme attribute, so every font/colour var carries its own fallback — an
   undefined var() paints SVG black. The `lr-io` panel that lives on this
   page keeps its own ink: `lr-` has ONE owner and it is openings-room.css,
   which declares the palette for both views. */

body.othome #wbView{
  overflow:hidden; padding:0 !important; scrollbar-gutter:auto; border-right:0;
}
body.othome #tab-openings{ display:flex; height:100%; min-height:0; }
/* the study room's column is built lazily by 13-ot-room and hidden by it on
   this view; nothing else from the openings shell renders here */

#ohHome{
  /* the landing's own material, carried raw (home-room.css --hl-* kin) */
  --oh-pine:#24382d;
  --oh-pine-ink:#efe9d6;
  --oh-pine-mut:#a9b8a6;
  --oh-pine-mut2:#7f8d7c;
  --oh-pine-flag:#e0906c;
  --oh-buff:#e9e1cc;
  --oh-buff-ink:#24342b;
  --oh-buff-mut:#5d6b5f;
  --oh-buff-flag:#a8402c;
  --oh-rule:rgba(36,56,45,.18);
  /* the contents' measure: the written area's left margin and one indent */
  --oh-x:34px;
  --oh-in:22px;
  flex:1; min-width:0; min-height:0;
  display:grid; grid-template-columns:minmax(320px, 37%) minmax(0,1fr);
}

/* ---- the pine square: the title page ------------------------------------
   container-type:size so the word's type scales to the SQUARE, not the
   viewport — the landing's trick, and what keeps the word monumental at
   every frame width without a media query per step. */
.oh-state{
  position:relative; overflow:hidden; container-type:size;
  background:var(--oh-pine,#24382d); color:var(--oh-pine-ink,#efe9d6);
  display:flex; flex-direction:column;
  /* NOT cq units: this element IS the query container, so cqi/cqh in its
     own padding is self-referential — the browser resolved 1cqi to 2.09px
     instead of ~4 and every cq-sized descendant came out half scale. The
     container's own box must be stated in units that do not depend on it. */
  padding:42px clamp(22px, 7%, 54px);
}

/* the word IS the switch: the landing's .hl-word grammar (Caslon, caps on
   .12em, nowrap) set twice, stacked — the volume you are reading in ink,
   the other dim; either is a button. Left-set and TOP-set, exactly the
   landing's composition: the word owns the top of the square and the piece
   owns the bottom-right corner, so the two never compete for the same
   ground (a centred plate collided with the piece the first time this was
   built). */
.oh-pick{
  display:flex; flex-direction:column; align-items:flex-start; gap:.16em;
  flex:none; margin-top:4.5cqh;
}
.oh-pick button{
  border:0; background:none; padding:0; cursor:pointer; border-radius:0;
  font-family:var(--serif,'Libre Caslon Text',Georgia,serif);
  font-weight:400; font-size:clamp(28px, 12cqi, 58px);
  letter-spacing:.12em; text-transform:uppercase; line-height:1.04;
  white-space:nowrap; text-align:left;
  color:var(--oh-pine-mut2,#7f8d7c);
  transition:color .15s ease;
}
.oh-pick button:hover{ color:var(--oh-pine-mut,#a9b8a6); }
.oh-pick button.on{ color:var(--oh-pine-ink,#efe9d6); }
/* the live volume is underlined in its own ink — the scoresheet's way of
   marking which column you are writing in */
.oh-pick button.on::after{
  content:""; display:block; height:1px; margin-top:.14em;
  background:var(--oh-pine-ink,#efe9d6);
}
/* the italic line: the landing's .hl-line — how big the book is. EMPTY SAYS
   NOTHING: no lines, no line (31-ot-home). */
.oh-line{
  margin-top:1.4em; max-width:26ch;
  font-family:var(--serif,'Libre Caslon Text',Georgia,serif);
  font-style:italic; font-size:clamp(13px, 3.5cqi, 16px); line-height:1.5;
  color:var(--oh-pine-mut,#a9b8a6);
}

/* the verbs: THE SOLVE BAND, taken whole (owner, 2026-08-13 second pass:
   "the border of the buttons is way different … just take their theme
   directly and make these buttons same"). A verb is never a boxed word in
   this voice — solve ships exactly two button forms, the band CELL and
   the borderless ghost, so this row IS the band: solve-session.css §4's
   materials verbatim — the lifted pine ground, a .34 rule top and bottom
   (solve's own band omits the bottom only because the viewport closes
   it), cells divided by .26 hairlines, filled only by the hover
   inversion, the armed cell's ink the flag-light. The --dv-* names are
   READS of the door voice's tokens (one declarer, door-frame.css; reads
   are always legal) with raw fallbacks per the palette law. */
/* the verbs ride directly under the word and its line, NOT on the floor:
   the floor belongs to the piece, and a bottom-set verb row is what kept
   colliding with it. This is the landing's own split — words up, piece
   down. */
.oh-verbs{
  display:flex; flex-wrap:nowrap; gap:0; align-items:stretch; flex:none;
  height:60px; margin-top:34px; max-width:100%;
  background:var(--dv-pine-hi,#2b4336);
  border-top:1px solid rgba(233,225,204,.34);
  border-bottom:1px solid rgba(233,225,204,.34);
}
.oh-verb{
  flex:1 1 auto; min-width:0; height:100%;
  border:0; border-right:1px solid rgba(233,225,204,.26); border-radius:0;
  background:none; color:var(--dv-buff-ink,#efe9d6); cursor:pointer;
  padding:0 12px;
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:12px; font-weight:500; letter-spacing:.1em; line-height:1;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  transition:color .15s ease, border-color .15s ease, background-color .15s ease;
}
.oh-verbs > :last-child{ border-right:0; }
/* in a band the inversion is the only hover a cell can show — there is no
   hairline of its own left to warm (solve's own comment, same rule) */
.oh-verb:hover{ background:var(--dv-flag,#a8402c); color:#f2e8d8; border-color:transparent; }
.oh-verb.oh-go{ color:var(--dv-flag-lt,#e0906c); }
.oh-verb.oh-go:hover{ background:var(--dv-flag,#a8402c); color:#f2e8d8; }
/* the quiet cell — the solve band's retreat: moss, its own width, never
   filled, not even on hover */
.oh-ghost{
  flex:0 0 auto; height:100%;
  border:0; border-radius:0; background:none; cursor:pointer;
  padding:0 20px;
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:12px; font-weight:500; letter-spacing:.1em; line-height:1;
  color:var(--dv-moss,#5d6b5f);
}
.oh-ghost:hover{ background:none; color:var(--dv-buff,#e9e1cc); }

/* the piece: monumental, cropped by the square's right edge like a demo
   board piece set down half off the table. It wears YOUR colour — the side
   you are training — so the colour pick flips it, which is the landing's
   own mid-move inversion made to mean something. */
/* the crop is deliberately past BOTH edges: a 45-box glyph carries air
   around its mass, so a piece that merely touches the edge reads as a small
   picture with a margin. The landing's own numbers are the reference. */
.oh-pc{
  /* percentages of the panel, not cq units — one less thing that can go
     circular, and the piece is meant to scale with its square anyway. It
     owns the floor of the panel; the word and verbs own the top. */
  position:absolute; right:-18%; bottom:-14%;
  width:86%; height:auto; aspect-ratio:1;
  pointer-events:none; z-index:0;
}
/* the word/line/verbs stack ABOVE the piece. Named EXPLICITLY, never as
   `.oh-state > *`: that blanket carries the same specificity as .oh-pc and
   .oh-file and sits later in this file, so it won the `position` cascade and
   turned both absolutely-positioned children back into flex ITEMS — the
   piece got shrunk to 51px of a 322px box and the file letter marched into
   the column under the verbs. Both looked like sizing bugs; both were
   layout-mode bugs. A `:not()` patch would have to grow a name every time
   this panel gains a child, so the positive list is the honest form. */
.oh-state > .oh-pick,
.oh-state > .oh-line,
.oh-state > .oh-verbs{ position:relative; z-index:1; }
/* the coordinate, set exactly as the board sets its own */
.oh-file{
  position:absolute; left:13px; bottom:9px; z-index:1;
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace);
  font-size:11px; color:var(--oh-pine-mut2,#7f8d7c);
}

/* ---- the buff square: the contents ------------------------------------ */
.oh-sheet{
  position:relative; min-width:0; min-height:0; overflow-y:auto;
  background:var(--oh-buff,#e9e1cc); color:var(--oh-buff-ink,#24342b);
  padding:5.5cqh 0 40px;
}
/* THE WRITTEN AREA, not the paper. The buff square stays full bleed, but a
   contents page's rules span what is written on them: at 1000px of sheet a
   name and its folio ended up ~700px apart and stopped reading as one
   row. The hairlines therefore stop at a measure, left-set. */
.oh-sheeth, .oh-rows{ max-width:940px; }
.oh-sheeth{
  display:flex; align-items:baseline; justify-content:space-between; gap:12px;
  padding:0 var(--oh-x,34px) 12px;
}
.oh-sheeth h2{
  margin:0; font-family:var(--serif,'Libre Caslon Text',Georgia,serif);
  font-style:italic; font-weight:400; font-size:19px; letter-spacing:0;
  color:var(--oh-buff-ink,#24342b);
}

/* THE ROW, in every role: one flex line — name, then the moves taking what
   is left (ellipsed, never wrapped: a truncated line is still a line and
   the whole of it rides the tooltip), then the folio hanging right. Depth
   is an indent (--d, set by 31-ot-home), never a box or a rule: within a
   chapter the page uses air, and the one hairline is the chapter's own. */
.oh-h, .oh-row{
  display:flex; align-items:baseline; gap:12px; width:100%; text-align:left;
  cursor:pointer; background:none; border:0; border-radius:0;
  padding:5px var(--oh-x,34px) 5px calc(var(--oh-x,34px) + var(--d,0) * var(--oh-in,22px));
  transition:background-color .12s ease;
}
.oh-h:hover, .oh-row:hover{ background:rgba(36,56,45,.05); }
.oh-h:focus-visible, .oh-row:focus-visible{ outline:2px solid var(--oh-buff-flag,#a8402c); outline-offset:-2px; }
/* the name: Caslon, in ink; a heading's hover warms it to the flag — the
   sign that the row is a door (the chapter's door is the fold; a
   section's is the board at its position; a line's is the line) */
.oh-nm{
  flex:none; min-width:0; max-width:60%;
  font-family:var(--serif,'Libre Caslon Text',Georgia,serif);
  line-height:1.25; color:var(--oh-buff-ink,#24342b);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  transition:color .12s ease;
}
.oh-h:hover .oh-nm, .oh-one:hover .oh-nm{ color:var(--oh-buff-flag,#a8402c); }
/* the moves: mono, figurines. On a heading and on a named line they are
   the quiet part (muted); on a bare line they ARE the line (ink). */
.oh-mv, .oh-row .mv{
  flex:1 1 auto; min-width:0;
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace);
  font-size:11.5px; letter-spacing:.01em; line-height:1.4;
  color:var(--oh-buff-mut,#5d6b5f);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  font-variant-numeric:tabular-nums lining-nums;
}
.oh-row .mv{ font-size:12.5px; color:var(--oh-buff-ink,#24342b); }
.oh-row.oh-one .mv{ font-size:11.5px; color:var(--oh-buff-mut,#5d6b5f); }
/* the folio: ECO, mono caps figures hanging right; a folded chapter's
   count rides beside it */
.oh-fig{
  display:flex; align-items:baseline; gap:12px; flex:none; margin-left:auto;
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace);
  font-size:10.5px; letter-spacing:.05em; color:var(--oh-buff-mut,#5d6b5f);
  font-variant-numeric:tabular-nums lining-nums;
}
.oh-fig:empty{ display:none; }
/* the levels: chapter (a rule above, the caret, the biggest name), section,
   subsection — type steps down, the indent steps in */
.oh-fam{ padding:0; border:0; border-top:1px solid var(--oh-rule,rgba(36,56,45,.18)); }
.oh-fam:last-child, .oh-rows > .oh-row:last-child{ border-bottom:1px solid var(--oh-rule,rgba(36,56,45,.18)); }
.oh-h1{ padding-top:15px; padding-bottom:9px; }
.oh-h1 .oh-nm{ font-size:21px; }
.oh-h2{ padding-top:9px; padding-bottom:5px; }
.oh-h2 .oh-nm{ font-size:17px; }
.oh-h3, .oh-h4{ padding-top:7px; padding-bottom:4px; }
.oh-h3 .oh-nm, .oh-h4 .oh-nm{ font-size:15.5px; }
.oh-fam > .oh-body{ padding-bottom:12px; }
/* the caret: a chevron in the rule's own ink, down when the chapter is
   open, right when folded — drawn, not a glyph, so it sits on the name's
   baseline at every size */
.oh-car{
  flex:none; display:inline-block; width:7px; height:7px; margin-right:-2px;
  border-right:1px solid var(--oh-buff-mut,#5d6b5f);
  border-bottom:1px solid var(--oh-buff-mut,#5d6b5f);
  transform:translateY(-4px) rotate(45deg);
  transition:transform .15s ease;
}
.oh-fam.fold .oh-car{ transform:translateY(-3px) rotate(-45deg); }
.oh-fam.fold > .oh-body{ display:none; }
/* the delete verb: the row's own ✕, shown on hover as the flat sheet showed it */
.oh-row .del{
  flex:none; visibility:hidden; border:0; background:none; cursor:pointer; padding:1px 4px;
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace);
  font-size:11px; color:var(--oh-buff-mut,#5d6b5f); border-radius:0;
}
.oh-row:hover .del{ visibility:visible; }
.oh-row .del:hover{ color:var(--oh-buff-flag,#a8402c); background:rgba(168,64,44,.1); }
/* the ECO table not yet landed: bare lines at the root, one hairline apart */
.oh-rows > .oh-row{ border-top:1px solid var(--oh-rule,rgba(36,56,45,.18)); padding-top:9px; padding-bottom:9px; }

/* the empty sheet: three ways in, as the SAME pine band set down on the
   buff square — the manage panel below is the precedent (summoned dark
   material on the sheet), and one band everywhere is the whole point of
   the owner's second pass. Cells identical to the pine square's. */
.oh-empty{ padding:6px var(--oh-x,34px) 0; }
.oh-empty p{
  margin:0 0 16px; font-family:var(--serif,'Libre Caslon Text',Georgia,serif);
  font-style:italic; font-size:15px; color:var(--oh-buff-mut,#5d6b5f);
}
.oh-ways{
  display:flex; flex-wrap:nowrap; gap:0; align-items:stretch;
  height:60px; max-width:640px;
  background:var(--dv-pine-hi,#2b4336);
  border-top:1px solid rgba(233,225,204,.34);
  border-bottom:1px solid rgba(233,225,204,.34);
}
.oh-way{
  flex:1 1 auto; min-width:0; height:100%;
  border:0; border-right:1px solid rgba(233,225,204,.26); border-radius:0;
  background:none; color:var(--dv-buff-ink,#efe9d6); cursor:pointer;
  padding:0 12px;
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:12px; font-weight:500; letter-spacing:.1em; line-height:1;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  transition:color .15s ease, border-color .15s ease, background-color .15s ease;
}
.oh-ways > :last-child{ border-right:0; }
.oh-way:hover{ background:var(--dv-flag,#a8402c); color:#f2e8d8; border-color:transparent; }
.oh-way.oh-go{ color:var(--dv-flag-lt,#e0906c); }
.oh-way.oh-go:hover{ background:var(--dv-flag,#a8402c); color:#f2e8d8; }

/* THE MANAGE PANEL IS A PINE SQUARE ON THE CONTENTS PAGE. It is an `lr-`
   surface with ONE owner (openings-room.css), and that owner's ink is a
   DARK-room palette — buff verbs, buff-alpha hairlines. Dropped straight
   onto the buff sheet those verbs computed sage-on-buff and vanished. So
   this file gives the panel the ground its ink was drawn for: the board's
   other square, full bleed across the sheet, which is also how it reads —
   summoned material rather than a form pasted onto the page. */
.oh-io{
  margin:26px 0 0; padding:22px var(--oh-x,34px) 28px;
  background:var(--oh-pine,#24382d); color:var(--oh-pine-ink,#efe9d6);
}
.oh-io[hidden]{ display:none; }

/* one orchestrated arrival — the landing's, at the same easing; never for
   reduced motion */
@media (prefers-reduced-motion: no-preference){
  .oh-pc{ animation:oh-rise .7s cubic-bezier(.22,.9,.3,1) backwards; animation-delay:.05s; }
  .oh-pick, .oh-line{ animation:oh-fade .55s ease backwards; animation-delay:.12s; }
  .oh-verbs{ animation:oh-fade .55s ease backwards; animation-delay:.20s; }
  .oh-sheet{ animation:oh-fade .55s ease backwards; animation-delay:.16s; }
}
@keyframes oh-rise{ from{ transform:translateY(7cqh); opacity:0; } }
@keyframes oh-fade{ from{ opacity:0; } }

/* ---- narrow: the two squares stack, pine over buff (LAST in the layer —
   a media query adds no specificity, so it must follow every rule it
   answers; the room's own narrow block learned this the hard way) ---- */
@media (max-width:860px){
  body.othome #wbView{ overflow:auto; }
  #ohHome{ grid-template-columns:1fr; grid-template-rows:auto auto; --oh-x:22px; --oh-in:16px; }
  /* inline-size containment only: a stacked band has no fixed block size, so
     cqh cannot resolve here and every vertical measure below is vh/px */
  .oh-state{ container-type:inline-size; padding:44px 22px 30px; }
  .oh-pick{ margin-top:0; }
  .oh-pick button{ font-size:clamp(28px, 9cqi, 44px); }
  .oh-line{ font-size:15px; }
  /* margin-top:auto has nothing to push against in an auto-height band and
     collapses to 0, which jammed the verbs into the facts row.
     TWO ROWS, FIXED — solve's own narrow band recipe: the band's height is
     the invariant, cells wrap inside it at 44px and the band carries one
     row or two with air around it (align-content:center, not stretch). */
  .oh-verbs{
    margin-top:28px; max-width:100%;
    height:88px; flex-wrap:wrap; align-content:center;
  }
  .oh-verb{ flex:1 1 auto; height:44px; padding:0 10px; }
  .oh-ghost{ height:44px; padding:0 12px; }
  .oh-ways{ height:88px; flex-wrap:wrap; align-content:center; max-width:100%; }
  .oh-way{ flex:1 1 auto; height:44px; padding:0 10px; }
  /* the piece takes the right-edge crop the landing's stacked rows take */
  .oh-pc{ right:-8vw; bottom:-3vh; width:min(48vw, 190px); }
  .oh-sheet{ overflow-y:visible; padding:26px 0 40px; }
  /* a chapter's name and folio keep the first line on a phone; its moves
     step under the name (order:1 sends them to the wrapped line, the folio
     stays beside the name) */
  .oh-h1{ flex-wrap:wrap; }
  .oh-h1 .oh-nm{ font-size:19px; max-width:70%; }
  .oh-h1 .oh-mv{ order:1; flex-basis:100%; padding-left:19px; }
  .oh-nm{ max-width:70%; }
  .oh-empty, .oh-io{ margin-left:0; margin-right:0; }
}
/* ====== ESPORTS WORLD CUP 2026 — #ewc, the tournament room (body.ewcroom)
   (owner, 2026-08-17: "a section … that's just a database of the EWC 2026
   games … visually stunning database")

   THE FORM IS THE OPENINGS HOME'S (openings-home.css): two adjacent squares
   of a board, full bleed, no hairline between —
     [ PINE ]  the state of the event: the champion as the monumental word,
               one italic line under it, mono facts in the clock-flag red,
               the verbs band, the podium as three scoresheet lines, and a
               monumental king cropped at the edge.
     [ BUFF ]  the sheet: a stage's bracket as match cards (Caslon names,
               mono scores, a pill per game), the standings, or every game
               as one scoresheet.

   ONE BUTTON VOICE, restated here as this file's own classes (the guard is
   single ownership per prefix, tests/css-ownership.test.mjs): the verbs are
   the BAND — the lifted pine ground, .34 rules, .26 dividers, an open cell,
   red inversion on hover, the armed cell flag-light — and the quiet cell is
   the borderless moss GHOST. No filled slab at rest anywhere; rows are
   never boxed; a game PILL is a mono figure on a hairline, not a badge.

   Board-first law: no board in this room, none at all (13i calls
   wbPreview(null)). Palette law: gated on a BODY CLASS, so every var()
   carries its fallback. Tokens are READS of the door voice's --dv-* set
   (one declarer, door-frame.css) plus raw values. */

body.ewcroom #wbView{
  overflow:hidden; padding:0 !important; scrollbar-gutter:auto; border-right:0;
}
body.ewcroom #tab-ewc{ display:flex; height:100%; min-height:0; }
#ewcRoom{
  --ewc-rule:rgba(36,56,45,.18);
  --ewc-rule2:rgba(36,56,45,.32);
  flex:1; min-width:0; min-height:0;
  display:grid; grid-template-columns:minmax(320px, 36%) minmax(0,1fr);
}

/* ---- the pine square: the state ---------------------------------------- */
.ewc-state{
  position:relative; overflow:hidden; container-type:size;
  background:var(--dv-pine,#24382d); color:var(--dv-buff-ink,#efe9d6);
  display:flex; flex-direction:column;
  padding:42px clamp(22px, 7%, 54px);
}
.ewc-eyebrow{
  flex:none; font-family:var(--mono,'Spline Sans Mono',Menlo,monospace);
  font-size:10.5px; letter-spacing:.16em; text-transform:uppercase;
  color:var(--dv-sage,#a9b8a6);
}
.ewc-plate{ margin-top:4.5cqh; display:flex; flex-direction:column; align-items:flex-start; flex:none; }
.ewc-word{
  font-family:var(--serif,'Libre Caslon Text',Georgia,serif);
  font-weight:400; font-size:clamp(44px, 20cqi, 112px); line-height:.94;
  letter-spacing:.005em; color:var(--dv-buff-ink,#efe9d6);
}
.ewc-line{
  margin:.9em 0 0; max-width:34ch;
  font-family:var(--serif,'Libre Caslon Text',Georgia,serif);
  font-style:italic; font-size:clamp(13px, 3.4cqi, 16px); line-height:1.5;
  color:var(--dv-sage,#a9b8a6);
}
.ewc-facts{ display:flex; flex-wrap:wrap; gap:0 14px; margin-top:1.6em; }
.ewc-fact{
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace);
  font-size:clamp(10.5px, 2.5cqi, 12px); letter-spacing:.14em;
  text-transform:uppercase; color:var(--dv-flag-lt,#e0906c);
  font-variant-numeric:tabular-nums lining-nums;
}
.ewc-idle{
  margin-top:2em; font-family:var(--serif,'Libre Caslon Text',Georgia,serif);
  font-style:italic; font-size:15px; color:var(--dv-sage,#a9b8a6);
}

/* the verbs — THE BAND, solve-session.css §4's materials verbatim */
.ewc-verbs{
  display:flex; flex-wrap:nowrap; gap:0; align-items:stretch; flex:none;
  height:52px; margin-top:28px; max-width:100%;
  background:var(--dv-pine-hi,#2b4336);
  border-top:1px solid rgba(233,225,204,.34);
  border-bottom:1px solid rgba(233,225,204,.34);
}
.ewc-verb{
  flex:1 1 auto; min-width:0; height:100%;
  border:0; border-right:1px solid rgba(233,225,204,.26); border-radius:0;
  background:none; color:var(--dv-buff-ink,#efe9d6); cursor:pointer;
  padding:0 4px;
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:11px; font-weight:500; letter-spacing:.03em; line-height:1;
  white-space:nowrap; overflow:hidden; text-overflow:clip;
  transition:color .15s ease, border-color .15s ease, background-color .15s ease;
}
.ewc-verbs > :last-child{ border-right:0; }
.ewc-verb:hover{ background:var(--dv-flag,#a8402c); color:#f2e8d8; border-color:transparent; }
.ewc-verb.ewc-go{ color:var(--dv-flag-lt,#e0906c); }
.ewc-verb.ewc-go:hover{ background:var(--dv-flag,#a8402c); color:#f2e8d8; }
.ewc-verb:focus-visible{ outline:2px solid var(--dv-flag-lt,#e0906c); outline-offset:-2px; }

/* the podium: three scoresheet lines on the pine — place, name, team, prize.
   It rides between the plate and the band; the floor below the band is the
   piece's (the landing's split — words up, piece down). */
.ewc-podium{ margin-top:24px; flex:none; position:relative; z-index:1; max-width:520px; }
.ewc-pod{
  display:grid; grid-template-columns:22px minmax(0,1fr) auto auto; gap:0 14px;
  align-items:baseline; padding:9px 0;
  border-bottom:1px solid rgba(233,225,204,.16);
}
.ewc-pod:first-child{ border-top:1px solid rgba(233,225,204,.16); }
.ewc-pod i{
  font-style:normal; font-family:var(--mono,'Spline Sans Mono',Menlo,monospace);
  font-size:11px; color:var(--dv-flag-lt,#e0906c); font-variant-numeric:tabular-nums;
}
.ewc-podname{
  border:0; background:none; padding:0; cursor:pointer; border-radius:0; text-align:left;
  font-family:var(--serif,'Libre Caslon Text',Georgia,serif); font-size:16px;
  color:var(--dv-buff-ink,#efe9d6); white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  min-width:0;
}
.ewc-podname:hover{ color:var(--dv-flag-lt,#e0906c); }
.ewc-podteam, .ewc-podprize{
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace); font-size:10.5px;
  letter-spacing:.04em; color:var(--dv-sage,#a9b8a6); white-space:nowrap;
  font-variant-numeric:tabular-nums;
}
.ewc-podprize{ color:var(--dv-buff-ink,#efe9d6); }

/* the piece: the champion's king, monumental, cropped past both edges */
.ewc-pc{
  position:absolute; right:-16%; bottom:-16%;
  width:70%; height:auto; aspect-ratio:1;
  pointer-events:none; z-index:0; opacity:.92;
}
.ewc-state > .ewc-eyebrow, .ewc-state > .ewc-plate,
.ewc-state > .ewc-verbs{ position:relative; z-index:1; }
.ewc-file{
  position:absolute; left:13px; bottom:9px; z-index:1;
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace);
  font-size:11px; color:#7f8d7c;
}

/* ---- the buff square: the sheet ------------------------------------------ */
.ewc-sheet{
  position:relative; min-width:0; min-height:0; overflow-y:auto;
  background:var(--dv-buff,#e9e1cc); color:var(--dv-ink,#24342b);
  padding:5.5cqh 0 48px;
}
.ewc-sheeth, .ewc-bracket, .ewc-srows, .ewc-qrow, .ewc-grows{ max-width:1080px; }
.ewc-sheeth{
  display:flex; align-items:baseline; justify-content:space-between; gap:12px;
  padding:0 34px 14px; flex-wrap:wrap;
}
.ewc-sheeth h2{
  margin:0; font-family:var(--serif,'Libre Caslon Text',Georgia,serif);
  font-style:italic; font-weight:400; font-size:21px; letter-spacing:0;
  color:var(--dv-ink,#24342b);
}
.ewc-sub{
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace); font-size:10.5px;
  letter-spacing:.05em; color:var(--dv-moss,#5d6b5f); font-variant-numeric:tabular-nums;
}
.ewc-clear{
  border:0; background:none; padding:0; cursor:pointer; border-radius:0;
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace); font-size:10.5px;
  letter-spacing:.05em; color:var(--dv-flag,#a8402c);
}
.ewc-clear:hover{ text-decoration:underline; }
.ewc-empty{ padding:24px 34px; font-family:var(--serif,'Libre Caslon Text',Georgia,serif); font-style:italic; color:var(--dv-moss,#5d6b5f); font-size:14px; }

/* the bracket: columns of match cards, ruled by hairlines only */
.ewc-bracket{ display:grid; gap:0 28px; padding:0 34px; align-items:start; }
.ewc-cols2{ grid-template-columns:repeat(2, minmax(0,1fr)); }
.ewc-cols3{ grid-template-columns:repeat(3, minmax(0,1fr)); }
.ewc-colcap{
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace); font-size:10.5px;
  letter-spacing:.14em; text-transform:uppercase; color:var(--dv-moss,#5d6b5f);
  padding:6px 0 8px; border-bottom:1px solid var(--ewc-rule2,rgba(36,56,45,.32));
}
.ewc-match{ padding:12px 0 12px; border-bottom:1px solid var(--ewc-rule,rgba(36,56,45,.18)); }
.ewc-mlabel{
  display:flex; justify-content:space-between; gap:8px;
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace); font-size:10px;
  letter-spacing:.08em; text-transform:uppercase; color:var(--dv-moss,#5d6b5f);
  margin-bottom:6px;
}
.ewc-mlabel i{ font-style:normal; text-transform:none; letter-spacing:.04em; }
.ewc-mrow{
  display:grid; grid-template-columns:minmax(0,1fr) 34px; gap:0 10px; align-items:baseline;
  padding:3px 0; color:var(--dv-moss,#5d6b5f);
}
.ewc-mrow.won{ color:var(--dv-ink,#24342b); }
.ewc-mname{
  font-family:var(--serif,'Libre Caslon Text',Georgia,serif); font-size:16px;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-width:0;
}
.ewc-mrow.won .ewc-mname{ font-weight:400; }
.ewc-mscore{
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace); font-size:15px;
  text-align:right; font-variant-numeric:tabular-nums;
}
.ewc-mrow.won .ewc-mscore{ color:var(--dv-flag,#a8402c); }
/* the pills — one mono figure per game, on a hairline; the Armageddon
   carries the flag as its rule, a forfeit is a dead figure */
.ewc-pills{ display:flex; gap:6px; margin-top:8px; flex-wrap:wrap; }
.ewc-pill{
  min-width:26px; height:22px; padding:0 6px; border-radius:0; cursor:pointer;
  border:1px solid var(--ewc-rule2,rgba(36,56,45,.32)); background:none;
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace); font-size:11px;
  color:var(--dv-ink,#24342b); line-height:20px; font-variant-numeric:tabular-nums;
  transition:color .15s ease, border-color .15s ease, background-color .15s ease;
}
.ewc-pill.win{ border-color:var(--dv-ink,#24342b); }
.ewc-pill.loss{ color:var(--dv-moss,#5d6b5f); }
.ewc-pill.arm{ border-bottom:2px solid var(--dv-flag,#a8402c); }
.ewc-pill.ff{ cursor:default; color:var(--dv-moss,#5d6b5f); border-style:dashed; display:inline-block; }
button.ewc-pill:hover{ background:var(--dv-flag,#a8402c); color:#f2e8d8; border-color:var(--dv-flag,#a8402c); }
button.ewc-pill:focus-visible{ outline:2px solid var(--dv-flag,#a8402c); outline-offset:1px; }

/* the standings: one row per player, hairlines, the top three in ink */
.ewc-srows{ padding:0 34px; }
.ewc-srow{
  display:grid; grid-template-columns:76px minmax(0,1.6fr) minmax(0,1fr) 54px 74px 92px;
  gap:0 14px; align-items:baseline; padding:9px 0;
  border-bottom:1px solid var(--ewc-rule,rgba(36,56,45,.18));
  color:var(--dv-moss,#5d6b5f);
}
.ewc-srow.top{ color:var(--dv-ink,#24342b); }
.ewc-shead{
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace); font-size:10px;
  letter-spacing:.14em; text-transform:uppercase; color:var(--dv-moss,#5d6b5f);
  border-bottom-color:var(--ewc-rule2,rgba(36,56,45,.32));
}
.ewc-splace, .ewc-selo, .ewc-srec, .ewc-sprize, .ewc-steam{
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace); font-size:11px;
  letter-spacing:.03em; font-variant-numeric:tabular-nums; white-space:nowrap;
}
.ewc-splace{ color:var(--dv-flag,#a8402c); }
.ewc-selo, .ewc-srec, .ewc-sprize{ text-align:right; }
.ewc-sname{
  border:0; background:none; padding:0; cursor:pointer; border-radius:0; text-align:left;
  font-family:var(--serif,'Libre Caslon Text',Georgia,serif); font-size:16px;
  color:inherit; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-width:0;
}
.ewc-shead .ewc-sname{ font-family:inherit; font-size:inherit; cursor:default; }
button.ewc-sname:hover{ color:var(--dv-flag,#a8402c); }
.ewc-srow.top .ewc-sprize{ color:var(--dv-ink,#24342b); }

/* every game, as one scoresheet */
.ewc-qrow{ padding:0 34px 10px; }
/* answers the frame's `#wbView input[type="search"]` roster at a higher
   specificity — match what you answer (the narrow-viewport law's cousin) */
body.ewcroom #wbView input.ewc-q{
  width:100%; max-width:520px; box-sizing:border-box; border:0; border-radius:0;
  border-bottom:1px solid var(--ewc-rule2,rgba(36,56,45,.32)); background:none;
  padding:6px 0; font-family:var(--mono,'Spline Sans Mono',Menlo,monospace);
  font-size:12px; color:var(--dv-ink,#24342b); outline:none;
}
body.ewcroom #wbView input.ewc-q::placeholder{ color:var(--dv-moss,#5d6b5f); opacity:.8; }
body.ewcroom #wbView input.ewc-q:focus{ border-bottom-color:var(--dv-flag,#a8402c); }
.ewc-grows{ padding:0 34px; }
.ewc-gsec{
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace); font-size:10.5px;
  letter-spacing:.14em; text-transform:uppercase; color:var(--dv-moss,#5d6b5f);
  padding:22px 0 6px; border-bottom:1px solid var(--ewc-rule2,rgba(36,56,45,.32));
}
.ewc-grow{
  display:grid; width:100%; box-sizing:border-box;
  grid-template-columns:30px 48px minmax(0,1.1fr) minmax(0,1.2fr) 44px minmax(0,1.2fr) minmax(0,1.6fr) 30px;
  gap:0 12px; align-items:baseline; padding:8px 0; text-align:left;
  border:0; border-bottom:1px solid var(--ewc-rule,rgba(36,56,45,.18)); border-radius:0;
  background:none; cursor:pointer; color:var(--dv-ink,#24342b);
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
}
.ewc-grow.ff{ cursor:default; color:var(--dv-moss,#5d6b5f); }
button.ewc-grow:hover{ background:rgba(36,56,45,.05); }
button.ewc-grow:focus-visible{ outline:2px solid var(--dv-flag,#a8402c); outline-offset:-2px; }
.ewc-gn, .ewc-gd, .ewc-gr, .ewc-gp{
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace); font-size:10.5px;
  letter-spacing:.03em; color:var(--dv-moss,#5d6b5f); font-variant-numeric:tabular-nums;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.ewc-gp{ text-align:right; }
.ewc-armtag{ font-style:normal; color:var(--dv-flag,#a8402c); letter-spacing:.08em; }
.ewc-gw, .ewc-gb{
  font-family:var(--serif,'Libre Caslon Text',Georgia,serif); font-size:15px;
  color:var(--dv-moss,#5d6b5f); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-width:0;
}
.ewc-gb{ text-align:right; }
.ewc-gw.won, .ewc-gb.won{ color:var(--dv-ink,#24342b); }
.ewc-gw i, .ewc-gb i{
  font-style:normal; font-family:var(--mono,'Spline Sans Mono',Menlo,monospace);
  font-size:10px; margin:0 .5em; opacity:.8;
}
.ewc-gres{
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace); font-size:11.5px;
  text-align:center; font-variant-numeric:tabular-nums; color:var(--dv-ink,#24342b);
}
.ewc-gres.d{ color:var(--dv-moss,#5d6b5f); }
.ewc-gop{
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace); font-size:10.5px;
  color:var(--dv-ink,#24342b); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-width:0;
}
.ewc-gop i{ font-style:normal; color:var(--dv-moss,#5d6b5f); margin-left:.6em; }

/* narrow: the two squares stack, the sheet grids fold */
@media (max-width: 900px){
  /* one page that scrolls: the plate on top, the sheet under it. The plate
     drops SIZE containment (a size container in an auto row collapses to
     its padding — measured: a 90px pine strip with the eyebrow spilling
     out) for inline-size, so cq units keep reading the width. */
  #ewcRoom{ display:block; overflow-y:auto; }
  .ewc-state{ container-type:inline-size; padding:26px 22px 22px; }
  .ewc-eyebrow{ padding-left:26px; }   /* clears the frame's ☰ at the top-left */
  .ewc-plate{ margin-top:18px; }
  .ewc-sheet{ overflow:visible; min-height:0; padding-top:28px; }
  .ewc-file{ display:none; }
  .ewc-pc{ width:38%; right:-10%; bottom:-16%; opacity:.55; }
  .ewc-bracket.ewc-cols2, .ewc-bracket.ewc-cols3{ grid-template-columns:minmax(0,1fr); }
  .ewc-grow{ grid-template-columns:30px minmax(0,1.2fr) 44px minmax(0,1.2fr); }
  .ewc-grow .ewc-gd, .ewc-grow .ewc-gr, .ewc-grow .ewc-gop, .ewc-grow .ewc-gp{ display:none; }
  .ewc-srow{ grid-template-columns:64px minmax(0,1.6fr) 54px 92px; }
  .ewc-srow .ewc-steam, .ewc-srow .ewc-srec{ display:none; }
}
/* ================================================================
   THE ENGINE PANE — the one owner of engine chrome (2026-08-11)
   ================================================================
   Every registered engine surface (sfRegister, js/07-daily-sf.js)
   dresses here and nowhere else. Formed by folding engine-interface.css
   (which was slot 28, holding only the status-dot contract and the
   ladder geometry) together with the engine blocks that had been
   squatting in solve-engine-overrides.css — the 962-line last-wins layer
   that css/-scoped greps could not see. The true owner was nearly empty
   while the overrides layer held its furniture; this is one file again.

   Order inside this file IS the old cascade order: the engine-interface
   body first (it loaded earlier), then the overrides blocks in their
   original sequence. Nothing between the old slot 28 and this tail slot
   styles these selectors except app-frame (cursor / user-select),
   interaction-pass (.pvm cursor), house-voice (.sf-mpv-btn, !important)
   and openings-room (a body.labone-scoped .sf-panel font-size) — none of
   which collide, and the cascade-order diff run for the fold reported
   zero winner changes.

   Engine = "candidate ladder": moves ranked, hairlines are the bars,
   continuation only on the selected move. The panel publishes whole
   depths only; MultiPV changes go through sfMpvSet. STRUCTURE decides
   rebuilds, values only patch.
   ================================================================ */

/* one contract for every registered engine surface (sfRegister, 07-daily-
   sf.js): the engine idiom is ONE 9px status dot; score chips are side-
   classed (light pill = good for White). Later-wins over both earlier
   engine eras. */
.sf-row.v2 .sf-btn.eng-toggle.v2{width:auto;flex:none;display:inline-flex;
  align-items:center;gap:.45rem;padding:.28rem .1rem;height:auto;
  font-family:var(--mono);font-size:.66rem;font-weight:500;letter-spacing:.16em;
  text-transform:uppercase;color:var(--ink2)}
.sf-row.v2 .sf-btn.eng-toggle.v2:hover{color:var(--ink)}
.sf-row.v2 .sf-btn.eng-toggle.v2.on{color:var(--acc)}
.sf-row.v2 .eng-toggle.v2 .tgl{position:static;order:2;flex:none;width:9px;height:9px;
  margin:0 0 0 .1rem;border-radius:50%;border:none;background:var(--hairline3);
  box-shadow:none}
.sf-row.v2 .eng-toggle.v2.on .tgl{background:var(--acc);
  box-shadow:0 0 7px var(--accdim)}
/* the id-scoped ON rules at #2306 beat any class-only selector — restate the
   status-dot accent at id level, later (same specificity, this file's order) */
#tab-solve .eng-toggle.on .tgl, #tab-vision .eng-toggle.on .tgl,
#tab-nihal .eng-toggle.on .tgl{background:var(--acc);border-color:transparent;
  box-shadow:0 0 7px var(--accdim)}
.sf-row.v2 .sf-dots{flex:none;display:inline-flex;align-items:center;
  padding:.2rem .3rem;border-radius:6px}
.sf-row.v2 .eng-depth,.sf-row.v2 .eng-name{font-family:var(--mono);
  font-size:.64rem;letter-spacing:.06em;color:var(--mut2)}
.sf-row.v2 .eng-name{color:var(--mut)}
.sf-row.v2 .sf-gear{display:inline-flex;align-items:center;padding:.2rem;
  border-radius:6px}

/* summary strip */
.sf-sum{display:flex;align-items:center;gap:.65rem;padding:.45rem 0 .5rem;
  margin-bottom:.15rem;border-bottom:1px solid var(--hairline)}
.sf-sum-score{flex:none;font-family:var(--mono);font-size:1.02rem;font-weight:700;
  font-variant-numeric:tabular-nums}
.sf-sum-score.w{color:#f2f6fb}
.sf-sum-score.b{color:#93a5bd}
.sf-evalbar{flex:1;display:flex;height:9px;border-radius:5px;overflow:hidden;
  background:#20242c;border:1px solid var(--hairline2)}
.sf-evalbar i{display:block;height:100%}
.sf-evalbar i.w{background:linear-gradient(180deg,#f5f8fb,#d9e1ea)}
.sf-evalbar i.d{background:#6e7887}
.sf-evalbar i.l{background:#141920}
.sf-sum-d{flex:none;font-family:var(--mono);font-size:.62rem;color:var(--mut2)}

/* the candidate ladder */
.sf-cand.v2{display:grid;grid-template-columns:auto 1fr auto;align-items:baseline;
  gap:.55rem;padding:.38rem .35rem;border-radius:7px}
.sf-cand.v2 + .sf-cand.v2{border-top:1px solid var(--hairline)}
.sf-cand.v2:hover{background:var(--surface2)}
.sf-cand.v2.sel{background:var(--surface2)}
.sf-cand.v2 .sf-chip{justify-self:start;min-width:3.1rem;text-align:center;
  font-family:var(--mono);font-size:.72rem;font-weight:700;padding:.14rem .3rem;
  border-radius:6px;font-variant-numeric:tabular-nums;border:1px solid transparent}
.sf-cand.v2 .sf-chip.w{background:#eef1f5;color:#15181d}
.sf-cand.v2 .sf-chip.b{background:#1a2230;color:#c9d8ea;border-color:var(--hairline3)}
.sf-cand.v2 .sf-pv{font-family:var(--sans);font-size:.8rem;font-weight:400;
  color:var(--ink2);line-height:1.5}
.sf-cand.v2.top .sf-pv{color:var(--ink);font-weight:500}
.sf-cand.v2.sel .sf-pv{color:var(--ink)}
.sf-cand.v2 .sf-caret{color:var(--mut2);font-size:.55rem;padding-top:0}
.sf-cand.v2.stale{opacity:.38;pointer-events:none}

/* ---- from the overrides layer, in its original order ---------------- */

/* engine toggle = a section header row, not hardware.
   "SF 18 engine" mono caps left · 6px status dot right. No box. */
.sf-row{ border-top: 1px solid var(--hairline); margin-top: 2px; padding-top: 11px; }
.sf-row .sf-btn.eng-toggle{ width: 100%; height: 20px; display: flex; align-items: center;
  gap: 8px; background: none !important; border: none !important; border-radius: 0;
  font-family: var(--mono); font-size: 10px; font-weight: 400; letter-spacing: .16em;
  text-transform: uppercase; color: var(--mut2); padding: 0; box-shadow: none; }
.sf-row .sf-btn.eng-toggle:hover{ color: var(--mut); }
.sf-row .eng-toggle .tgl{ position: static; order: 2; margin-left: auto;
  width: 6px; height: 6px; flex: none; border-radius: 50%; background: var(--mut2);
  border: none; box-shadow: none; transition: background .12s ease; }
.sf-row .eng-toggle .tgl i{ display: none; }
.sf-row .eng-toggle::before, .sf-row .eng-toggle::after{ content: none; }
.sf-row .eng-toggle.on{ color: var(--acc); background: none !important; border: none !important; }
.sf-row .eng-toggle.on .tgl{ background: var(--acc); }

/* panel: no box at all — content under the header. One rule for every
   registered engine surface (see sfRegister in js/07-daily-sf.js). */
#sfPanelSolve.sf-panel, #sfPanelNdb.sf-panel, #sfPanelArt.sf-panel, #sfPanelEl.sf-panel{ margin-top: 0; background: none;
  border: none; border-radius: 0; padding: 8px 0 2px; }

/* the candidate ladder */
.sf-cand{ display: flex; flex-direction: column; padding-top: 8px; cursor: pointer; }

/* notes */
.sf-note{ font-family: var(--mono); font-size: 10px; color: var(--mut); }

/* header per mock: ENGINE ·· ● SF 18 d N; depth lives in the header */
.sf-row .eng-toggle .tgl{ order: 2; }
.sf-row .eng-toggle .eng-name{ order: 3; color: var(--mut); letter-spacing: .16em; }
.sf-row .eng-toggle .eng-depth{ order: 4; color: var(--mut2); letter-spacing: .06em;
  text-transform: none; min-width: 34px; text-align: right; }
.sf-row .eng-toggle.on .eng-name{ color: var(--ink2); }

.sf-cann{ font-family: var(--mono); font-size: 10.5px; color: var(--mut2); margin-left: 9px; }

/* stale-while-thinking: previous position's lines stay visible, dimmed and
   inert, until fresh lines land (sfStash/sfCandRow in js/07-daily-sf.js) */
.sf-cand.stale{ opacity: .38; pointer-events: none; }

/* ============ ENGINE PANE CONTRACT v2 (2026-07-24 design overhaul) ============
   Fixed grid geometry: eval column 4.6em (tabular-nums, right-stable), PV
   one-line ellipsis (selected row unwraps), caret flush. Threat mode tints
   the panel border and posts a banner. The ± steppers replace the old dots. */
.sf-panel{ border: 1px solid transparent; border-radius: 6px;
  transition: border-color var(--mo-fast) var(--mo-ease); }
.sf-panel.threat{ border-color: var(--mid); }
.sf-panel.threat::before{ content: "threat mode — side to move flipped · x exits";
  display: block; font-family: var(--mono); font-size: .56rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--mid); padding: .32rem .45rem 0; }
.sf-cand.v2{ grid-template-columns: 4.6em minmax(0,1fr) 1em; gap: .4rem; }
.sf-cand.v2 .sf-ec{ display: flex; align-items: baseline; gap: .22rem; min-width: 0; }
.sf-cand.v2 .sf-chip{ font-variant-numeric: tabular-nums lining-nums; }
.sf-cand.v2 .sf-tr{ flex: none; width: .95em; font-size: .54rem; color: var(--ok);
  font-family: var(--mono); }
.sf-cand.v2 .sf-pv{ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sf-cand.v2.sel .sf-pv{ white-space: normal; }
.sf-mpv{ flex: none; display: inline-flex; align-items: center; gap: .14rem;
  margin-left: .3rem; }
.sf-mpv-btn{ appearance: none; background: none; border: 1px solid var(--hairline2);
  border-radius: 4px; color: var(--mut); width: 1.06rem; height: 1.06rem; padding: 0;
  font: 400 .72rem/1 var(--mono); cursor: pointer; }
.sf-mpv-btn:hover{ color: var(--ink); border-color: var(--acc); }
.sf-mpv-n{ font-family: var(--mono); font-size: .62rem; color: var(--mut);
  min-width: .85em; text-align: center; }

/* the house voice over the instrument (2026-08-03): colour only, geometry
   untouched — the pane keeps mono, because an instrument speaking mono IS
   the theme's second voice. (.sf-block dropped 2026-08-11: no emitter has
   ever written that class.) */
.sf-panel{ border-color:rgba(255,255,255,.09); }
.sf-row .eng-toggle .tgl{ border-radius:5px; }
.sf-mpv-btn{ font-family:var(--mono) !important; }

/* ---- THE PUZZLE ROOM'S ENGINE (2026-08-11) --------------------------
   The engine is a guest in a door-voice room: it appears only when the
   solver presses `analysis` (solve-session.css owns that visibility; this
   file still owns the DRESS, so sf- keeps one owner). Two things had to
   answer the room rather than the house:

   1. THE SCORE CHIP WAS THE LAST FILLED SLAB ON THE SCREEN. `.sf-chip.w`
      is a solid #eef1f5 pill — bright white against pine, and louder than
      the board it is commenting on. The bordered-verbs law has forbidden
      a filled object at rest since 2026-08-03; the score is DATA, so it
      becomes a mono figure in a hairline. (This is the call T1 and T2
      both parked — reports/T1-OVERRIDES-DISSOLVED-2026-08-11.md — taken
      here only for this room, where the pine ground forces it.)
   2. THE PANEL OVERFLOWED THE PLATE. The block is built for a ~560px
      column and the eval bar plus `depth NN` ran past its right edge
      (measured 1440x900: clipped at the viewport). The grid's middle
      track is 1fr, so it only needed permission to shrink — min-width:0
      on the track, and the PV line clips with an ellipsis instead. */
/* (scope: body.svpage — the ONE engine face, 2026-08-13. This block was
      the puzzle room's (`:not(.repmode)`) while sessions kept the 2026-07
      chrome; the session-layer rework put every session on the T5 plate
      and this dress came with it. The openings study room's rail pane
      wore the same rules under `body.labone #wbRail` from 2026-08-13
      until 2026-08-18, when the room moved onto the solve page as the
      explorer session in repertoire dress and the pane — and its scope —
      died; the plate's own engine row is the study room's now.) */
/* 3. THE ROW IS THE SWITCH (2026-08-12, owner: "instead of analysis being
      a button, it should always be in this format — you just click
      analysis to turn it on, off"). #svEngBtn — a second control for the
      same engine — is deleted; this row is resident at every phase and
      its own label is the toggle it always was. So it has to READ as one:
      it was 10px in --mut2 against pine, the quietest thing on a screen
      whose only other verbs are 12px words. Mono caps in the room's sage,
      warming to buff on hover and standing in the flag when the engine is
      running — the same three-state grammar the verbs use. The hairline
      above it is the plate's one rule: it separates the room's own words
      from the machine's opinion. */
body.svpage #tab-solve .sf-row{
  border-top:1px solid rgba(233,225,204,.14);
  margin-top:26px; padding-top:13px; align-items:center;
}
body.svpage #tab-solve .sf-row .sf-btn.eng-toggle{
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace);
  font-size:11px; letter-spacing:.16em; text-transform:uppercase;
  color:var(--dv-sage,#a9b8a6); cursor:pointer;
}
body.svpage #tab-solve .sf-row .sf-btn.eng-toggle:hover{
  color:var(--dv-buff,#e9e1cc);
}
body.svpage #tab-solve .sf-row .eng-toggle.on{
  color:var(--dv-flag-lt,#e0906c);
}
body.svpage #tab-solve .sf-row .eng-toggle .tgl{
  background:rgba(233,225,204,.28);
}
body.svpage #tab-solve .sf-row .eng-toggle.on .tgl{
  background:var(--dv-flag-lt,#e0906c); box-shadow:0 0 7px rgba(224,144,108,.5);
}
/* THE PUZZLE ROOM'S ENGINE ROW SPEAKS THE ROOM'S TYPE (2026-08-12). The
   owner's type pass moved every piece of text on that plate off the
   monospace — "including STOCKFISH 18 lite text, i'm talking literally
   every piece of text on this page" — and this row is the last of it. The
   change lands HERE and not in solve-session.css because the engine pane's
   dress is this file's; the room states ORDER and VISIBILITY for the block
   and nothing else. Scope is already the puzzle room, so no other board
   screen moves. The nameplate stays (it is Stockfish's GPL attribution and
   the app's only visible one) — it just stops being the loudest-typeset
   thing in a room that reads in a grotesk. */
body.svpage #tab-solve .sf-row :is(.eng-depth, .eng-name){
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:10.5px; letter-spacing:.04em; color:var(--dv-moss,#5d6b5f);
  font-variant-numeric:tabular-nums;
}
/* the MultiPV stepper. !important answers this file's own line 164, which
   answers house-voice's — the family has been claimed twice already and a
   third claimant cannot be polite about it. Specificity, not shouting, is
   what wins here: (1,4,0) over (0,1,0). */
body.svpage #tab-solve .sf-row :is(.sf-mpv-btn, .sf-mpv-n){
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif) !important;
  font-variant-numeric:tabular-nums;
}
/* the panel's readouts — the evaluation, the depth, the per-line score.
   Figures, so tabular numerals do the aligning a monospace was there for.
   (The PV moves keep their figurine face: those are piece GLYPHS, not
   text, and the whole point of that font is that a knight draws a knight.) */
body.svpage #tab-solve :is(.sf-sum-score, .sf-sum-d, .sf-chip){
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-variant-numeric:tabular-nums lining-nums;
}
body.svpage #tab-solve .sf-row .sf-mpv-btn{
  border-color:rgba(233,225,204,.22); border-radius:0;
  color:var(--dv-sage,#a9b8a6);
}
body.svpage #tab-solve .sf-row .sf-mpv-btn:hover{
  border-color:rgba(224,144,108,.5); color:var(--dv-flag-lt,#e0906c);
}
body.svpage #tab-solve .sf-row .sf-mpv-n{
  color:var(--dv-sage,#a9b8a6);
}
body.svpage #tab-solve .sf-row .sf-gear{
  color:var(--dv-moss,#5d6b5f); cursor:pointer;
}
body.svpage #tab-solve .sf-row .sf-gear:hover{
  color:var(--dv-buff,#e9e1cc);
}

body.svpage #tab-solve .sf-cand.v2 .sf-chip{
  background:none; border:1px solid rgba(233,225,204,.28); border-radius:0;
  color:var(--dv-buff-ink,#efe9d6); font-weight:400;
}
body.svpage #tab-solve .sf-cand.v2.top .sf-chip{
  border-color:rgba(224,144,108,.5); color:var(--dv-flag-lt,#e0906c);
}
body.svpage #tab-solve .sf-row,
body.svpage #tab-solve #sfPanelSolve{ min-width:0; overflow:hidden; }
body.svpage #tab-solve .sf-cand.v2{ min-width:0; }
body.svpage #tab-solve .sf-cand.v2 .sf-pv{
  min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
/* ================================================================
   WINDOW-CONTROLS-OVERLAY (installed PWA, 2026-07-24)
   ================================================================
   display_override lands WCO first: the chrome's top edges become window
   drag surfaces (VS Code style), content shifts clear of the OS buttons via
   the titlebar-area env vars. Sidebar wordmark drags; a full-width strip
   drags on board pages. Interactive children stay clickable — the drag
   region is the padding, never a button.

   Its own file since 2026-08-11, at the manifest TAIL, which is where it
   lived inside solve-engine-overrides.css. The tail is load-bearing:
   sidebar-flatten.css sets #tabs{padding} wholesale at slot 45, so a WCO
   padding-top parked any earlier would silently lose in the one display
   mode it exists for.
   ================================================================ */
@media (display-mode: window-controls-overlay) {
  #tabs{ padding-top: calc(1.1rem + env(titlebar-area-height, 0px)); }
  #tabs::before{ -webkit-app-region: drag; app-region: drag;
    padding-top: env(titlebar-area-height, 0px);
    margin-top: calc(-1 * env(titlebar-area-height, 0px)); }
  body.svpage::before{ content: ""; position: fixed; top: 0; left: 0; right: 0;
    height: env(titlebar-area-height, 0px); z-index: 60;
    -webkit-app-region: drag; app-region: drag; }
}
/* ================================================================
   THE SOLVE SESSION — the one owner of the solve/train surface
   (2026-08-11)
   ================================================================
   Every puzzle in the site is SOLVED here: #tab-solve and the four
   train rooms that feed it. Formed by lifting the solve blocks out of
   solve-engine-overrides.css, the 962-line last-wins layer that lived
   in patterns/ (not patterns/css/) and that every css/-scoped grep
   missed. The layer's position — "last by design" — is now this file's
   manifest slot, so the cascade is unchanged and the ownership is
   legible.

   Blocks keep their original relative order; the engine chrome went to
   engine-pane.css and the explorer session to explorer-session.css,
   both of which the manifest places around this file exactly where the
   old single layer put them.

   Board-first law: the board is the hero and --bd is the single source
   of its size. Quiet-screen law: a screen states each fact once.
   ================================================================ */

/* ================================================================
   THE LIFTED PLATE (2026-08-12) — every rule that dressed the solve
   room's right column, from the ten files that used to share it
   ================================================================
   Owner's read: "maybe the button layouts is in like 18 files when it
   could be in one or two". It was ten, and this is what they said
   between them: .sv-act defined EIGHT times, .sv-msg six, .sv-rank
   five, .sv-idbtn and .sv-links four each — every layer overwriting
   part of the last, the final two rounds with !important, and the
   door-voice block at the end of this file answering all of them with
   !important again. That is why the verbs looked like leftovers: they
   were the residue of five faces, not one face.

   Lifted VERBATIM and in cascade order (build/assets.py's manifest
   order, then source order within each file), so this move alone
   changes no winner — proven with tests/cascade_diff.py before the
   collapse below it. Each rule keeps a provenance comment. The
   collapse is the NEXT block; these stay as the layer they always
   were, and every one that the collapse subsumes is deleted there
   rather than left to fight.

   The classes are machine-guarded to this file from here on
   (tests/css-ownership.test.mjs, CLASS_OWNERS) — the prefix guard
   could never hold `sv-`, because two namespaces wear it: this room,
   and the site-wide verb kit (.sv-sec / .sv-ghost / .sv-bar) that has
   squatted in the room's prefix since the beginning and legitimately
   lives in the house layers.
   ================================================================ */

/* tokens-base.css:259 */
.sv-prognums{ display:flex; justify-content:space-between; align-items:baseline; font-family:var(--mono); font-size:.72rem; color:var(--ink2); font-variant-numeric:tabular-nums; margin-bottom:.35rem }
/* tokens-base.css:266 */
.sv-progress{ margin:0 0 .85rem }
/* tokens-base.css:267 */
.sv-msg{ min-height:2.4em; margin:0 0 .7rem; font-size:.92rem; color:var(--ink2); display:flex; align-items:center }
/* tokens-base.css:269 */
.sv-msg.good, .sv-msg.bad{ border-radius:9px; padding:.5rem .8rem; font-weight:600 }
/* chrome-redesign.css:124 */
.sv-bignext{ display:block; width:100%; font-size:1.12rem; font-weight:700; letter-spacing:.05em; padding:.9rem 1rem; margin:.65rem 0 .1rem; animation:svpop .18s ease-out }
@media (prefers-reduced-motion: reduce){
  /* chrome-redesign.css:128 */
  .sv-bignext{ animation:none }
}
/* chrome-redesign.css:372 */
.sv-meta{ font-family:var(--sans); font-size:.76rem; color:var(--ink2); letter-spacing:.01em; margin-top:.35rem; line-height:1.6 }
/* chrome-redesign.css:374 */
.sv-meta em{ font-style:normal }
/* chrome-redesign.css:375 */
.sv-meta em.ok{ color:var(--ok) }
/* chrome-redesign.css:376 */
.sv-meta em.hot{ color:#c9a86a }
/* chrome-redesign.css:378 */
.sv-actions .seg{ align-self:stretch; display:flex }
/* chrome-redesign.css:379 */
.sv-actions .seg button{ flex:0 0 auto }
/* chrome-redesign.css:380 */
.sv-actions .seg #svHintBtn{ flex:1; text-align:center; white-space:normal }
/* chrome-redesign.css:381 */
.sv-actions .sv-ghost{ align-self:center; font-size:.74rem }
/* chrome-redesign.css:382 */
.sv-actions .seg .seg-go.pulse{ animation:segpulse 1.4s ease-in-out infinite }
/* chrome-redesign.css:384 */
.sv-progress .sv-prognums{ font-size:.7rem }
/* chrome-redesign.css:450 */
.sv-idsp{ flex:1 }
/* chrome-redesign.css:453 */
.sv-idbtn:hover{ border-color:var(--btnlineh); color:var(--ink) }
/* chrome-redesign.css:454 */
.sv-idbtn.on{ color:var(--acc) }
/* tokens-base.css:251, chrome-redesign.css:27, chrome-redesign.css:533 */
.sv-rank{ font-family:var(--sans); font-size:.62rem; letter-spacing:.01em; color:var(--ink2); text-transform:none; opacity:.85 }
/* chrome-redesign.css:564 */
.solve-side.v2 .sv-progress{ display:flex; flex-direction:column; gap:5px }
/* chrome-redesign.css:570 */
.solve-side.v2 .sv-actions{ display:flex; flex-direction:column; gap:7px; border-top:1px solid var(--hairline); padding-top:12px }
/* (.sv-act.go / .sv-act.go:hover from chrome-redesign 576-577 and
   spec-sync 13 are subsumed by THE VERB below, which states the same
   two declarations once. .sv-prevlink and .sv-fochelp died here
   2026-08-12 with the focus mode they were named for — `← back one` is
   a verb now and stands in the verb row.) */
/* chrome-redesign.css:451, chrome-redesign.css:529, spec-sync.css:14 */
.sv-idbtn{ font-family:var(--mono); font-size:11px; color:var(--ink2); background:none; border:1px solid var(--btnline); border-radius:4px; padding:2px 7px; cursor:pointer; line-height:16px }
/* chrome-redesign.css:449, chrome-redesign.css:528, spec-sync.css:16 */
.sv-deckpos{ font-family:var(--mono); font-size:10.5px; color:var(--mut) }
/* chrome-redesign.css:561, spec-sync.css:20 */
.solve-side.v2 .sv-rank{ font-size:16px; letter-spacing:.01em; text-transform:none; font-family:var(--sans); font-weight:600; color:var(--ink); opacity:1 }
/* chrome-redesign.css:563, spec-sync.css:21 */
.solve-side.v2 .sv-meta{ font-size:10.5px; color:var(--mut); line-height:1.7 }
/* chrome-redesign.css:569, spec-sync.css:22 */
.solve-side.v2 .sv-msg{ font-size:12px; color:#c6d5e6; min-height:2.2em }
/* chrome-redesign.css:567, spec-sync.css:23 */
.solve-side.v2 .sv-prognums{ display:flex; justify-content:space-between; font-family:var(--mono); font-size:10px; color:var(--mut) }
/* deep-water.css:39 */
.sv-actions .seg .seg-go.pulse, .sv-bignext{ animation:none }
/* tokens-base.css:270, deep-water.css:44 */
.sv-msg.good{ background:none; color:var(--ok); box-shadow:none; border-left:2px solid var(--ok); border-radius:0; padding:.15rem 0 .15rem .7rem; font-weight:400 }
/* tokens-base.css:272, deep-water.css:45 */
.sv-msg.bad{ background:none; color:#a06060; box-shadow:none; border-left:2px solid var(--bad); border-radius:0; padding:.15rem 0 .15rem .7rem; font-weight:400 }
/* sidebar-nav.css:40 */
.sv-moveswrap{ border-top:1px solid var(--hairline); padding-top:.45rem; margin-top:.1rem }
/* sidebar-nav.css:41 */
.sv-movesbar{ display:flex; align-items:center; gap:.35rem; margin-bottom:.3rem }
/* sidebar-nav.css:46 */
.sv-moveslbl{ font-family:var(--mono); font-size:.62rem; letter-spacing:.1em; text-transform:uppercase; color:var(--mut); margin-left:.2rem }
/* sidebar-nav.css:48 */
.sv-backsol{ margin-left:auto; font-family:var(--mono); font-size:.68rem; color:var(--acc); background:none; border:1px solid rgba(216, 176, 120, .45); border-radius:6px; padding:.24rem .6rem; cursor:pointer }
/* sidebar-nav.css:51 */
.sv-backsol:hover{ background:rgba(216, 176, 120, .1) }
/* sidebar-nav.css:52 */
.sv-moves2{ font-family:var(--mono); font-size:.8rem; line-height:1.95; color:var(--ink2); max-height:190px; overflow-y:auto; scrollbar-width:thin; word-spacing:.04em }
/* sidebar-nav.css:54 */
.sv-moves2 i{ font-style:normal; color:var(--mut2); font-size:.7rem; margin-right:.12em }
/* sidebar-nav.css:55 */
.sv-moves2 .svm{ cursor:pointer; padding:.04em .26em; border-radius:4px; color:var(--ink) }
/* sidebar-nav.css:56 */
.sv-moves2 .svm:hover{ background:var(--surface2) }
/* sidebar-nav.css:57 */
.sv-moves2 .svm.cur{ background:var(--acc-wash); color:var(--acc) }
/* sidebar-nav.css:58 */
.sv-moves2 .svm.off{ opacity:.4 }
/* sidebar-nav.css:59 */
.sv-moves2 .svm.var{ color:var(--mid) }
/* sidebar-nav.css:60 */
.sv-moves2 .svm-varwrap{ color:var(--mut) }
/* sidebar-nav.css:61 */
body.repmode .sv-moveswrap{ display:none }
/* calm-board.css:29 */
#tab-solve .sv-backsol{ color:var(--ink2); border-color:var(--btnline) }
/* (the repwork face — build/explore's compact 26px verb row, folded in
   from rep-workbench.css 2026-08-12 — died 2026-08-13 with the one-face
   rework: every session wears the T5 plate at this file's tail, and the
   repwork class itself is no longer granted.) */
/* chrome-redesign.css:377, app-frame.css:7 */
.sv-actions{ margin-top:.7rem; display:flex; flex-direction:column; gap:.45rem; user-select:none; -webkit-user-select:none }

/* ================================================================
   THE VERB — ONE FACE (2026-08-12)
   ================================================================
   `.sv-act` had SEVEN definitions and only two of them were ever on
   screen: this one (the house voice, which the rep / spar / explorer
   boards wear) and the room's own door voice at the end of the file.
   The other five were a 2026-07 rounded-slab design that never
   rendered a pixel — house-voice.css's roster carried !important, so
   the room's own later block lost to a file it could not see, and the
   dead layer sat in the source reading like the truth for months.
   That is what "the buttons look horrid" was: the residue of five
   faces, not one face.

   Now: this is the base, the door voice overrides it BY SPECIFICITY,
   and there is no !important anywhere in the chain. `.sv-act` has one
   emitter in the whole repo (the solve room's action row in
   build/skeleton_rooms.py), so the base needs no #tab-solve scope —
   and the exact-class guard in tests/css-ownership.test.mjs is what
   keeps a sixth face from appearing.
   ================================================================ */
.sv-act{ display:flex; align-items:center; justify-content:center; width:100%;
  padding:6px 14px; line-height:1.25; cursor:pointer;
  background:none; border:1px solid var(--btnline); border-radius:3px;
  font-family:var(--serif); font-size:13.5px; font-weight:400;
  letter-spacing:.01em; text-transform:none; color:var(--ink2);
  transition:color .12s ease, border-color .12s ease, background .12s ease }
.sv-act:hover{ border-color:var(--btnlineh); color:var(--acc-hi); background:var(--acc-wash2) }
.sv-act.go{ color:var(--acc); border-color:var(--accborder) }
.sv-act.go:hover{ color:var(--acc-hi); border-color:var(--acc); background:var(--acc-wash2) }
.sv-act:focus-visible{ outline:1px solid var(--acc); outline-offset:2px }
@media (prefers-reduced-motion:reduce){ .sv-act{ transition:none } }

/* sidebar-nav.css:42, house-voice.css:87 */
.sv-mstep{ width:26px; height:24px; display:flex; align-items:center; justify-content:center; background:none; border:1px solid var(--hairline3); border-radius:3px; color:var(--ink2); font-size:12px; cursor:pointer; padding:0 }
/* sidebar-nav.css:45, house-voice.css:91 */
.sv-mstep:hover{ border-color:var(--btnlineh); color:var(--ink) }

/* panel width: 208 → 280 (board is vh-capped at all common sizes;
   1440×900: 594 board + 36 + 280 + gutters = 974px used — margin pays) */
.solve-side.v2{ width: 280px; }

/* the verb ROW: words on a line, the advance last. (The 2026-07-25
   `1fr 1fr` grid that used to be here went with the dead slab face it
   was drawn for — it inflated three words into half-panel bars, which
   is the bordered-verbs law broken by geometry rather than by fill.) */
.solve-side.v2 .sv-actions{ display: flex; flex-wrap: wrap;
  gap: .55rem; border-top: none; padding-top: 0; margin-top: 1rem; }
.solve-side.v2 .sv-actions .sv-act{ width: auto; }
.sv-act.go{ order: 9; }
.sv-act.sv-back{ order: 8; }


/* calm board zone: solver chrome goes neutral on board screens.
   (The .go neutralizer is gone — the action stack's ONE primary stays gold
   by design, 2026-07-25 pm.) */

/* the drawn card must never overflow its grid track: the board svg is vh-sized,
   so when the viewport is width-tight (browser zoom, small windows, chat rail)
   the track shrinks but the card didn't — it painted over the side card.
   Constraint flows down from the track; the board flex-shrinks to fit. */
#tab-solve .sv-boardcol{ min-width: 0; }
#tab-solve .sv-card{ max-width: 100%; }
#tab-solve .sv-ranks{ flex: none; }
#tab-solve #svBoard{ min-width: 0; flex: 0 1 auto; }
#tab-solve .sv-card #svBoard svg{ max-width: 100%; }

/* ============ svpage — HIARCS-scale board page (2026-07, v2) ============
   Measured target (HIARCS Chess Explorer Pro, user screenshot 2000x1259):
   board SQUARES 87% of window height, side panel ~41% of width, board
   flush on the page — no framing card. v1 reserved 195px of chrome and
   kept the card shell (squares landed at 80%); v2 dissolves the card
   (the 7px gallery mat is the only frame, as in HIARCS) and budgets a
   fixed 128px of chrome: strip 37 + id row 25 + mat 14 + files 19 +
   status 26 + page gaps 7. --bd is the single source of board size —
   squares = --bd, svg box = --bd + 14 (mat is svg padding), grid track
   = --bd + 28 (rank strip 14 + mat), so board and track never disagree.
   Below 1000px the mobile card layout is untouched. */
body.svpage{ padding-left: 0; }
body.svpage #tabs{ display: none; }
body.svpage .solve-top{ max-width: none; min-height: 0; padding: .3rem 1.1rem .25rem; }
/* A tablet held upright is not a phone: it has more board width in
   portrait (834) than a laptop window gives in landscape, so the big-board
   page belongs there too. The gate is min-width 700 in portrait — below
   that the mobile card layout is still untouched. The stacked column comes
   from the frame layer (workbench.css, "portrait: the control card goes
   UNDER the board"); this block is only the immersive dress. */
@media (min-width: 1000px), (min-width: 700px) and (orientation: portrait){
  body.svpage .solve-grid{ --bd: min(calc(100vh - 128px), 58vw);
    max-width: none; justify-content: stretch;
    grid-template-columns: minmax(280px, calc(var(--bd) + 28px)) minmax(320px, 1fr);
    gap: 1.1rem; padding: 0 1.1rem .4rem; }
  body.svpage .sv-card{ background: none; border: none; border-radius: 0;
    padding: 0; gap: 3px; max-width: none; }
  body.svpage .sv-card::before, body.svpage .sv-card::after{ display: none; }
  body.svpage #tab-solve .sv-card #svBoard svg{ width: var(--bd); max-width: none; }
  body.svpage .sv-files{ margin-left: 21px; width: var(--bd); }
  body.svpage .sv-statusrow{ border-top: none; padding-top: 1px; }
  body.svpage .solve-side.v2{ width: auto; }
}

/* what survives of the svpage NAV RAIL block (2026-07): the rail itself is
   deleted (2026-08-11). It expanded #tabs to a 46px hover-to-open icon
   column on board pages, and every glyph rule in it addressed ids that do
   not exist — #sg-opening / -middle / -endgame / -masters / -elite /
   -articles against a DOM whose groups are #sg-openings / -puzzles /
   -database / -study / -you, through a .sg-head that is .sg-lbl. Its
   premise died with the doorframe: --wb-left is 0, #wbLeft is display:none
   unless the map is summoned, and when it IS summoned the rail's width:46px
   squeezed the 264px buff sheet. Its body padding-left:46px had already
   been dead — workbench.css sets body{padding-left:0 !important}.
   A third survivor, `.set-panel{left:54px}`, went the same day: it was
   the rail's 46px + 8, and the settings panel's one position is now
   chrome-redesign.css's, anchored to the gear that opens it. These two
   had nothing to do with the rail and stay: */
@media (min-width: 1000px){
  body.svpage .solve-top{ padding-left: .55rem; }
  body.svpage .solve-grid{ padding-left: .45rem; }
}

/* ============ session mode facts (2026-08-13, the one-face rework) ====
   A rep / spar / build / explorer session is CONTENT on the T5 plate:
   the door-voice layer at this file's tail dresses every svpage screen,
   sessions included, and body.repmode remains only as the SESSION marker
   the puzzle-only phase rules key their :not() on. The 2026-07 era that
   lived here — its own gap scale, organ orders, eyebrow rank, compact
   verbs — is deleted, not moved. What survives is the mode's one
   visibility fact: the retreat is a PILE verb (it steps to the card
   before this one, which a session does not have — svPrev's handler has
   always returned early on SV.rep), and sessions do not go through
   svLoad's per-card hide, so the room states it once for the mode. */
body.repmode #svPrev{ display: none; }

/* the 100dvh app-frame lock (app-frame.css) means the rep rail can no longer
   ride the document scroll — it becomes its own overflow pane */
@media (min-width:1000px){
  body.svpage .solve-side.v2{ overflow-y: auto; overflow-x: hidden;
    max-height: calc(100dvh - 92px); overscroll-behavior: contain;
    scrollbar-gutter: stable; }
}

/* ============ gallery pass (2026-07-25 pm) ============
   The board is the hero: no card frame, no stacked ghosts — a floating
   board with one soft shadow. Panel header gets editorial hierarchy:
   serif title, tiny mono meta, gold progress. */
#tab-solve .sv-card{ background: none; border: none; box-shadow: none;
  padding: 0; gap: 10px; }
#tab-solve .sv-card::before, #tab-solve .sv-card::after{ content: none; }
/* No radius, no shadow (2026-07-30). The 10px rounded the corner squares of a
   grid of squares and disagreed with the 4px the base sheet set and the 1px
   square-cornered host border around it; the "soft shadow" was --ink at 24% —
   a near-white glow under an 840px board on a #0e1113 page, i.e. more of the
   glare the board pass exists to remove. The svg's own hairline is the edge. */
#tab-solve .sv-card #svBoard svg{ border-radius: 0; box-shadow: none; }
#tab-solve .sv-statusrow{ padding-top: 2px; }
#tab-solve .sv-statusrow h2{ font-family: var(--mono); font-size: .62rem;
  font-weight: 400; letter-spacing: .14em; text-transform: uppercase;
  color: var(--mut); }
.solve-side.v2 .sv-rank{ font-family: 'Libre Caslon Text', Georgia, serif;
  font-size: 1.32rem; font-weight: 700; letter-spacing: 0; line-height: 1.22;
  color: var(--ink); }
.sv-idline{ display: flex; align-items: center; gap: 7px; margin-top: 2px;
  font-family: var(--mono); font-size: .62rem; color: var(--mut2); }
.sv-idline .sv-deckpos{ font-size: .62rem; }
.sv-idline .sv-idbtn{ background: none; border: none; padding: 0 .1rem;
  font-size: .82rem; line-height: 1; color: var(--mut2); cursor: pointer; }
.sv-idline .sv-idbtn:hover{ color: var(--ink); }
.sv-idline .sv-idbtn.on{ color: var(--acc); }
#tab-solve .sv-bar i{ background: var(--btn, #c9a86a); }

/* ============ immersive board screens (2026-07-25 pm) ============
   On any board session (body.svpage — solve, explorer, lab boards) the
   whole workbench frame recedes: no sidebar, no rail, no command bar.
   The board IS the page; solve-top keeps the exit. (#wbStrip left the
   selector 2026-08-11 — the workspace strip has had no emitter since the
   doorframe; the frame's one piece of chrome is #svAppBar, which this
   file must never hide.) */
body.svpage #wbRail, body.svpage #wbCmd, body.svpage .wb-grip{ display: none; }
/* the recession means NO RESIDENT nav, not "no nav" — a summoned sheet is
   not resident (2026-08-11). Unscoped, this rule tied door-frame.css's
   `body:is(.dv-map,.sideopen) #wbLeft{display:block}` on specificity
   (1,1,1) and won on order, so ☰ on a narrow board session set .sideopen
   and opened a 0x0 sheet: a visible control that did nothing, on solve,
   explorer and every lab board. Measured 375x812 before the fix —
   #wbLeft display:none, rect 0x0, .sideopen present. */
body.svpage:not(.dv-map):not(.sideopen) #wbLeft{ display: none; }
/* ONE column, DECLARED AS TWO with the first at zero. nav-grid.css pins
   #wbMain to grid-column 2 at every width (body.wb-lean), so a single
   declared track left the room in an IMPLICIT auto column and turned the
   declared track into an empty gutter — measured 149.6px at 1440w, on
   every board session since the doorframe. It was invisible for as long as
   the room's ground matched the frame's; the pine ground below made it a
   visible band, which is how it was found. narrow-frame.css states the same
   pattern for the same reason (<1000px), and cov-board.css states its
   partner form: collapse the track AND re-pin #wbMain. */
body.svpage #wbBody{ grid-template-columns: 0 minmax(0, 1fr); grid-row: 1 / span 2; }

/* (the 2026-07-28 "frame is invariant on a board session" block that sat
   here is gone, 2026-08-11: every rule in it was scoped body.hroom, and
   the home room's body class is and always was hroom-on — so the four
   --sv-chrome budget bases it declared, graphite included, never once
   applied. The live budget is workbench.css's body.svpage{--sv-chrome:
   116px}, which is what the reading board below has always measured
   against. Restoring the block would be a render change, not a rescue;
   it goes back only with a fresh measurement behind it.) */

/* ================================================================== */
/* THE CALM PUZZLES (solve + train reskin) — redesign layer            */
/*                                                                     */
/* ⚠ THE THEME IS THE DELIVERABLE (HANDOFF-PUZZLES.md §0). Do not      */
/* re-skin with the frame's graphite measures or shrink verbs back to  */
/* 10px — the lifted values ARE the redesign. Inside the five scoped   */
/* tabs use only the --cm-* tokens declared below.                     */
/*                                                                     */
/* CSS-ONLY layer: type, colour, and verb faces — no grid or layout    */
/* geometry.                                                           */
/*                                                                     */
/* Palette law: tab-scoped, not theme-attribute-scoped, so it carries  */
/* its own raw --cm-* values (the covered-board lesson). The coverage  */
/* vocabulary (--cv-*) and the engine pane are untouched.              */
/*                                                                     */
/* INTEGRATED against the live DOM (a re-drop would undo this): the    */
/* vision chips' live states are .ok and .hot (12-vision line 65) —    */
/* .chip.on does not exist there and its selector was dropped.         */
/*                                                                     */
/* THE ONE DECLARER (T3, 2026-08-11). The calm era dresses seven       */
/* scopes: these five tabs, the database room and the master-games     */
/* popup. db-calm.css declared the same fifteen tokens for the last    */
/* two, character for character — one fact stated twice, which is how  */
/* a palette drifts. The db room and the popup joined this rule's      */
/* selector list and READ the tokens; `--cm-` is machine-guarded to    */
/* this file (tests/css-ownership.test.mjs TOKEN_OWNERS). Order does   */
/* not matter to a custom property with no competing declaration —     */
/* what matters is that there is only one.                             */
/* ================================================================== */

#tab-solve, #tab-positional, #tab-exercises, #tab-calc, #tab-vision,
body.dbroom, .sm-pop{
  --cm-paper:#14191e; --cm-surface:#1a2127; --cm-surface2:#202830;
  --cm-line:rgba(255,255,255,.07); --cm-ink:#e7ecf0; --cm-ink2:#b4bec6;
  --cm-mut:#808b94; --cm-mut2:#5d676f;
  --cm-brass:#d8b078; --cm-brass-hi:#e6c391; --cm-brass-wash:rgba(216,176,120,.12);
  --cm-terra:#cf8f6d; --cm-slate:#9db0bf; --cm-live:#8fd6a0;
  --cm-mono:'Spline Sans Mono',ui-monospace,monospace;
}
/* the session adds what the explorer's rows need (the book bar's three
   inks, and a third mute); explorer-session.css reads them by DOM
   inheritance, not by file order */
#tab-solve{
  --cm-mut3:#4b555d;
  --cm-bar:#232b31; --cm-barw:#e9edf0; --cm-bard:#59646d;
}

/* ---- the shared verb face: bordered 12.5px words that earn brass ----
   (the lr-big / dbr-verbs face; the advance/continue verb below is the
   screen's ONE filled element) */
#tab-solve .sv-sec, #tab-solve a.sv-sec, #tab-solve .sv-ghost, :is(#tab-positional, #tab-exercises, #tab-calc, #tab-vision) :is(button.primary, .solvebtn, .sv-sec, a.sv-sec, button.sv-ghost){
  font-family:inherit; font-size:12.5px; font-weight:400; letter-spacing:0;
  background:none; color:var(--cm-ink2);
  border:1px solid rgba(255,255,255,.14); border-radius:8px;
  padding:6px 12px; min-height:0; box-shadow:none; text-transform:none;
  cursor:pointer;
}
#tab-solve .sv-sec:hover, #tab-solve a.sv-sec:hover, #tab-solve .sv-ghost:hover, :is(#tab-positional, #tab-exercises, #tab-calc, #tab-vision) :is(button.primary, .solvebtn, .sv-sec, a.sv-sec, button.sv-ghost):hover{
  border-color:var(--cm-brass); color:var(--cm-brass-hi);
  background:none; transform:none;
}
/* the top strip's ghosts read quieter than the card's verbs */
#tab-solve .solve-top .sv-ghost{
  font:11.5px var(--cm-mono); border-color:var(--cm-line); color:var(--cm-mut);
}
#tab-solve .solve-top .sv-ghost:hover{ color:var(--cm-brass-hi); border-color:var(--cm-brass); }
#tab-solve .solve-top a{ font-size:12.5px; color:var(--cm-mut); }
#tab-solve .solve-top a:hover{ color:var(--cm-brass-hi); }

/* THE FILLED ADVANCE IS RETIRED (2026-08-03, the house voice): no verb
   on this site is a filled slab any more. The advance keeps its rank as
   the screen's one brass object — as a brass WORD in a brass hairline,
   dressed by the house layer at the end of this file. */
/* a Solve on every row is nine accents — rows stay quiet (the frame-voice
   law, restated at this layer's size) */
:is(#tab-positional, #tab-exercises, #tab-calc, #tab-vision) button.solvebtn{
  background:none !important; border-color:rgba(255,255,255,.14) !important;
  color:var(--cm-ink2) !important; font-weight:400;
}
:is(#tab-positional, #tab-exercises, #tab-calc, #tab-vision) button.solvebtn:hover{
  border-color:var(--cm-brass) !important; color:var(--cm-brass-hi) !important;
}

/* ---- the card: rank in the reading voice, facts in mono ---- */
#tab-solve .solve-side .sv-rank, #tab-solve .solve-side.v2 .sv-rank{
  font:italic 400 16px 'Libre Caslon Text',Georgia,serif;
  letter-spacing:0; line-height:1.45; color:var(--cm-ink);
}
#tab-solve .sv-idline{ font:11px var(--cm-mono); color:var(--cm-mut); }
#tab-solve .sv-idline .sv-idbtn{ color:var(--cm-mut); }
#tab-solve .sv-idline .sv-idbtn:hover{ color:var(--cm-brass-hi); }
#tab-solve .sv-deckpos{ color:var(--cm-mut2); font-variant-numeric:tabular-nums; }
#tab-solve .sv-meta > *{
  font:11px var(--cm-mono); color:var(--cm-brass-hi);
  background:var(--cm-brass-wash); border:1px solid rgba(216,176,120,.3);
  border-radius:99px; padding:3px 10px;
}
#tab-solve .sv-progress .sv-bar{ background:#232b31; border-radius:4px; overflow:hidden; }
#tab-solve .sv-progress .sv-bar i{ background:var(--cm-brass); }
#tab-solve .sv-prognums{
  font:11px var(--cm-mono); color:var(--cm-mut); font-variant-numeric:tabular-nums;
}
#tab-solve .sv-msg{ font-size:12.5px; color:var(--cm-ink2); }
#tab-solve .sv-statusrow h2{ font-size:12.5px; font-weight:600; color:var(--cm-ink2); }

/* ---- moves, links, aftermath ---- */
#tab-solve .sv-moves2{
  font:12px var(--cm-mono); color:var(--cm-ink2); font-variant-numeric:tabular-nums;
}
#tab-solve .sv-moveslbl{ font:11px var(--cm-mono); letter-spacing:.08em;
  text-transform:uppercase; color:var(--cm-mut); }
#tab-solve .sv-mstep, #tab-solve .sv-backsol{ color:var(--cm-mut); }
#tab-solve .sv-mstep:hover, #tab-solve .sv-backsol:hover{ color:var(--cm-brass-hi); }
#tab-solve .kbd, #tab-solve span.kbd{
  font:10px var(--cm-mono); color:var(--cm-mut2);
}

/* ---- train interiors: rows and chapters in the lifted voice ---- */
:is(#tab-positional, #tab-exercises, #tab-calc, #tab-vision) :is(h2, summary){
  font-size:13px; font-weight:600; letter-spacing:0; color:var(--cm-ink);
}
:is(#tab-positional, #tab-exercises, #tab-calc, #tab-vision) .ch-name{
  font-size:13px; font-weight:600; color:var(--cm-ink);
}
:is(#tab-positional, #tab-exercises, #tab-calc, #tab-vision) .ch-num{
  font:11px var(--cm-mono); color:var(--cm-mut2); font-variant-numeric:tabular-nums;
}
:is(#tab-positional, #tab-exercises, #tab-calc, #tab-vision) .ch-sub{
  font-size:11px; color:var(--cm-mut);
}
:is(#tab-positional, #tab-exercises, #tab-calc, #tab-vision) :is(.src, footer.col, .stlib-names){
  font-size:11px; color:var(--cm-mut);
}
:is(#tab-positional, #tab-exercises, #tab-calc, #tab-vision) .exdone{
  color:var(--cm-live);
}
#tab-positional .unit > span:not(.ct){ font-size:12.5px; color:var(--cm-ink2); }
#tab-positional .unit .uid{ font:11px var(--cm-mono); color:var(--cm-brass); }
#tab-positional .unit .ct{
  font:11px var(--cm-mono); color:var(--cm-mut); font-variant-numeric:tabular-nums;
}
#tab-positional .unit:hover{ background:var(--cm-surface2); }
#tab-vision :is(p, b, i, .sv-msg){ font-size:12.5px; }
#tab-vision .chip{
  font:11px var(--cm-mono); color:var(--cm-mut);
  border:1px solid var(--cm-line); border-radius:99px; padding:3px 10px;
  background:none;
}
#tab-vision .chip.ok, #tab-vision .chip.hot{
  color:var(--cm-brass-hi); border-color:rgba(216,176,120,.3);
  background:var(--cm-brass-wash);
}
#tab-vision .dlabel{ font:11px var(--cm-mono); letter-spacing:.08em;
  text-transform:uppercase; color:var(--cm-mut); }

/* ================================================================
   THE READING BOARD (2026-08-01) — the non-covered session
   ================================================================
   Scope: body.svpage:not(.cov-board). A covered session is prep and
   keeps every inch of its anatomy; this is the OTHER errand — the
   Explorer, or prep with the layer switched off — where you are
   reading a position rather than checking it against your book.

   What was wrong was not the palette, it was the arithmetic. Measured
   at 1600x1000: the board took 828px and the reading column 400px,
   and EIGHT of that column's children overflowed their boxes —
   "Carlsen,M" rendered into a 40px cell as "Carls...", the master-game
   totals cut at 49px, even the result glyph clipped. The screen was
   spending its width on a board that had stopped getting clearer and
   destroying the words that carry the answer.

   Its rows 3 and 4 (the book's heads and row widths) are the explorer
   session's and live in explorer-session.css; row 5 was deleted
   2026-08-11 (see the note at the end of this file). What follows is
   the geometry and the ordering, which are this surface's.
   ================================================================ */

/* 1. THE BOARD STOPS GROWING. --bd was min(100vh - 128px, 58vw), both
   of which keep climbing with the window; a chess board is fully
   legible around 660 and past that you are only drawing bigger pieces.
   The third term is the ceiling, and it hands ~170px back to the
   column — which is precisely what every truncation above needed.
   (The PUZZLE room raises this ceiling to 900 — see its own block near
   the end of this file. It is raised there and not here on purpose: the
   rooms on this surface do not share a chrome budget in practice, and
   660 -> 900 measured out as the database's status row printing under
   the strip at 1440x900. A room takes the taller board when its own
   composition has been measured, not before.)
   The rule that actually owned this is workbench.css "body.svpage #wbView
   .solve-grid", which pins the column with
   "minmax(280px, 400px) !important" — the 400 IS the truncation. Matching
   its ID and its !important is the only way past it without editing the
   shared rule, which would drag covered sessions along too.
   (--sv-chrome and --sv-side are workbench.css's: 116px and 430px.) */
@media (min-width: 1000px), (min-width: 700px) and (orientation: portrait){
  body.svpage:not(.cov-board) #wbView .solve-grid{
    --bd: min(calc(100dvh - var(--sv-chrome)), calc(100vw - var(--sv-side)), 660px);
    grid-template-columns: calc(var(--bd) + 28px) minmax(320px, 560px) !important; }
}

/* 2. THE SUBJECT COMES FIRST — in a GAME EXPLORER the master book and
   its games outrank the engine (the room's subject vs a second
   opinion). Since 2026-08-13 the one-face order block below states
   this for every session: content organs sit under the head, above
   the void; the engine leads the answer matter at the foot. */

/* 6. An empty message row still took its gap. It collapses now.
   NOT hidden outright: #svMsg is the solver's own feedback line, and the
   room blurb that sits in it in the Explorer is written there by JS.
   Hiding the element to remove a sentence would also silence "correct"
   and "try again" in a rep session with this layer switched off — the
   blurb is a JS concern and does not belong to a stylesheet. */
body.svpage:not(.cov-board) #svMsg:empty{ display: none; margin: 0; }

/* ==================================================================== */
/* THE HOUSE VOICE over the solver — part 2 of 2 (2026-08-03)           */
/* -------------------------------------------------------------------- */
/* Part 1 (house-voice.css) carries the tokens and the verb roster; this */
/* carries the same voice over the solver, and must outrank the calm-    */
/* puzzles verb face above it — which is why it sits at the end of this  */
/* file and leans on !important.                                        */
/* ==================================================================== */

/* the solve page's verbs, over the calm-puzzles layer */
#tab-solve .sv-sec, #tab-solve .sv-ghost{
  font-family:var(--serif) !important;
  font-size:13.5px !important; font-weight:400 !important;
  letter-spacing:.01em !important;
  color:var(--cm-ink2, var(--ink2)) !important;
  background:none !important;
  border:1px solid rgba(255,255,255,.12) !important;
  border-radius:3px !important;
}
#tab-solve .sv-sec:hover, #tab-solve .sv-ghost:hover{
  color:var(--acc-hi) !important;
  border-color:rgba(216,176,120,.55) !important;
  background:rgba(216,176,120,.06) !important;
}
/* (the advance's brass word/hairline pair that sat here died 2026-08-12:
   it was two !important rules re-stating what `.sv-act.go` in THE VERB
   already says, and their only remaining job was to beat the roster that
   no longer claims the class. `.sv-act.primary` went with them — no verb
   in this room wears `.primary` any more; see #svOppBtn's note in
   build/skeleton_rooms.py for why that class had to go.) */

/* ---- rules deleted here 2026-08-11, each with zero emitters ----------
   .sv-idrow  (body.svpage.repmode .sv-idrow{display:none}) — the id row
   the svpage banner still describes is #svIdrow's ancestor by another
   name; no module writes this class.
   .sm-btn    (the repmode structure-cart button face) — the live class
   is .sm-act, dressed in house-voice.css.
   .sv-morein (an 11px mono line under the card) — no writer.
   READING BOARD row 5, "A SCORE IS DATA, NOT A BADGE": it addressed
   .sf-sc, and the engine's score element has always been .sf-chip
   (07-daily-sf.js ~517). The block never matched, so the filled pills it
   was written to flatten are still filled — the intent is recorded in
   reports/T1-OVERRIDES-DISSOLVED-2026-08-11.md and is a design call, not
   a rename to make silently. */

/* ==================================================================== */
/* THE PUZZLE ROOM TAKES THE DOOR VOICE (2026-08-11)                    */
/* -------------------------------------------------------------------- */
/* Owner: "the only thing the user sees on the page is exactly what they */
/* need for that moment … the board page should look like the homepage." */
/*                                                                      */
/* SCOPE IS THE WHOLE PAGE (2026-08-13, the one-face rework). #tab-solve */
/* is shared — puzzles, drill, spar, build and the explorer all render   */
/* here — and since the session-layer rework they all wear THIS plate:   */
/* `body.svpage` is the scope, sessions pour their content into the same */
/* organs, and body.repmode survives only as the marker the puzzle-only  */
/* PHASE rules (svNext / hint / reveal / the solving blur) key their     */
/* :not() on — a session has no solved phase, so its verbs must stand.   */
/*                                                                      */
/* WHY PINE, MEASURED. The ground was #131a15, which made the board's    */
/* own outer edge the LOUDEST contrast on the screen — 15.00x against    */
/* the light squares, above the 14.61x of a black piece on a light       */
/* square, which is the strongest thing you actually have to read. The   */
/* frame outshouting the content is the wrong ranking for a task that is */
/* all focus and visualisation, and it lands in the periphery where the  */
/* eye is most sensitive to luminance steps. Pine #24382d drops that     */
/* edge to 10.60x — under the information peak — while holding the       */
/* board's boundary at 3.73x on the dark squares, above the 3:1 that     */
/* WCAG 1.4.11 asks of a graphical boundary. Buff was measured and       */
/* DISQUALIFIED at 1.10x: the puzzles door is buff, but a buff room      */
/* would dissolve the board's light squares into the page. The landing's */
/* own pine and the perceptual answer are the same colour.               */
/*                                                                      */
/* Tokens are --dv-* (door-frame.css declares them; reads are always     */
/* legal). Every use carries a fallback — this layer is gated on a BODY  */
/* CLASS, not the theme attribute, and an undefined var() paints SVG     */
/* black. !important answers the house-voice block above, which uses it. */
/* ==================================================================== */

body.svpage #wbView{ background:var(--dv-pine,#24382d); }

/* ---- THE PLATE — the landing's composition, at the board's side -------
   THE COLUMN IS THE CONTAINER, so the type scales to the PLATE and not to
   the viewport: this is the landing's own trick (openings-home .oh-state)
   and it is what keeps a card's name monumental on a 2000px monitor without
   a media query per step. Before this, a 25px title sat top-left in a 950px
   column and the remaining ~700px read as a void rather than as air.
   inline-size, not size: this column is a flex child with max-height and
   overflow-y:auto, so its height is not definite and `size` containment
   would collapse it. cqi is all the plate needs. */
body.svpage #tab-solve .solve-side.v2{
  container-type:inline-size;
  /* NOT cq units: this element IS the query container, so cqi in its own
     padding is self-referential. openings-home.css records the same trap
     ("the browser resolved 1cqi to 2.09px instead of ~4 and every cq-sized
     descendant came out half scale"); here it dropped a clamp(25px,…) title
     to 9.92px — BELOW its own stated minimum, which is the tell. The
     container's own box must be stated in units that do not depend on it. */
  padding:6px 8px 0 0;
}
/* THE PLATE HANGS FROM THE BOARD, NOT FROM THE TOP OF THE PAGE
   (2026-08-12). Measured at 1600x1000 before this: board 26→910, plate
   26→289, and 621px of empty ground under a four-line caption — the screen
   read as unfinished rather than as air. Centring the column was the
   obvious answer and the wrong one: the plate's height changes with the
   phase (263px solving, ~600px answered), so a centred title JUMPS between
   cards and the eye loses it.
   --bd is the board's size and this room's single source of it, so a
   fraction of --bd is an offset that scales with the board and holds still
   across phases: the title lands a sixth of the way down, the plate grows
   into the remaining five sixths, and nothing moves when the card is
   answered. The cap keeps it honest on a short viewport.
   GATED, because the offset only means anything BESIDE the board. Below
   1000px the frame stacks the plate UNDER it (workbench.css, "portrait:
   the control card goes UNDER the board") and the same rule printed 150px
   of dead ground between the board and the title — measured 375x812. */
@media (min-width: 1000px){
  body.svpage #tab-solve .solve-side.v2{
    padding-top:min(calc(var(--bd, 660px) * .16), 150px);
  }
}
/* the card is named ONCE, monumentally, the way the landing states its one
   number. max-width is in CH so the measure holds as the type grows — a
   title is prose, not a figure, and 15ch is where Caslon still reads. */
body.svpage #tab-solve .solve-side.v2 .sv-rank{
  font-family:var(--serif,'Libre Caslon Text',Georgia,serif);
  font-size:clamp(26px, 7cqi, 46px); font-weight:400;
  line-height:1.06; letter-spacing:.01em; max-width:15ch;
  color:var(--dv-buff-ink,#efe9d6);
}
/* the figures: mono caps, the landing's .oh-fact rhythm, in the flag.
   LEFT-SET, NOT SPREAD (2026-08-12). The base lays this row out for a
   280px panel: `.sv-idsp{flex:1}` shoves the ♥/⧉ pair to the far edge,
   which at this room's 560px column marooned them 400px from the id they
   act on. A plate is a caption — its lines start at the same margin and
   end where they end. (The prognums below had the same disease in its
   own words: `justify-content:space-between` with an empty first child
   printed "1 SOLVED" against the right edge of the screen, 550px from
   the ribbon it was counting.) */
body.svpage #tab-solve .sv-idline{
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace);
  font-size:clamp(10px, 2.1cqi, 12px); letter-spacing:.14em;
  text-transform:uppercase; color:var(--dv-flag-lt,#e0906c);
  margin-top:1.5em; justify-content:flex-start; gap:11px;
}
body.svpage #tab-solve .sv-idsp{ display:none; }
/* the live line — "try again", "✓ solved" — is the plate's one italic
   voice, the landing's .oh-line exactly. It is the only thing here that
   speaks in sentences, so it is the only thing set in italic. */
body.svpage #tab-solve #svMsg{
  font-family:var(--serif,'Libre Caslon Text',Georgia,serif);
  font-style:italic; font-size:clamp(13px, 2.6cqi, 17px); line-height:1.5;
  max-width:26ch; margin-top:1.1em; color:var(--dv-sage,#a9b8a6);
  border:0; padding:0; background:none;
}
body.svpage #tab-solve #svMsg.good{ color:var(--dv-buff,#e9e1cc); }
body.svpage #tab-solve .sv-idline .sv-idbtn{ color:var(--dv-moss,#5d6b5f); }
body.svpage #tab-solve .sv-idline .sv-idbtn:hover{ color:var(--dv-flag-lt,#e0906c); }
/* where you stand, under the board — the study room's own title row */
body.svpage #tab-solve .sv-statusrow h2{
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace);
  font-size:10px; letter-spacing:.16em; color:var(--dv-sage,#a9b8a6);
}
/* the deck's progress, as the landing's ribbon: a short measured track, not
   a hairline stretched across the whole column */
body.svpage #tab-solve .sv-progress{ margin-top:1.6em; }
body.svpage #tab-solve .sv-bar{
  width:min(100%, 46cqi); height:5px; background:rgba(233,225,204,.14);
}
body.svpage #tab-solve .sv-bar i{ background:var(--dv-buff,#e9e1cc); }
body.svpage #tab-solve .sv-prognums{
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace);
  font-size:10px; letter-spacing:.12em; text-transform:uppercase;
  color:var(--dv-moss,#5d6b5f); margin-top:.6em;
  justify-content:flex-start; gap:14px;
}
/* an empty flex child still spends the row's gap — #svPos is blank in a
   pile session, and its 14px indented "1 SOLVED" out of line with every
   other line on the plate. Empty says nothing, and now costs nothing. */
body.svpage #tab-solve .sv-prognums > :empty{ display:none; }

/* ---- the line you played: a scoresheet, in the room's own ink --------
   The move list arrived from the sidebar era wearing graphite hairlines,
   6px radii and a brass wash on the current move — three inks that are
   not this room's. It is the one place the answer is written down, so it
   reads as the landing's own material: a buff rule above it, square
   steppers, and the move you are standing on marked in the flag. */
body.svpage #tab-solve .sv-moveswrap{
  border-top:1px solid rgba(233,225,204,.14);
  margin-top:26px; padding-top:13px;
}
body.svpage #tab-solve .sv-moveslbl{
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace);
  font-size:10px; letter-spacing:.16em; color:var(--dv-moss,#5d6b5f);
}
body.svpage #tab-solve .sv-mstep{
  border:1px solid rgba(233,225,204,.22); border-radius:0;
  color:var(--dv-sage,#a9b8a6);
}
body.svpage #tab-solve .sv-mstep:hover{
  border-color:rgba(224,144,108,.5); color:var(--dv-flag-lt,#e0906c);
}
body.svpage #tab-solve .sv-moves2{
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace);
  font-size:12px; color:var(--dv-buff-ink,#efe9d6);
}
body.svpage #tab-solve .sv-moves2 i{ color:var(--dv-moss,#5d6b5f); }
body.svpage #tab-solve .sv-moves2 .svm{
  color:var(--dv-buff-ink,#efe9d6); border-radius:0;
}
body.svpage #tab-solve .sv-moves2 .svm:hover{
  background:rgba(233,225,204,.09);
}
body.svpage #tab-solve .sv-moves2 .svm.cur{
  background:none; color:var(--dv-flag-lt,#e0906c);
  box-shadow:inset 0 -1px 0 var(--dv-flag-lt,#e0906c);
}
body.svpage #tab-solve .sv-backsol{
  border:1px solid rgba(224,144,108,.5); border-radius:0; background:none;
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace);
  font-size:10.5px; letter-spacing:.05em; color:var(--dv-flag-lt,#e0906c);
}
body.svpage #tab-solve .sv-backsol:hover{
  background:var(--dv-flag,#a8402c); border-color:var(--dv-flag,#a8402c); color:#f2e8d8;
}


/* the board gets air on the side the retired nav column used to give it by
   accident (the ghost track above): 7px from the viewport edge read as a
   crop, not a margin. Costs the board nothing — it is height-bound here
   (660px at 900vh, with 70px of width slack beside the plate). */
@media (min-width: 1000px){
  body.svpage .solve-grid{ padding-left:26px; }
  /* THE PAIR IS COMPOSED, NOT STRETCHED. Both tracks are FIXED (block 1
     pins them with !important, and that is the right owner — this rule
     must not restate them or the two will drift). Fixed tracks in a wider
     grid leave the slack wherever the alignment puts it, and the default
     put ALL of it on the right: measured at 2000x1200, 750px of empty
     ground past the plate, which reads as an unfinished page rather than
     as margin. Centring on both axes spends the slack as symmetric air. */
  /* THE PUZZLE ROOM TAKES A TALLER BOARD — 900, against the surface's 660
     (block 1 above). 660 was chosen to hand ~170px back to a column that
     was truncating; this room's plate truncates nothing, and on a large
     monitor the ceiling was costing the board and paying nobody — measured
     at 2000x1200, board 660 = 55% of viewport height with ~450px of dead
     ground beneath it, against the board-first law's "the board takes
     min(free height, free width)". 900 puts it at 75%, the same figure the
     openings study room measures, and still leaves the plate its 560.
     It is raised HERE and not at the shared rule because the raise is only
     safe where the whole composition has been measured: applied to the
     surface it pushed the DATABASE room's status row under the strip at
     1440x900. That room takes its taller board in its own sitting.
     The selector matches block 1's EXACTLY (:not(.cov-board) and #wbView
     included) — that rule owns --bd at equal weight and only cascade order
     lets this one win; an unscoped override loses to it silently. The
     2026-08-13 widen tripped precisely that wire (the live A-B-A measured
     the puzzle board 784 -> 660 at 1440x900) and the scope came back as
     :not(.cov-board), which is also the truth: under the covered layer the
     anatomy sizes its own board and this raise must stand down. */
  body.svpage:not(.cov-board) #wbView .solve-grid{
    --bd: min(calc(100dvh - var(--sv-chrome)), calc(100vw - var(--sv-side)), 900px);
  }
  body.svpage .solve-grid{
    /* min-height is what makes align-content mean anything: the grid's own
       height is its content's, so with nothing to distribute the centring
       was a no-op and the slack all fell BELOW the board (measured 160px at
       2000x1200). Giving the grid the view's height hands it that slack to
       split. --sv-chrome is workbench.css's 116px budget. */
    min-height:calc(100dvh - var(--sv-chrome, 116px));
    justify-content:center; align-content:center;
    column-gap:clamp(20px, 3vw, 64px);
  }
  /* THE CHAT RAIL IS FIXED OVER THE FRAME (chrome-redesign: #labChat 34px,
     z-index 60; `body{margin-right:34px}` reserves it for the document flow,
     which a 100dvh grid ignores). At 1440x900 the pair fills the row and
     the plate's last 16px sat UNDER the rail — invisible while the plate
     was left-set prose, plain the moment the instrument put right-aligned
     figures there (measured 2026-08-18: elementFromPoint at the games
     column's own pixels returned .lc-rail). The grid clears the rail;
     body.lc-on (chat open) already clears the panel with margin-right. */
  body.svpage:not(.lc-on) .solve-grid{ padding-right:calc(1.1rem + 34px); }
}
/* a 0% track is the emptiest fact there is; svMeta hides it until the
   first solve, and this is the rule that lets `hidden` mean it here */
body.svpage #tab-solve .sv-progress[hidden]{ display:none; }

/* ---- THE VERBS: mono words in warm hairlines, never filled at rest ---
   COMPACT WORDS, LEFT-SET — the landing's .oh-verbs row, and the same
   material the two shipped door rooms wear (.oh-verb, .lr-big).

   NOT ONE !important IN THIS BLOCK, and that is the whole point of the
   2026-08-12 consolidation above: `.sv-act` used to be claimed by four
   files with !important, so the room could only answer in kind, and a
   room that can only shout cannot be tuned. It is one class, one owner,
   one base — so this block wins by being more specific, the way CSS is
   supposed to work, and the next change here is a one-line change.

   SIZE, MEASURED. The words were 11px/8px-14px against a 46px Caslon
   title and a 900px board: 32px tall, which is under the 44px pointer
   target and read as chiclets dropped in a void. 12px on .06em with
   11px/17px padding puts them at 38px and gives the plate its missing
   middle register — small enough to stay quiet beside the title, big
   enough to be the thing you reach for. */
body.svpage #tab-solve .sv-actions{
  /* flex-direction is STATED, not inherited: the base lays .sv-actions
     out twice (bare and .solve-side.v2-scoped), so a rule that only says
     display:flex here can still inherit a column. */
  display:flex; flex-direction:row; flex-wrap:wrap;
  gap:9px; margin-top:26px; row-gap:9px;
}
body.svpage #tab-solve .sv-actions .sv-act{
  width:auto; flex:none; white-space:nowrap;
}
body.svpage #tab-solve .sv-act{
  padding:11px 17px; min-height:0;
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace);
  font-size:12px; letter-spacing:.06em; line-height:1;
  color:var(--dv-buff-ink,#efe9d6);
  background:none;
  border:1px solid rgba(233,225,204,.26);
  border-radius:0;
}
body.svpage #tab-solve .sv-act:hover{
  color:var(--dv-flag-lt,#e0906c);
  border-color:rgba(224,144,108,.5);
  background:none;
}
body.svpage #tab-solve .sv-act:focus-visible{
  outline:2px solid var(--dv-flag-lt,#e0906c); outline-offset:2px;
}
/* the RETREAT is the quietest verb on the plate — it is the way back, not
   an offer. A word with no hairline, the door voice's .oh-ghost. */
body.svpage #tab-solve .sv-act.sv-back{
  border-color:transparent; padding-left:2px; padding-right:10px;
  color:var(--dv-moss,#5d6b5f);
}
body.svpage #tab-solve .sv-act.sv-back:hover{
  border-color:transparent; color:var(--dv-buff,#e9e1cc);
}
/* the armed verb wears the flag standing, and the hover FILL is the door
   voice's native inversion — the one place a fill is legal */
body.svpage #tab-solve .sv-act.go{
  color:var(--dv-flag-lt,#e0906c);
  border-color:rgba(224,144,108,.55);
}
body.svpage #tab-solve .sv-act.go:hover{
  background:var(--dv-flag,#a8402c);
  border-color:var(--dv-flag,#a8402c);
  color:#f2e8d8;
}
/* ONE WAY ON, PER PHASE. `next card` is a SKIP while you are solving; the
   advance once you are done is the .sv-bignext svFinish injects. Both on
   screen at once stated one fact twice. Since 2026-08-12 the injected one
   is BORN a `.sv-act go` in the verb row (05-solver), so it needs no face
   of its own — only the ranks below, and the fill/animation the house era
   left on the class. */
body.svpage:not(.repmode):not(.sv-solving) #tab-solve #svNext{ display:none; }
body.svpage #tab-solve .sv-bignext{
  display:flex; width:auto; margin:0; animation:none;
  font-size:12px; font-weight:400; letter-spacing:.06em; text-transform:none;
  padding:11px 17px;
}
/* THE ANSWERED CARD RETIRES ITS OWN VERBS. `hint` and `reveal` act on a
   question; once it is answered they are two dead words at the top of the
   row you actually want (the advance). The phase already exists —
   body.sv-solving, dropped by svPhase the moment the card is done — so
   this is the same one-fact-per-phase rule the engine block uses. */
body.svpage:not(.repmode):not(.sv-solving) #tab-solve #svHintBtn,
body.svpage:not(.repmode):not(.sv-solving) #tab-solve #svReveal{ display:none; }

/* the way out and the strip's ghosts read quietest of all */
body.svpage #tab-solve .solve-top a,
body.svpage #tab-solve .solve-top .sv-ghost{
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace) !important;
  font-size:10.5px !important; letter-spacing:.06em !important;
  color:var(--dv-moss,#5d6b5f) !important;
  border-color:transparent !important; border-radius:0 !important;
}
body.svpage #tab-solve .solve-top a:hover,
body.svpage #tab-solve .solve-top .sv-ghost:hover{
  color:var(--dv-buff,#e9e1cc) !important;
}

/* ---- THE MOMENT: while you are solving, the answer is not on screen --
   The engine, the analysis links and the game citation ARE the answer;
   the video chip names the structure, which is the hint. A screen that
   shows them beside the question is not a puzzle. They arrive the instant
   the card is answered — svPhase (05-solve-board) drops body.sv-solving on
   svFinish, and study cards never wear it because they have nothing to
   solve. Nothing is deleted and nothing moves: this is a phase, so the
   room does not reflow when the card is done, it fills in.
   Visibility and ORDER of the engine block on this page are already this
   file's (the order block below); its DRESS stays engine-pane.css's. */
/* (.sv-links and #svAfter left this list 2026-08-12 by leaving the room —
   there is no longer an answer to put away here, only #svChips, which the
   rep sessions still write, and the id row's own two buttons.) */
body.sv-solving:not(.repmode) #tab-solve .solve-side.v2 > #svChips,
body.sv-solving:not(.repmode) #tab-solve .sv-idline .sv-idbtn{ display:none; }
/* THE ENGINE IS A SWITCH, NOT A VERB (owner, 2026-08-12: "instead of
   analysis being a button, it should always be in this format — you just
   click analysis to turn it on, off"). The row is RESIDENT at every phase.
   That does not put the answer beside the question: the row is a switch and
   a nameplate, and #sfPanelSolve — the evaluation and the lines, which are
   the answer — carries `hidden` until SF.on, which only a click sets.
   The .sv-peek indirection this replaces (a verb whose one job was to reveal
   a control that was already a control) died with #svEngBtn: two switches
   for one engine was the quiet-screen law broken on its own example. */

/* ---- narrow, and LAST in this layer (a media query adds no specificity,
   so it must follow every rule it answers) ---------------------------------
   The way home clears ☰. solve-top's 1.1rem inset puts the back word at
   x=18 while #sideTgl occupies 9–43, so the two have been printing on top
   of each other on every board session at this width — measured 375x812,
   25px of overlap, and it predates this pass. The ☰ is the FRAME's, so the
   clearance is stated for the whole solve page rather than this one room. */
@media (max-width: 1000px){
  body.svpage .solve-top{ padding-left:52px; }
}

/* ---- the three rules that sat in explorer-session.css (index 74, AFTER
   this file) and dressed EVERY session's move stepper, not the explorer's.
   They keep their cascade position by landing at this file's end. ---- */
/* explorer-session.css:287 */
#tab-solve .sv-mstep{ border:1px solid rgba(255,255,255,.12); border-radius:6px; background:none;
  color:var(--cm-ink2); padding:2px 10px; cursor:pointer; }
/* explorer-session.css:291 */
#tab-solve .sv-mstep:hover{ border-color:var(--cm-brass); color:var(--cm-brass-hi); }
/* explorer-session.css:292 */
#tab-solve .sv-mstep[disabled]{ opacity:.35; }

/* ====================================================================== */
/* T5 — THE PLATE GETS A SKELETON (2026-08-12)                            */
/* ---------------------------------------------------------------------- */
/* Owner: "past the first layer it gets ugly fast — once you hit one of    */
/* the buttons or solve the puzzle it gets super ugly super fast … the     */
/* home landing page is so elegant".                                       */
/*                                                                        */
/* THE PAINT WAS NOT THE DEFECT. The block above already wears the         */
/* landing's material — pine, Caslon, the clock-flag red — and the pine    */
/* ground has a measurement behind it. What the plate did not have was a   */
/* SKELETON: it was a flex column whose CHILD COUNT changed with the       */
/* phase, so every composition decision above was renegotiated the moment  */
/* anything happened. Measured at 1280x720, one card's life:               */
/*                                                                        */
/*   .sv-actions top   fresh 331px -> revealed 455px -> answered 540px     */
/*   .sf-row top       fresh 407px ->                    answered 643px     */
/*                                                                        */
/* The verb row moved 209px and the engine row 236px WITHIN ONE CARD, and  */
/* pressing `hint` re-labels its own button ("no hint for this one"),      */
/* which grew the cell 63px -> 171px and shoved the two verbs beside it    */
/* 126px right. The thing under the pointer moved before it was pressed.   */
/* The file comment at "THE MOMENT" claims "nothing moves … it fills in";  */
/* that was the intent, and the flex column could not keep it.             */
/*                                                                        */
/* THE SKELETON IS TWO RULES, and neither depends on how many children     */
/* are on screen:                                                          */
/*   1. NOTHING IS EVER INSERTED ABOVE THE HEAD. Every child that arrives  */
/*      when the card is answered (#svChips, #svAfter, .sv-links, the      */
/*      engine panel) is ORDERED into the bottom group, so it grows        */
/*      DOWNWARD into the void and no line above it can move. #svChips is  */
/*      the one that had to travel: in markup it sits between the id line  */
/*      and the message, which is why answering a card pushed the whole    */
/*      middle of the plate down ~50px. It is after-matter and now reads   */
/*      with the citation.                                                 */
/*   2. THE RANK IS PINNED. `margin-top:auto` puts the verb band at the    */
/*      bottom of the column and `position:sticky` holds it there when the */
/*      content behind it overflows. The band's position is not a          */
/*      consequence of what is above it any more — at any phase, any       */
/*      width, the verbs are in the same place.                            */
/* The plate stretches to the board's height (align-self), so that place   */
/* is the board's own bottom edge.                                         */
/*                                                                        */
/* THE BAND IS A RANK OF SQUARES — the landing's grammar, which divides    */
/* full-bleed panels by their edges and boxes nothing. Cells share the     */
/* band; the phase changes how many there are, never how tall it is. Ten   */
/* px of hairline is the whole ornament, no fill AT REST (the cells' own   */
/* background stays transparent — the pine belongs to the band, and is     */
/* there so scrolled content does not print through a sticky element), and */
/* the hover inversion is the door voice's own.                            */
/*                                                                        */
/* THE BIG WORD IS THE STATE. 05-solver's svVerdict writes it; the deck's  */
/* name moved to the fact line. The h2 under the board that used to carry  */
/* the outcome at 10px goes quiet here — the quiet-screen law, which is    */
/* also why it was the wrong place for it.                                 */
/*                                                                        */
/* TYPE: FOUR ROLES, THE LANDING'S. The plate measured ELEVEN font sizes   */
/* (9.92 / 10 / 10.5 / 11 / 11.2 / 11.52 / 12 / 13.12 / 14.35 / 16 /       */
/* 38.64) and seven text colours in one 560px column, because eight        */
/* layers each dressed one organ. The landing states everything it has to  */
/* say in THREE (47.79 Caslon caps / 14.08 Caslon / 10.67 mono caps) and   */
/* two colours per ground. Everything small on this plate collapses into   */
/* the fact role and separates by COLOUR — moss for a quiet fact, the flag */
/* for a live one — which is how the landing separates its own.            */
/*                                                                        */
/* Scope is body.svpage — every screen on this page (2026-08-13): the     */
/* puzzle room AND the sessions, whose painters feed these same organs.    */
/* plAudit's puzzle-room + session rows are the probe — the answer rows    */
/* need these to stay DIRECT children, so this is ordering and dress,      */
/* never a new wrapper.                                                    */
/* ====================================================================== */

/* ---- the column: full height beside the board, packed from the top ---- */
body.svpage #tab-solve .solve-side.v2{
  display:flex; flex-direction:column; gap:0;
}
/* NOTHING SQUASHES — the plate scrolls instead. A flex item's default
   shrink is 1, so the moment the column's content exceeded its box every
   child gave up height: measured at 375x812, the engine row went 49px ->
   16px, which is SHORTER than the 27px switch inside it, and .sf-row's own
   overflow:hidden then clipped `Analysis` out of existence. It read as a
   blank band between two rules, and elementFromPoint at the switch's own
   centre returned the plate — a control that was neither visible nor
   clickable, with nothing in the DOM to say so. Silent failure is a bug of
   its own; a scrollport is the honest way to be out of room. */
body.svpage #tab-solve .solve-side.v2 > *{ flex:0 0 auto; }
@media (min-width: 1000px){
  body.svpage #tab-solve .solve-side.v2{
    /* the grid row is the board's height; stretching into it is what puts
       the band level with the board's bottom edge. max-height (set for the
       svpage rail above) would cap the
       stretch at 100dvh-92 and float the band off the floor.
       contain:size (2026-08-13): the plate's CONTENT must never size the
       row. The sessions proved the latent hole the puzzle plate never hit:
       the build/explorer book panel made this column taller than the
       board, the row grew past the height-locked frame, and the verb band
       sat unreachable below it — the T5 narrow bug, at wide. Containment
       zeroes the plate's contribution to track sizing, so the row is the
       board's alone; the plate stretches into it, its overflow scrolls
       (the svpage rail rule above), and the sticky band pins to the
       board's floor. (The container-query header note rejected `size` for
       the old flex configuration; under stretch-into-a-definite-row it is
       exactly right, and the cqi query keeps its inline subject.) */
    align-self:stretch; max-height:none; min-height:0;
    contain:size;
  }
}

/* ---- 1. the order: the head is fixed, everything new lands below ------ */
body.svpage #tab-solve .solve-side.v2 > #svRank{ order:1; }
body.svpage #tab-solve .solve-side.v2 > #svMsg{ order:2; }
body.svpage #tab-solve .solve-side.v2 > .sv-idline{ order:3; }
body.svpage #tab-solve .solve-side.v2 > .sv-progress{ order:4; }
/* session content — the room's SUBJECT (the explorer's note slot, book,
   games) — sits UNDER the head and grows down into the void; the engine
   keeps leading the answer matter at the foot. For puzzles every one of
   these is empty or hidden, so the plate is unchanged. #svBook / #exGames
   share one order so exOrganOrder's DOM swap (your game outranks the book
   when one is loaded) still decides their tie. (#exLabBtn / #exActs /
   #smWrap left this list 2026-08-18: the explorer's verbs are cells of
   the band now — block 4c — and the wrapper row and the structure
   launcher panel have no emitter.) */
body.svpage #tab-solve .solve-side.v2 > #svAfter{ order:11; }
body.svpage #tab-solve .solve-side.v2 > #svBook,
body.svpage #tab-solve .solve-side.v2 > #exGames{ order:12; }
/* THE VOID IS ONE GAP, AND IT IS THE LANDING'S — a head at the top, air
   through the middle, everything else gathered at the foot (where the home
   squares put their cropped glyph). One `margin-top:auto` makes that gap,
   and the item that carries it must be on screen at EVERY phase or the gap
   vanishes with it: .sf-row is the only one — the engine's switch row is
   resident by law (plAudit, "the engine is hidden, not withheld"), while
   the moves, the chips, the citation and the links all come and go. So the
   bottom group is led by the switch and the answer's own matter follows
   it, rather than the reverse. */
body.svpage #tab-solve .solve-side.v2 > .sf-row{
  order:20; margin-top:auto;
}
body.svpage #tab-solve .solve-side.v2 > #sfPanelSolve{ order:21; }
body.svpage #tab-solve .solve-side.v2 > #svMovesWrap{ order:22; }
body.svpage #tab-solve .solve-side.v2 > #svChips{ order:23; }
body.svpage #tab-solve .solve-side.v2 > .sv-actions{ order:30; }

/* ---- 2. the head: the landing's word / line / fact, at fixed heights -- */
/* THE ONE BIG WORD, in the landing's own setting: .hl-word is Caslon
   uppercase on .12em (measured 47.79px / 5.73px on the home squares). The
   clamp is the plate's, not the viewport's — 7cqi against this column as
   the container, which plAudit asserts as a RANGE because the scaling is
   the point. */
body.svpage #tab-solve .solve-side.v2 .sv-rank{
  text-transform:uppercase; letter-spacing:.12em; max-width:none;
  margin:0;
}
body.svpage #tab-solve .solve-side.v2 .sv-rank.ok{
  color:var(--dv-buff,#e9e1cc);
}
body.svpage #tab-solve .solve-side.v2 .sv-rank.bad{
  color:var(--dv-flag-lt,#e0906c);
}
/* the sentence: THE SLOT IS RESERVED WHETHER OR NOT IT SPEAKS. The reading
   board's `#svMsg:empty{display:none}` collapses the row, which on a fresh
   card pulled the fact line 48px up and dropped it again on the first move
   — a jump inside one card, from the rule that exists to keep the rep rail
   tight. Reserved air is not a fact wearing a costume; a collapsing slot
   is a moving screen. */
body.svpage #tab-solve #svMsg{
  min-height:3.1em; margin:1.15em 0 0; align-items:flex-start;
}
body.svpage #tab-solve #svMsg:empty{ display:flex; }
body.svpage #tab-solve #svMsg.bad{ color:var(--dv-flag-lt,#e0906c); }
/* the fact line and the ribbon under it are one block */
body.svpage #tab-solve .sv-idline{ margin-top:.6em; }
body.svpage #tab-solve .sv-progress{ margin-top:1.2em; }

/* ---- 3. THE PAGE'S TYPE, STATED ONCE (owner, 2026-08-12: "all the text
   should be different fonts than they are now … including STOCKFISH 18
   lite text, i'm talking literally every piece of text on this page") -----
   The plate was mono end to end — Spline Sans Mono carried the fact line,
   the ribbon count, the moves, the verbs, the engine's nameplate — with
   Caslon on the two display lines. A monospace is a typeface for columns of
   code; worn by every phrase in a room it makes prose read as output.

   The site already ships three families and no fourth is worth 40 KB of
   base64 for one room, so this is a REASSIGNMENT, not an acquisition:
     Libre Caslon Text — the verdict and the one italic sentence. The
                         landing's own display voice, and the thing the
                         owner named as elegant. It stays.
     Schibsted Grotesk — EVERY other piece of text in the room. The fact
                         line, the ribbon, the scoresheet, the verbs, the
                         engine row and its nameplate.
   Figures get tabular numerals and .14em of tracking; prose gets .02em.
   CAPS ARE FOR FIGURES ONLY — "3 SOLVED" and "CARD 3 OF 113" are measured
   quantities and uppercase is what makes them read as such; a title or a
   verb set the same way just shouts.
   Stated as ONE selector list so the room has one answer about its type,
   and placed after the door-voice block it supersedes rather than editing
   that block in place — its Caslon/mono assignment is the record of what
   this replaced. */
body.svpage #tab-solve .sv-idline,
body.svpage #tab-solve .sv-deckpos,
body.svpage #tab-solve .sv-idline .sv-idbtn,
body.svpage #tab-solve .sv-prognums,
body.svpage #tab-solve .sv-moveslbl,
body.svpage #tab-solve .sv-meta > *,
body.svpage #tab-solve .sv-moves2,
body.svpage #tab-solve .sv-mstep,
body.svpage #tab-solve .sv-backsol,
body.svpage #tab-solve .sv-act,
body.svpage #tab-solve .sf-btn{
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-variant-numeric:tabular-nums;
}
/* (.eng-name / .eng-depth / the MultiPV stepper take the same grotesk in
   engine-pane.css's own door-voice block — that surface's dress is its
   file's, and out-specifying it from here is how a class ends up with two
   owners. This room states the engine block's ORDER and VISIBILITY only.) */
/* the figures */
body.svpage #tab-solve .sv-idline,
body.svpage #tab-solve .sv-prognums,
body.svpage #tab-solve .sv-moveslbl{
  font-size:clamp(10px, 2.1cqi, 12px); letter-spacing:.14em;
  text-transform:uppercase;
}
body.svpage #tab-solve .sv-idline .sv-idbtn{
  font-size:clamp(11px, 2.3cqi, 13px); line-height:1; letter-spacing:0;
}
/* the prose */
body.svpage #tab-solve .sv-meta > *{
  font-size:clamp(11px, 2.2cqi, 13px); letter-spacing:.02em;
  text-transform:none;
  background:none; border:0; border-radius:0; padding:0;
  color:var(--dv-flag-lt,#e0906c);
}
body.svpage #tab-solve .sv-meta > *:hover{
  color:var(--dv-buff,#e9e1cc);
}
body.svpage #tab-solve #svChips{ margin-top:1.4em; }
/* THE ENGINE'S NAMEPLATE STAYS, AND ONLY BECAUSE OF THE LICENCE. Under the
   owner's "strong bias towards not having text" it is the first thing that
   should go — it is a credit, not a control, and it says nothing about the
   position. Stockfish is GPLv3 and this is the app's only visible
   attribution of it, so it is not mine to delete in a type pass. Its size
   and family are engine-pane.css's; what this room owns is the switch's
   own label. */
body.svpage #tab-solve .sf-btn.eng-toggle{
  font-size:clamp(10px, 2.1cqi, 12px); letter-spacing:.14em;
  font-weight:500;
}

/* the outcome is stated ONCE, and the plate's big word is where. This row
   carried it at 10px in the bottom-left corner of the screen, 29px above
   the strip and under the board's file letters — the smallest type on the
   screen reporting the only thing that had changed. */
body.svpage #tab-solve .sv-statusrow{ display:none; }

/* ---- 3b. THE SCORESHEET: two ply to the line ---------------------------
   A move list is a TABLE everywhere it is done properly, and for one
   reason: the number is a row label, so White is always the first column
   and Black always the second, and a move is findable by eye. As an inline
   stream the same move sat somewhere different on every card and a long
   line broke wherever the column happened to end. 05-solver emits the rows;
   this is their measure. Fixed em columns rather than subgrid — every row
   states the same three tracks, so they agree without one. */
body.svpage #tab-solve .sv-moves2{
  font-size:clamp(12px, 2.4cqi, 14px); line-height:1.5; max-height:none;
}
/* the tracks are MEASURED, not fractional: `1fr 1fr` spent the plate's whole
   560px on two moves, so White sat at x=520 and Black at x=660 with an
   80px gulf between a pair that belongs together. A move is at most six
   characters; the column is sized to the move and the rest of the row is
   left as margin, which is what a printed sheet does. */
body.svpage #tab-solve .sv-mrow{
  display:grid; grid-template-columns:3.4em 6.6em 6.6em;
  align-items:baseline; column-gap:.4em;
}
body.svpage #tab-solve .sv-mrow > i{
  font-style:normal; text-align:right;
  font-size:clamp(10px, 2cqi, 11.5px); letter-spacing:.04em;
  color:var(--dv-moss,#5d6b5f);
}
body.svpage #tab-solve .sv-mrow .svm{
  padding:.16em .34em; border-radius:0;
}
/* the ellipsis that opens a line on Black's move is a placeholder, not a
   move — it is never a target and never reads as one */
body.svpage #tab-solve .svm-el{ color:var(--dv-moss,#5d6b5f); }
/* a variation answers a move rather than continuing the game, so it spans
   the tracks instead of taking them */
body.svpage #tab-solve .sv-mspan{
  grid-template-columns:1fr; padding-left:4.1em;
}

/* ---- 4. THE RANK: pinned, full-bleed, divided by its own hairlines ----
   MORE PRESENT (owner, 2026-08-12: "the boxes are straight beautiful, i
   feel like somehow they can be more visible. and striking"). The band was
   drawn ON the plate's own ground with .20/.14 hairlines, so it read as a
   ruled-off area rather than as an object you press. Three changes, none of
   them a fill on a verb: the band's own ground lifts to pine-hi (#2b4336
   against the room's #24382d) so the whole rank sits proud of the plate,
   its rules go to .34/.26, and it grows 54px -> 60px. The CELLS stay
   transparent — plAudit's "the advance is never filled" reads the cell's
   own background, and the bordered-verbs law is about the verb, not the
   surface it stands on. Weight does the rest: Schibsted Grotesk at 500 on
   .1em reads twice as loud as mono 400 at the same 12px, which is the size
   plAudit pins. */
body.svpage #tab-solve .sv-actions{
  /* NOT margin-top:auto — .sf-row above already carries the one void, and
     a second auto margin SPLITS the free space between them (measured:
     ~100px stranded between the engine row and the band). The band is held
     down by that gap and pinned by sticky, not by a margin of its own. */
  margin:22px 0 0; flex:none;
  position:sticky; bottom:0; z-index:3;
  display:flex; flex-direction:row; flex-wrap:nowrap; gap:0;
  align-items:stretch; height:60px;
  background:var(--dv-pine-hi,#2b4336);
  border-top:1px solid rgba(233,225,204,.34);
}
body.svpage #tab-solve .sv-actions .sv-act{
  /* BASIS IS THE WORD, not zero. `flex:1 1 0` makes every cell the same
     width, and the mid-solve phase carries five: at 560px that is 112px a
     cell against `play out the rest` needing 124, so the longest verb — the
     one you reach for when you are stuck — was the one that clipped, to
     "lay out the res". Content basis lets the cells share the slack in
     proportion to their words instead of pretending they are equal. The
     band's own width and height do not change either way, which is the
     invariant that matters. */
  flex:1 1 auto; width:auto; min-width:0; height:100%;
  padding:0 12px; border:0; border-radius:0;
  border-right:1px solid rgba(233,225,204,.26);
  background:none; white-space:nowrap;
  overflow:hidden; text-overflow:ellipsis;
  font-weight:500; letter-spacing:.1em;
}
body.svpage #tab-solve .sv-actions .sv-act:last-child{
  border-right:0;
}
/* the inversion is the door voice's, and in a band it is the only hover a
   cell can show — there is no hairline of its own left to warm */
body.svpage #tab-solve .sv-actions .sv-act:hover{
  background:var(--dv-flag,#a8402c); color:#f2e8d8; border-color:transparent;
}
body.svpage #tab-solve .sv-actions .sv-act.go{
  color:var(--dv-flag-lt,#e0906c); border-color:rgba(233,225,204,.14);
}
body.svpage #tab-solve .sv-actions .sv-act.go:last-child{
  border-right:0;
}
/* a spent verb still works (press it to re-read the hint) but stops
   asking — the offer has been taken */
body.svpage #tab-solve .sv-actions #svHintBtn.spent{
  color:var(--dv-moss,#5d6b5f);
}
/* the retreat is the way back, not an offer: it takes only the width of
   its own word and reads in moss */
body.svpage #tab-solve .sv-actions .sv-act.sv-back{
  flex:0 0 auto; padding:0 20px; color:var(--dv-moss,#5d6b5f);
}
body.svpage #tab-solve .sv-actions .sv-act.sv-back:hover{
  background:none; color:var(--dv-buff,#e9e1cc);
}

/* ---- 4b. THE BOARD TAKES THE ROOM WHEN YOU LOOK AT IT ------------------
   Owner, 2026-08-12: "when you hover over board implement a blur that blurs
   out everything and hides the massive TO MOVE text."

   Put the pointer on the board and the rest of the room recedes — the plate
   and the way-home strip go soft, and the verdict word goes out entirely.
   It is the board-first law expressed as an interaction rather than a
   measurement: while you are calculating, the only thing in front of you is
   the position.

   GATED ON body.sv-solving, and the ask itself is the reason: "TO MOVE" is
   only ever on the plate while the card is unanswered. Once it is answered
   the big word is the verdict and the plate carries the scoresheet you are
   stepping through — blurring THAT would hide the line at the moment you
   are reading it, and the board is exactly where you click to step through
   it. So the blur belongs to the thinking phase and stops when it ends.

   OPACITY, NOT display, on the word (the phase-invariant law): the slot
   keeps its height, so nothing below it moves when the word goes. A blur
   that reflowed the plate would be the 209px travel back by another route.

   @media (hover:hover) because a touch device has no hover to leave — the
   state would latch on first tap and the plate would stay blurred.
   `:has()` because .solve-top is the grid's UNCLE, not its sibling: it sits
   beside .solve-grid, so no combinator from the board reaches it. */
body.svpage #tab-solve .solve-side.v2,
body.svpage #tab-solve .solve-top{
  transition:filter .2s ease, opacity .2s ease;
}
body.svpage #tab-solve .sv-rank{ transition:opacity .16s ease; }
@media (prefers-reduced-motion:reduce){
  body.svpage #tab-solve .solve-side.v2,
  body.svpage #tab-solve .solve-top,
  body.svpage #tab-solve .sv-rank{ transition:none; }
}
@media (hover: hover){
  body.svpage.sv-solving:not(.repmode) #tab-solve:has(.sv-card:hover) .solve-side.v2,
  body.svpage.sv-solving:not(.repmode) #tab-solve:has(.sv-card:hover) .solve-top{
    filter:blur(5px); opacity:.3;
  }
  body.svpage.sv-solving:not(.repmode) #tab-solve:has(.sv-card:hover) .sv-rank{
    opacity:0;
  }
}

/* ---- 4c. THE INSTRUMENT — the explorer session's plate (2026-08-18) ----
   Owner, on #explorer/ewc/64/24: "as u scroll down, looking for where the
   engine analysis, you cant find it … u scroll down the notation pane
   rather then the interface … Scrolling should never be an option on this
   website … the main page should never ever scroll on."

   MEASURED FIRST, 1280x720, the EWC game at ply 24: the plate's box was
   627px and its content 1310 — the scrollport the 2026-08-13 rework called
   "the honest way to be out of room". The engine row sat at y=1089, 426px
   under the fold. The head spent 364px (96 hang + 123 title + 65 sentence
   + 16 fact + 23 EMPTY ribbon + gaps) naming things the frame already
   names (the back link says "← esports world cup"; the fact line said it
   again; the title said "EWC 2026 · GROUP B …" and the games panel's own
   sub-line said it a third time). The scoresheet inside was ITS OWN
   scrollport (42vh), so a wheel over it moved the moves and only then the
   plate. The band at the foot was EMPTY — 60px of pine-hi with all five
   puzzle verbs hidden — while the explorer's own verbs (◂ ▸, close, +
   opening lab, ☆ save, the ▦ launchers) sat in hairline boxes under the
   book, below the fold: the drift ONE-BUTTON-VOICE v2 killed everywhere
   else.

   THE NO-SCROLL LAW (owner, 2026-08-18): a plate never scrolls. It names
   ONE flex organ, which scrolls inside itself; every other organ is fixed.
   Here the flex organ is #exGames — the scoresheet with a game on the
   board, the games-at-this-position list without one — and the rest is a
   rank of fixed organs, head to band:

     head    the word (the two players with their ratings, or the room)
             + the fact line (result · citation) — ONE head; the games
             panel's own head, sub-line and control row are DELETED, not
             restyled (13c-exgames)
     note    #svAfter (your own games only — orGameNote)
     crumb   #svChips (the line walked — no game only; the sheet has it)
     FLEX    #exGames — the sheet + its variation strip | the games list
     book    #svBook — FIXED rows, scrolling inside. The phase-invariant
             law: the position changes the book's ROW COUNT on every move,
             so a box that followed it would move the engine every step.
     engine  .sf-row resident, #sfPanelSolve bounded (MultiPV ≤ 5)
     band    .sv-actions — the explorer's cells (13c exBandSync):
             ◂ ▸ · ＋ opening lab · ☆ save · ▦ N games · ✕ close, the
             last a moss ghost cell (.sv-back — the way out, not an offer)

   Scope: body.exsession — set by exOpen, cleared by exEnded (13c). The
   puzzle, drill and spar plates keep T5's composition; only the session
   that has organs takes the instrument. The head and the band's faces
   hold at every width; the GEOMETRY (the flex organ, the book's box, the
   engine's bound) is ≥1000 — narrow keeps its measured recipe (block 5).
   What this block states is the RANK and MEASURE of the plate's children;
   what the organs look like is explorer-session.css's ("the instrument's
   organs"). */
/* the HEAD, the crumb and the band's cell faces are the instrument's at
   every width — a phone's plate keeps T5's narrow scrollport (block 5) but
   wears the same head */
body.svpage.exsession #tab-solve .solve-side.v2 .sv-rank{
  /* the landing's word is UPRIGHT; the italic on the plate's word is the
     calm layer's `font:italic …` shorthand leaking through the door-voice
     rules (which set family/size/weight and never style) — corrected here
     for the session; the puzzle plate's is the owner's call and is flagged
     in reports/EXPLORER-INSTRUMENT-2026-08-18.md. A caption over an
     instrument, not a word in a void. */
  font-style:normal; font-size:clamp(14px, 3cqi, 18px);
  line-height:1.3; letter-spacing:.1em;
}
/* the ratings ride the names as small tabular figures */
body.svpage.exsession #tab-solve .solve-side.v2 .sv-rank i{
  font-style:normal;
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:.72em; letter-spacing:.06em; margin-left:.2em;
  color:var(--dv-sage,#a9b8a6); font-variant-numeric:tabular-nums;
}
/* the fact line is a CITATION — prose, sentence case (caps are for
   figures), wrapping as it needs to */
body.svpage.exsession #tab-solve .sv-idline{
  margin-top:.55em; flex-wrap:wrap; row-gap:2px; line-height:1.45;
  font-size:clamp(11px, 2.2cqi, 12.5px); letter-spacing:.02em;
  text-transform:none;
}
/* the sentence slot speaks only when it has something LIVE to say (an
   archive error, the authoring ask on a new game of yours); the
   instructions that used to sit here are tooltips now (quiet-screen).
   Empty says nothing and costs nothing. */
body.svpage.exsession #tab-solve #svMsg{ min-height:0; margin-top:.8em; }
body.svpage.exsession #tab-solve #svMsg:empty{ display:none; }
/* no deck, no ribbon */
body.svpage.exsession #tab-solve .sv-progress{ display:none; }
/* the crumb sits above the organs, one line */
body.svpage.exsession #tab-solve .solve-side.v2 > #svChips{
  order:11; margin:14px 0 0;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
body.svpage.exsession #tab-solve #svChips:empty{ display:none; }
/* the band: cells the explorer supplies. The divider law restated for a
   band whose LAST cell (✕ close) hides without a game: a cell with no
   shown cell after it draws no divider — DOM order is the visual order
   here, so this reads the truth the T5 :last-child rule cannot. The word
   cells take 10px of side padding (T5's 12): six cells at the plate's
   499px (1440x900, the rail cleared) is what the band holds, and the
   words were clipping at 12. The step cells are glyphs — a fixed
   hand-sized cell each, never a share of the slack. */
body.svpage.exsession #tab-solve .sv-actions .sv-act{ padding:0 10px; }
body.svpage.exsession #tab-solve .sv-actions #exStepB,
body.svpage.exsession #tab-solve .sv-actions #exStepF{
  flex:0 0 auto; padding:0 17px; font-size:14px;
}
body.svpage.exsession #tab-solve .sv-actions .sv-act.sv-back{ padding:0 14px; }
body.svpage.exsession #tab-solve .sv-actions .sv-act:not(:has(~ .sv-act:not([hidden]))){
  border-right:0;
}
body.svpage.exsession #tab-solve .sv-actions .sv-act[disabled]{
  color:var(--dv-moss,#5d6b5f); pointer-events:none;
}
body.svpage.exsession #tab-solve .sv-actions #pfSaveGameBtn.on{
  color:var(--dv-flag-lt,#e0906c);
}
/* THE GEOMETRY — wide only. Narrow keeps block 5's scrollport. */
@media (min-width:1000px){
  body.svpage.exsession #tab-solve .solve-side.v2{
    overflow:hidden; padding:10px 8px 0 0;
  }
  /* THE ONE FLEX ORGAN (chrome-redesign's global `[hidden]{display:none
     !important}` still puts it away when a session ends) */
  body.svpage.exsession #tab-solve .solve-side.v2 > #exGames{
    flex:1 1 0; min-height:0; margin-top:14px; overflow:hidden;
    display:flex; flex-direction:column;
  }
  /* THE BOOK'S BOX — at most four rows, the rows a scroller inside
     (.ot-bookrows, 13-ot-games). Four, measured: at 1280x720 five rows
     left the sheet 101px — four and a half moves of a 183-ply game — and
     the fifth was air on every position past the opening.
     Two measures for two orders, and the DOM order is the truth read
     (exOrganOrder puts the game's sheet before the book, the book before
     the games list):
       game on the board  — the book sits UNDER the flex organ, so its
         height may follow the position (max-height): the sheet's rows are
         anchored at their top and the engine row and band by the plate's
         floor, so a book that shrinks out of the opening moves neither —
         only the sheet's viewport lengthens. Out of book it is a head and
         one line, and the middlegame gets its ~80px back.
       no game (#svBook:has(~ #exGames)) — the book sits ABOVE the flex
         organ, so a height that followed the position would move the
         games list's first row on every step (the phase-invariant law).
         Fixed at four rows; fewer rows leave air. */
  body.svpage.exsession #tab-solve .solve-side.v2 > #svBook{
    flex:0 1 auto; max-height:calc(11px + 22px + 4 * 26px + 4px);
    min-height:calc(11px + 22px + 26px); overflow:hidden;
    display:flex; flex-direction:column; margin-top:12px;
  }
  body.svpage.exsession #tab-solve .solve-side.v2 > #svBook:has(~ #exGames){
    height:calc(11px + 22px + 4 * 26px + 4px);
  }
  /* the engine: the row hugs the book (no void to hold open — the flex
     organ above owns the slack), the panel is bounded and scrolls inside */
  body.svpage.exsession #tab-solve .solve-side.v2 > .sf-row{ margin-top:12px; }
  body.svpage.exsession #tab-solve .solve-side.v2 > #sfPanelSolve{
    flex:0 1 auto; max-height:186px; min-height:0;
    overflow-y:auto; overscroll-behavior:contain; scrollbar-width:thin;
  }
  body.svpage.exsession #tab-solve .sv-actions{ margin-top:12px; }
}

/* ---- 4d. THE AUTHOR SESSION's band (16d-pz-author, 2026-08-23) ---------
   body.pzauthor — a puzzle being ENTERED on this page (the rep/explorer
   precedent, a session overlay; reports/PUZZLE-DB-PROGRAM-2026-08-21.md).
   Its cells are the band's own (.sv-act, minted after #svNext: ⌫ undo ·
   ✕ discard · the one advance, `solution ▸` then `save ▸`), so their face
   is stated here by their owner and nowhere else — puzzle-author.css
   dresses only the organ the session adds. What the session needs from
   the band is ONE state the puzzle plate never had: an advance that is
   on screen but not yet ARMED (the position is not set, the line is
   empty). Never `disabled` — a disabled cell cannot explain itself, and
   the session writes the missing fact to #svMsg on the click — so the
   state is aria-disabled and the cell keeps its place and its tooltip,
   reading in moss until it is earned. */
body.svpage.pzauthor #tab-solve .sv-actions .sv-act[aria-disabled="true"]{
  color:var(--dv-moss,#5d6b5f);
}
body.svpage.pzauthor #tab-solve .sv-actions .sv-act[aria-disabled="true"]:hover{
  background:none; color:var(--dv-sage,#a9b8a6);
}
/* the divider law for a band whose DOM-last cell may be hidden: a cell
   with no shown cell after it draws no divider (block 4c's rule, restated
   for this session's scope) */
body.svpage.pzauthor #tab-solve .sv-actions .sv-act:not(:has(~ .sv-act:not([hidden]))){
  border-right:0;
}
/* THE GEOMETRY (sitting 2, the no-scroll law — block 4c's recipe for this
   session): the plate never scrolls; #pzaOrgan (puzzle-author.css) is its
   ONE flex organ and the scoresheet lives inside it for the session. Wide
   only — narrow keeps block 5's scrollport. */
@media (min-width:1000px){
  body.svpage.pzauthor #tab-solve .solve-side.v2{ overflow:hidden; padding:10px 8px 0 0; }
  body.svpage.pzauthor #tab-solve .solve-side.v2 > .sf-row{ margin-top:12px; }
  body.svpage.pzauthor #tab-solve .sv-actions{ margin-top:12px; }
}
/* the sheet inside the organ keeps its face; its own scroller yields to
   the organ's (one scroller on the plate) */
body.svpage.pzauthor #tab-solve #svMovesWrap{ margin-top:0; padding-top:0; border-top:0; }
body.svpage.pzauthor #tab-solve #svMovesWrap[hidden]{ display:none; }
body.svpage.pzauthor #tab-solve .sv-moves2{ max-height:none; overflow:visible; }

/* ---- 5. narrow: the plate is the scrollport, the band is its floor ----
   MEASURED FIRST, 375x812: the room already overflowed a height-LOCKED
   frame and nothing scrolled. #wbMain and #wbView are 812 (app-frame's
   100dvh lock), the strip starts at 786, and .solve-grid ran to 890 —
   78px of the plate simply fell off the bottom of the screen, with
   document.scrollingElement.scrollHeight still 812. It was invisible while
   the tail happened to be short; pinning the band made it show up as an
   overlap, which is the bug reporting itself rather than a new one.

   So the plate gets a bounded height and becomes its own scrollport: the
   board keeps its auto row, the plate takes minmax(0,1fr) of what is left,
   and the band sticks to the BOTTOM OF THAT BOX — bottom:0, not 26, since
   the strip is outside it. Content scrolls behind the verbs instead of
   under them. 52px is the two 26s the frame spends here: .solve-top above
   the grid, #svAppBar below it.
   LAST in this layer, because a media query adds no specificity. */
@media (max-width: 999px){
  body.svpage .solve-grid{
    height:calc(100dvh - 52px);
    grid-template-rows:auto minmax(0, 1fr);
  }
  body.svpage #tab-solve .solve-side.v2{
    /* align-self, because the grid says align-items:start — without it the
       plate takes its CONTENT height (measured 406.9px against a 347.6px
       track), overflows the row instead of scrolling inside it, and the
       sticky band pins to a box whose bottom is 35px below the strip. A
       scrollport that is not bounded is not a scrollport. */
    align-self:stretch;
    overflow-y:auto; min-height:0; overscroll-behavior:contain;
    scrollbar-width:thin;
  }
  body.svpage #tab-solve .sv-actions{
    bottom:0; margin-top:22px;
  }
  /* TWO ROWS, FIXED — the band's height is the invariant, not its division.
     Measured at 375px: the mid-solve phase carries FIVE verbs (hint /
     reveal / play out the rest / back one / next card) into a 343px band,
     which is 62px a cell against `play out the rest` needing 101 and `next
     card ▸` needing 77. Equal cells cannot be made to fit, and no amount of
     padding closes a 500px-of-words-in-343px gap; the choice is to drop
     verbs from a phone or to give them a second row. They get the row.
     `height` stays FIXED so the phase still cannot move anything above the
     band — with two rows the cells are 44px, with one they are the full 88,
     which is a better thumb target than a strip anyway. Cells size to their
     own words here (flex-basis auto) because equal cells is what did not
     fit; within the band they reflow, and the band does not. */
  body.svpage #tab-solve .sv-actions{
    /* align-content:CENTER, not stretch: the band's height is the fixed
       thing, the cell's is not. Stretched, the answered card's two cells
       grew to the full 88px and read as two hollow boxes; centred, a row is
       always 44px and the band simply carries one row or two with air
       around it. */
    height:88px; flex-wrap:wrap; align-content:center;
  }
  body.svpage #tab-solve .sv-actions .sv-act{
    flex:1 1 auto; height:44px; padding:0 10px;
  }
  body.svpage #tab-solve .sv-actions .sv-act.sv-back{ padding:0 12px; }
  body.svpage #tab-solve #svMsg{ min-height:2.6em; }
}
/* ================================================================
   THE EXPLORER SESSION — the games, the book, the open game
   (2026-08-11)
   ================================================================
   The Game Explorer has no room: its door opens the walkable SESSION
   directly (13c exgBuild), so every organ it owns — the master book
   rows, the games panel, the scoresheet, the variation rows, the paste
   dialog — is a #tab-solve child. This file is that surface's ONE
   owner.

   Formed in two passes. T1 (2026-08-11) lifted the exg- / ot-b* blocks
   out of solve-engine-overrides.css. T2 (same day) folded in the five
   explorer-* shards that were five ERAS, not five concerns —
   explorer-exg (the 2026-07 base), -focus, -landing, -strip,
   -archive-rows — plus the dress that had drifted into seven other
   files. What each file kept, and why, is at the bottom of this header.

   ORDER IN THIS FILE IS THE OLD CASCADE ORDER: the recovered blocks
   come first, in their original manifest-slot sequence (15, 17, 20, 21,
   24, 28, 29, 30, 36, 42, 52), then T1's calm dress last, which is what
   overrides the base. Proven by tests/cascade_diff.py.

   What did NOT move, and must not: the cross-cutting rosters that state
   ONE fact for many components — app-frame.css (user-select, cursor,
   overscroll contracts), type-color.css (tabular numerals),
   app-chrome.css §2 (the rep board's one panel-head voice). Splitting
   those would restate a fact per component, which is the quiet-screen
   law pointing the other way. The ownership test allows exactly those
   three and nothing else.

   The .ot-book* rows are SHARED with the Opening Lab's build board, so
   they stay scoped to #tab-solve here and are never restyled globally.
   ================================================================ */

/* ================================================================
   1 · THE BASE (was explorer-exg.css, slot 15, 2026-07)
   ================================================================
   The landing's own shell went with the room: .exg-shell and
   .exg-results had no emitter left after the 2026-08-01 cut. */
.res-pill.d { --rp-bg: #71717c; --rp-ink: #efecdd; --rp-line: #8b8b98; }
.exg-q { flex: 1 1 16rem; min-width: 12rem; font-family: var(--sans); font-size: .88rem;
  padding: .5rem .8rem; background: var(--card); color: var(--ink);
  border: 1px solid var(--hairline2); border-radius: 7px; }
.exg-q:focus { outline: none; border-color: var(--acc); }
.exg-sec { font-family: var(--mono); font-size: .64rem; letter-spacing: .09em;
  text-transform: uppercase; color: var(--mut); padding: .8rem .3rem .3rem; }
.exg-row { display: flex; align-items: center; gap: .55rem; padding: .34rem .5rem;
  border-radius: 6px; cursor: pointer; font-size: .82rem; min-width: 0; }
.exg-row:hover { background: var(--surface2); }
.exg-row + .exg-row { border-top: 1px solid var(--hairline); }
.exg-players b { font-weight: 600; }
.exg-y { flex: none; min-width: 3.4em; text-align: right;
  font-family: var(--mono); font-size: .68rem; color: var(--mut2);
  min-width: 2.6em; text-align: right; }
.exg-empty { font-family: var(--mono); font-size: .7rem; color: var(--mut2);
  padding: .5rem .3rem; line-height: 1.6; }
.exg-econame { margin-left: .35rem; font-size: .72rem; color: var(--ink2); }
/* games panel in the solve side card — same frame as the book panel */
.exg-panel { border: 1px solid var(--hairline); border-radius: 8px; background: var(--card);
  padding: .4rem .5rem .35rem; margin: .55rem 0 .1rem; }
.exg-panel .exg-row { padding: .26rem .3rem; font-size: .76rem; }
/* (.exg-ghead / .exg-gsub / .exg-edit / .exg-ctl / .exg-pos / .exg-x /
   .exg-here left 2026-08-18: the open game's own head, sub-line and
   control row are gone — the plate's head names the game and the band
   carries the verbs; reports/EXPLORER-INSTRUMENT-2026-08-18.md.) */
.exg-strip { font-size: .78rem; line-height: 1.8; max-height: 10.5em; overflow-y: auto;
  scrollbar-width: thin; padding: .2rem .3rem .1rem; }
.exg-strip i { font-style: normal; font-family: var(--mono); font-size: .66rem;
  color: var(--mut2); margin-right: .08em; }
.exg-m { display: inline-block; padding: 0 .3em; border-radius: 4px; cursor: pointer;
  color: var(--ink2); }
.exg-m:hover { background: var(--surface2); color: var(--ink); }
.exg-m.cur { background: var(--accfaint); color: var(--ink); }
.exg-players { flex: 1; display: flex; gap: .4em; min-width: 0; overflow: hidden;
  color: var(--ink); }
.exg-pl { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.exg-pl + .exg-pl::before { content: "— "; color: var(--mut2); }
.exg-pl b { font-weight: 600; }
.exg-pl i { font-style: normal; font-family: var(--mono); font-size: .68rem; color: var(--mut2); }
/* narrow side panel + game header: stack the two players, no separator */
.exg-panel .exg-players { flex-direction: column; gap: 0; }
.exg-panel .exg-pl { line-height: 1.4; }
.exg-panel .exg-pl + .exg-pl::before { content: ""; }

/* ================================================================
   2 · THE LAB DOOR (was explorer-focus.css, slot 17)
   ================================================================
   "+ opening lab" sat directly under the master book panel until
   2026-08-18; it is a cell of the plate's band now (13c exLabSync
   anchors it there and it wears .sv-act), so its box rule is gone. The
   rest of that file left 2026-08-11: .exg-branch and .exg-m.exg-skip had
   no emitter, its focus-mode engine rules went to engine-pane.css (the
   engine's owner), and its order:1/order:2 block was dead — identical
   selectors in solve-session.css sit later in the manifest and the
   reading board outranks both. */

/* ================================================================
   3 · THE RESULT PILLS AND SHOW-MORE (was explorer-landing.css, slot 20)
   ================================================================ */
#tab-explorer .exg-rf{display:inline-flex;gap:.35rem;margin-left:.6rem;
  vertical-align:middle}
.exg-rf button.res-pill{cursor:pointer;background:none;color:var(--mut);
  border:1px solid var(--line);font-size:.72rem;transition:border-color .12s}
.exg-rf button.res-pill:hover{border-color:var(--acc);color:var(--ink)}
.exg-rf button.res-pill.on{background:var(--rp-bg);color:var(--rp-ink);
  border-color:var(--rp-line);outline:2px solid var(--acc);outline-offset:1px}
.exg-more{display:block;width:100%;margin:.5rem 0 0;padding:.55rem .9rem;
  cursor:pointer;font:inherit;font-size:.85rem;color:var(--mut);
  background:var(--card);border:1px dashed var(--line);border-radius:8px}
.exg-more:hover{color:var(--ink);border-color:var(--acc)}

/* ================================================================
   4 · THE ROWS OTHER ROOMS BORROW (recovered 2026-08-11)
   ================================================================
   Three rooms render explorer primitives inside their own furniture —
   the structure plans' evidence line (slot 21), the master-games popup
   (slot 24), and the rep board's dense panel (slot 28). The rows are
   the explorer's, so their dress is this file's; the hosts keep their
   own shells where they were. */
.std-ev .exg-y{font-size:.72rem}
.sm-ctl .exg-q{flex:1 1 8.5rem;min-width:7.5rem;font-size:.8rem;padding:.36rem .6rem;
  background:var(--surface)}
.sm-list .exg-sec{position:sticky;top:0;z-index:1;background:var(--card);padding-top:.4rem}
/* squared work surfaces + database density, not web cards */
body.repmode #tab-solve .exg-panel{border-radius:3px}
.sm-pop .exg-row{padding-top:.22rem;padding-bottom:.22rem}
body.repmode #tab-solve .exg-panel .exg-row{padding-top:.22rem;padding-bottom:.22rem}

/* ================================================================
   5 · THE SCORESHEET (was notation-pane.css slot 29 + declutter.css
   slot 42) — the kit's two-column sheet, no eval rail
   ================================================================ */
#exgSheet.exg-sheet{max-height:42vh;overflow-y:auto;margin-top:.35rem;
  border-radius:3px}
#exgSheet.exg-sheet { border: 1px solid var(--hairline2); border-radius: 8px;
  background: var(--card); margin-top: .5rem; padding: .2rem 0; }

/* ================================================================
   6 · THE VARIATION STRIP AND THE PASTE DIALOG
   (was explorer-strip.css, slot 30)
   ================================================================ */
.exg-var{display:flex;align-items:center;gap:.35rem;flex-wrap:wrap;
  font-family:var(--mono);font-size:.7rem;color:var(--ink2);
  padding:.4rem .3rem .2rem;border-top:1px solid var(--hairline);
  margin-top:.3rem;line-height:1.6}
.exg-var:empty{display:none}
.exg-var .exg-varlbl{display:inline-block;font-size:.54rem;letter-spacing:.12em;
  text-transform:uppercase;color:var(--mut2);border:1px solid var(--hairline2);
  border-radius:4px;padding:.05rem .3rem}
.exg-var .exg-varre{font-family:var(--mono);font-size:.68rem;color:var(--ink);
  background:var(--surface);border:1px solid var(--hairline2);border-radius:6px;
  padding:.14rem .45rem;cursor:pointer}
.exg-var .exg-varre:hover{border-color:var(--acc)}
.exg-var .exg-varre i{font-style:normal;color:var(--mut2);font-size:.56rem;
  letter-spacing:.05em;margin-left:.3rem}

/* --- explorer PGN paste (13c exPgnDialog; the panel's two paste
   buttons died 2026-08-18 — the strip's ⎘ is the one door) --- */
.exg-pdta{width:100%;min-width:min(480px,72vw);box-sizing:border-box;margin-top:.55rem;
  font-family:var(--mono);font-size:.78rem;line-height:1.5;color:var(--ink);
  background:var(--surface2);border:1px solid var(--hairline3);border-radius:8px;
  padding:.55rem .6rem;resize:vertical}
.exg-pdta:focus{outline:none;border-color:var(--acc)}
.exg-pdfoot{display:flex;align-items:center;gap:.6rem;margin-top:.55rem}
.exg-pdfoot span{flex:1;font-family:var(--mono);font-size:.68rem;color:var(--bad)}

/* ================================================================
   7 · IN A vgrid (was grid-kit.css, slot 36)
   ================================================================
   The games list is a vgrid; these are the explorer's cells inside the
   kit's managed row, so they are the explorer's to dress. The kit keeps
   #exgList.vg's height contract and .vg .res-pill, which are the kit's. */
.vg .exg-players { flex-direction:row; gap:.35em; font-size:.92em; }
.vg .exg-pl { line-height:var(--g-rowh); }
.vg .exg-pl + .exg-pl::before { content:"— "; color:var(--mut2); }

/* ================================================================
   8 · THE DOORS INTO AND OUT OF A POSITION
   (was database-tab-doors.css, slot 52)
   ================================================================
   The archive layer's rows and its label. (The step-row door and the
   rule under a loaded game's sheet left 2026-08-18 with the row and the
   under-game list they dressed.)

   The archive layer (13c2-archive) offers the full OTB corpus under the
   offline list — its rows ARE explorer rows (.exg-row / .exg-empty /
   .exg-sec siblings), so the explorer dresses them. Quiet on purpose:
   the same kind of thing as the rows above, just more of them, so it
   gets a section label and no new colour. (T3, 2026-08-11: the four
   .arc- rules came home from database-tab-doors.css, which had held
   three different surfaces under one era name.) */
.arc-more { margin-left: 8px; font-family: var(--chrome); font-size: 11px;
  background: none; border: none; color: var(--ink2); cursor: pointer; padding: 0; }
.arc-more:hover { color: var(--ink); text-decoration: underline; }
.arc-list { margin-top: 6px; }
.arc-row { cursor: pointer; }
.arc-cap { font-size: 10.5px; color: var(--mut2); }
.arc-list .exg-sec { font-family: var(--mono); font-size: 9.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--mut2); padding: 6px 2px 4px; }


/* ---- the games panel's control row (all-games search + filter) ------- */
#exGames .exg-ctlrow{display:flex;align-items:center;gap:.45rem;
  margin:.35rem 0 .5rem}
#exGames .exg-qsm{flex:1;min-width:0;font:inherit;font-size:.8rem;
  padding:.35rem .55rem;color:var(--ink);background:var(--card);
  border:1px solid var(--line);border-radius:7px;outline:none}
#exGames .exg-qsm:focus{border-color:var(--acc)}
#exGames .exg-rf{display:inline-flex;gap:.3rem;margin:0}
#exGames .exg-more{font-size:.78rem;padding:.4rem .7rem}
#exGames .exg-idxnote{font-size:.75rem;opacity:.7;margin-top:.4rem}

/* (the "＋ opening lab" + "☆ save game" actions row — .ex-acts, built by
   16-profile as a wrapper under the book — died 2026-08-18: both verbs
   are cells of the plate's band, and the band needs no wrapper.) */

/* ================================================================== */
/* THE CALM EXPLORER — Game Explorer redesign layer                    */
/*                                                                     */
/* ⚠ THE THEME IS THE DELIVERABLE (HANDOFF-EXPLORER.md §0). Do not     */
/* re-skin with frame graphite (--acc/--ink2/--mut3) or shrink back to  */
/* the 10–11.5px measures — the lifted values ARE the redesign. Inside  */
/* the scopes below use only the --cm-* tokens, which solve-session.css */
/* declares on #tab-solve and every organ here inherits through the DOM */
/* (custom properties resolve by scope, not by file order).            */
/*                                                                     */
/* CSS-ONLY layer: no module, no markup, no second grid. The session   */
/* machinery (the ex- / or- dispatchers, EXG index, exgVerify's ply     */
/* contract, the route grammar, the gdb sink, i:-1) ships identical.   */
/*                                                                     */
/* ONE SCOPE since 2026-08-01: #tab-solve, the SESSION. The ROOM scope  */
/* (body.exroom — left POSITION column, rail LINE pane, drawer GAMES   */
/* HERE) was deleted with the room itself; the four orphan section      */
/* headings it left behind went with it 2026-08-11.                    */
/* ================================================================== */

/* ---- the games row language (session, archive, popup alike) ---------- */
#tab-solve .exg-row{
  display:flex; align-items:baseline; gap:10px; padding:7px 12px;
  border-bottom:1px solid rgba(255,255,255,.04); font-size:12.5px;
  color:var(--cm-ink2); cursor:pointer;
}
#tab-solve .exg-row:hover{ background:var(--cm-surface2); }
#tab-solve .exg-players{
  display:flex; gap:10px; min-width:0; flex:1;
}
#tab-solve .exg-pl{
  display:flex; align-items:baseline; gap:5px; min-width:0;
}
#tab-solve .exg-pl b{
  font-weight:400; color:var(--cm-ink2);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
#tab-solve .exg-pl i{
  font-style:normal; font:11px var(--cm-mono); color:var(--cm-mut2);
  font-variant-numeric:tabular-nums;
}
#tab-solve .exg-y{
  font:11px var(--cm-mono); color:var(--cm-mut2); font-variant-numeric:tabular-nums;
}
#tab-solve .res-pill{
  font:11px var(--cm-mono); color:var(--cm-mut); background:none;
  border:1px solid var(--cm-line); border-radius:99px; padding:2px 9px; cursor:pointer;
}
#tab-solve .res-pill.on{
  color:var(--cm-brass-hi); border-color:rgba(216,176,120,.3);
  background:var(--cm-brass-wash);
}
#tab-solve .exg-rf{ display:flex; gap:6px; }
#tab-solve .exg-empty{
  padding:8px 12px; font-size:12px; color:var(--cm-mut);
}
#tab-solve .exg-idxnote{
  font:11px var(--cm-mono); color:var(--cm-mut2);
}
#tab-solve .exg-econame{ font:11.5px var(--cm-mono); color:var(--cm-mut); }

/* THE SESSION'S GAMES PANEL IS A vgrid TOO (live-DOM adjustment, §3
   "adjust selectors not values"). The handoff styled `.exg-row`, which is
   now only the archive's and the popup's row class: `#exgList` migrated to
   its own vgrid (key "exg", 13c ~1021), so without these rules the SAME
   games read 11.5px/20px on the session board and 12.5px/30px in the room
   drawer — the half-unstyled surface §3.1 exists to prevent, one layer
   deeper than the room class. Values are the room's, unchanged.
   `exgGridSize` reads --g-rowh per render, so the panel's height math
   follows the taller row on its own. */
#tab-solve #exgList{ --g-rowh:30px; }
#tab-solve #exgList.vg{ border:0; background:none; }
#tab-solve #exgList .vg-row{
  font-size:12.5px; color:var(--cm-ink2);
  border-bottom:1px solid rgba(255,255,255,.04); border-left:2px solid transparent;
}
#tab-solve #exgList .vg-row:hover{ background:var(--cm-surface2); }
#tab-solve #exgList .vg-row[aria-selected="true"]{
  background:var(--cm-brass-wash); border-left-color:var(--cm-brass);
  color:var(--cm-brass-hi);
}
#tab-solve #exgList .vg-h{
  font:10.5px var(--cm-mono); letter-spacing:.06em; text-transform:uppercase;
  color:var(--cm-mut); background:none; border:0;
}

/* ---- the session: the master book panel (#svBook) --------------------
   SCOPED to the solve page on purpose — .ot-book* is shared with the
   Opening Lab's build board, and this layer is not its redesign. */
#tab-solve .ot-bookhead{
  font:11px var(--cm-mono); letter-spacing:.08em; text-transform:uppercase;
  color:var(--cm-mut); padding:2px 0 8px;
}
#tab-solve .ot-bookhead .hot{ font-style:normal; color:var(--cm-terra); }
#tab-solve .ot-bookempty{ font-size:12px; color:var(--cm-mut); padding:4px 0; }
#tab-solve .ot-bookrow{
  display:grid; grid-template-columns:76px 38px minmax(0,1fr) 56px;
  align-items:center; gap:8px; height:26px; cursor:pointer;
  font:12px var(--cm-mono); border-radius:5px;
}
#tab-solve .ot-bookrow:hover{ background:var(--cm-surface2); }
#tab-solve .ot-bookrow.eng{ grid-template-columns:76px minmax(0,1fr); }
#tab-solve .ot-bsan{
  display:flex; align-items:center; gap:4px; color:var(--cm-ink2);
  font-size:12.5px; padding-left:4px;
}
#tab-solve .ot-bbest{ font-style:normal; color:var(--cm-brass); }
#tab-solve .ot-bknown{ font-style:normal; font-size:10.5px; color:var(--cm-brass); }
#tab-solve .ot-bpct{
  color:var(--cm-slate); text-align:right; font-variant-numeric:tabular-nums;
}
#tab-solve .ot-bbar{
  display:flex; height:6px; border-radius:3px; background:var(--cm-bar); overflow:hidden;
}
#tab-solve .ot-bbar i{ display:block; height:100%; }
#tab-solve .ot-bbar i.w{ background:var(--cm-barw); }
#tab-solve .ot-bbar i.d{ background:var(--cm-bard); }
#tab-solve .ot-bbar i.b{ background:#22282d; }
#tab-solve .ot-bgames{
  color:var(--cm-mut2); text-align:right; font-variant-numeric:tabular-nums;
}
#tab-solve .ot-bengtag{ font-size:11px; color:var(--cm-mut2); }
/* A BOOK ROW IS FOUR CELLS, OR FIVE WITH THE ENGINE ON (live-DOM
   adjustment). orBookDep INSERTS an .ot-bev eval chip before .ot-bpct on
   every row it has a line for, so the row's child count is a function of
   whether Stockfish is running. The handoff's fixed 4-column template
   pushed that fifth cell into an implicit zero-width column and the SAN,
   the counts and the chips piled on top of each other — invisible with
   the engine off, which is how it shipped. The pre-calm rule was
   display:flex, which absorbed the extra child for free. Declare the
   fifth column only when the chip is actually there; :has is already
   used elsewhere in these sheets. Widths are the handoff's, unchanged. */
#tab-solve .ot-bookrow:has(.ot-bev){
  grid-template-columns:76px 62px 38px minmax(0,1fr) 56px;
}
/* the chip itself is a light scoresheet-era pill (a background #f2f4f6,
   weight 700, from the earlier sheet) — the layer set its colour but the
   pill survived underneath, so it read as a white lozenge on the dark card */
#tab-solve .ot-bev{
  background:none; font-weight:400; padding:0; min-width:0; text-align:right;
  color:var(--cm-ink2); font-variant-numeric:tabular-nums;
}
#tab-solve .ot-bev.neg{ color:var(--cm-slate); }
#tab-solve .ot-crumb{ font:12.5px var(--cm-mono); color:var(--cm-ink2); }
#tab-solve .ot-b.ot-eco{
  font-style:normal; font:10.5px var(--cm-mono); color:var(--cm-mut);
  border:1px solid var(--cm-line); border-radius:5px; padding:2px 7px;
}

/* ---- the session: an open game (sheet, variations) — its head and
   control row are the plate's since 2026-08-18 ---- */
#tab-solve .exg-sheet{
  font:12px var(--cm-mono); color:var(--cm-ink2);
  font-variant-numeric:tabular-nums;
}
#tab-solve .exg-var{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; padding:8px 0 0; }
/* the base's `.exg-var:empty{display:none}` lost to the id above on
   specificity, so an empty strip kept its 9px of rule and padding —
   restated at the id's weight (2026-08-18) */
#tab-solve .exg-var:empty{ display:none; }
#tab-solve .exg-varlbl{
  font:10.5px var(--cm-mono); letter-spacing:.08em; text-transform:uppercase;
  color:var(--cm-mut2);
}
#tab-solve .exg-varre{
  display:inline-flex; align-items:center; gap:6px; cursor:pointer;
  border:1px solid rgba(255,255,255,.14); border-radius:8px; background:none;
  color:var(--cm-ink2); font:12px var(--cm-mono); padding:5px 11px;
}
#tab-solve .exg-varre:hover{ border-color:var(--cm-brass); color:var(--cm-brass-hi); }
#tab-solve .exg-varre i{ font-style:normal; color:var(--cm-mut); }
#tab-solve .exg-varre:hover i{ color:var(--cm-slate); }

/* ---- the paste dialog: the one filled verb on this surface ------------ */
#tab-solve .exg-pdta, .exg-pdta{
  width:100%; background:var(--cm-paper); color:var(--cm-ink);
  border:1px solid var(--cm-line); border-radius:9px; padding:10px 12px;
  font:12px var(--cm-mono); resize:vertical;
}
.exg-pdfoot{ display:flex; align-items:center; gap:10px; padding-top:10px; }
/* fallback literals on purpose: these dialogs open OUTSIDE the elements
   that carry the --lr scope (labDialog is a body child), so a bare var()
   here silently loses its ink — the covered-palette rule */
.exg-pdfoot #exgPgnGo, .exg-pdfoot .udb-go{
  margin-left:auto;
  background:var(--cm-brass,#d8b078) !important; border:1px solid var(--cm-brass,#d8b078) !important;
  color:#14191e !important; font-weight:600; font-size:12.5px;
  border-radius:8px; padding:7px 13px; cursor:pointer;
}
.exg-pdfoot #exgPgnGo:hover, .exg-pdfoot .udb-go:hover{
  background:var(--cm-brass-hi,#e6c391) !important; border-color:var(--cm-brass-hi,#e6c391) !important;
}
.exg-pdfoot #exgPgnMsg{ font-size:12px; color:var(--cm-terra,#cf8f6d); }
.exg-pdfoot span[role="alert"]{ font-size:12px; color:var(--cm-terra,#cf8f6d); }

/* ====== YOUR GAME ON THE SESSION BOARD (16b-my-dbs) ======================
   The inline variation rows in the scoresheet. (The event sub-line and
   the ✎ door left 2026-08-18: the citation is the plate's fact line and
   ✎ is #exEditBtn beside it.) Session organs are #tab-solve children
   (the two-scope law) and speak the calm --lr dialect with fallbacks
   where the dialog escapes the scope. */
/* a fork line is a chess-book variation: indented under its branch move,
   every ply a door, the whole row quiet until it is the line on the board */
#tab-solve .exg-vrow{
  display:flex; align-items:baseline; flex-wrap:wrap; gap:0 2px;
  padding:1px 6px 1px 20px; font-family:var(--cm-mono);
  font-size:11.5px; line-height:1.55; border-radius:4px;
}
#tab-solve .exg-vrow.von{ background:var(--cm-brass-wash); }
#tab-solve .exg-vrow .exg-vind{ color:var(--cm-mut2); flex:none; margin-right:3px; }
#tab-solve .exg-vln{ display:contents; }
#tab-solve .exg-vrow .exg-vln button{
  background:none; border:0; padding:0 3px; margin:0; cursor:pointer;
  font:inherit; color:var(--cm-mut); border-radius:3px;
}
#tab-solve .exg-vrow .exg-vln button i{
  font-style:normal; color:var(--cm-mut2); font-size:10px; margin-right:1px;
}
#tab-solve .exg-vrow .exg-vln button:hover{ color:var(--cm-brass-hi); }
#tab-solve .exg-vrow .exg-vln button.past{ color:var(--cm-ink2); }
#tab-solve .exg-vrow .exg-vln button.cur{
  background:var(--cm-brass-wash); color:var(--cm-brass-hi);
}
#tab-solve .exg-vrow .exg-vdel{
  flex:none; margin-left:auto; padding:0 4px; opacity:0;
  background:none; border:0; cursor:pointer;
  font-size:11px; color:var(--cm-terra); border-radius:3px;
}
#tab-solve .exg-vrow:hover .exg-vdel, #tab-solve .exg-vrow.von .exg-vdel{ opacity:1; }

/* ---- THE READING BOARD, row 4 (2026-08-01) ---------------------------
   The rest of that pass — the board ceiling and the column order — is
   solve-session.css's; this one is the book's, so it lives here.

   (Row 3, "THREE REGISTERS, ONE VOICE", was deleted 2026-08-11. It was
   the second rule written for an intent app-chrome.css §2 already owned
   — "one mono-caps strip per panel on the rep boards" — and it landed
   nothing: `#tab-solve .ot-bookhead` outranks its three classes with an
   id, and engine-pane's `border:none !important` ate the hairline it
   won on the toggle. Its .ot-bdep companion was outranked the same way.
   The engine head it was reaching for is now in app-chrome's selector
   list, which is the rule that actually wins. Measurements in
   reports/T1-LEFTOVERS-2026-08-11.md.) */

/* 4. THE ROW GETS ITS WIDTH BACK.
   The row is a single flex line and stays one: a first pass tried to
   promote the White/draw/Black split onto a full-width spine under each
   row, and it fought the component — a bordered 9px flex bar with its
   own min-width does not become a hairline by being told to, and the
   result drew straight through the next row's text. The honest fix is
   the one the space bought: the ~160px reclaimed from the board goes to
   the two things that were being cut. The bar simply breathes, flat and
   wide, and the game totals stop being clipped mid-number.

   .ot-bgames was width:4.6em at .66rem — about 53px for "4,174,814",
   which needs 57. A fixed width narrower than its own content is the
   whole truncation, in one declaration. */
body.svpage:not(.cov-board) .ot-bookrow{
  gap: .55rem; padding: 4px .3rem; border-radius: 0;
  border-bottom: 1px solid var(--hairline2); }
body.svpage:not(.cov-board) .ot-bookrow:last-child{ border-bottom: 0; }
body.svpage:not(.cov-board) .ot-bookrow:hover{ background: var(--surface2); }
body.svpage:not(.cov-board) .ot-bsan{ min-width: 5.6em; font-size: .8rem; }
body.svpage:not(.cov-board) .ot-bev{ color: var(--mut2); font-size: .72rem;
  min-width: 4.2em; text-align: right; }
body.svpage:not(.cov-board) .ot-bpct{ color: var(--ink2); font-size: .72rem;
  min-width: 2.6em; text-align: right; }
body.svpage:not(.cov-board) .ot-bgames{
  width: auto; min-width: 5.4em; font-size: .7rem;
  color: var(--mut3); white-space: nowrap; }
/* flat, and the only bar on the screen now that the engine's pills are
   figures — 5px reads as a proportion without reading as a widget */
body.svpage:not(.cov-board) .ot-bbar{
  height: 5px; border-radius: 0; border: 0;
  background: var(--hairline2); min-width: 80px; }

/* the house voice's one line over this surface (2026-08-03) */
#tab-solve .ot-bev{ font-variant-numeric:tabular-nums; }

/* ================================================================
   THE INSTRUMENT'S ORGANS (2026-08-18) — the explorer session takes
   the door voice
   ================================================================
   solve-session.css block 4c gives the explorer's plate a skeleton
   that never scrolls (the owner's no-scroll law) and names #exGames as
   the one flex organ; this is what the organs LOOK like inside it, in
   the room's own material — the pine ground, buff ink, moss for the
   quiet, the clock-flag for the live — and the kit-era furniture they
   arrived in (dark rounded cards, blue cursor inks, mono everywhere,
   verbs in hairline boxes) answered here for the session only.
   Scope: body.exsession (13c exOpen/exEnded). The sm popup and the
   archive rows OUTSIDE the session keep the calm dress above.
   Type is the plate's (T5): Schibsted Grotesk for every figure and
   verb, tabular numerals, caps only for figures. Nothing is boxed and
   nothing is filled at rest; the one fill is the band cell's hover
   inversion, which the plate owns.
   ================================================================ */

/* ---- the panels are not cards: no ground, no border, no radius ---- */
body.svpage.exsession #tab-solve .exg-panel,
body.svpage.exsession #tab-solve .ot-book{
  background:none; border:0; border-radius:0; padding:0; margin:0;
}
/* the section label — the plate's fact role at its quietest */
body.svpage.exsession #tab-solve .ot-bookhead{
  display:flex; align-items:baseline; gap:10px; flex:none;
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:10px; letter-spacing:.16em; text-transform:uppercase;
  color:var(--dv-moss,#5d6b5f); padding:0 0 6px;
}
body.svpage.exsession #tab-solve .ot-bookhead .hot{ color:var(--dv-flag-lt,#e0906c); }
/* the book: a rule above it, its rows a scroller of their own */
body.svpage.exsession #tab-solve #svBook{
  border-top:1px solid rgba(233,225,204,.14); padding-top:11px;
}
/* basis AUTO, not 0: the book's own box is sized by its content (max-
   height caps it, min-height floors it), and a zero-basis scroller
   contributes nothing — measured 2026-08-18: a ten-row book collapsed to
   its one-row floor because the rows counted for 0px in its height */
body.svpage.exsession #tab-solve .ot-bookrows{
  flex:1 1 auto; min-height:0; overflow-y:auto; overscroll-behavior:contain;
  scrollbar-width:thin;
}
body.svpage.exsession #tab-solve .ot-bookrow{
  height:26px; padding:0 4px; gap:8px; border-bottom:0; border-radius:0;
  /* the move column grew 76 → 88 on 2026-08-18: it leads with the
     coverage MARK now (one em) beside the SAN, the ★ and the N× tag */
  grid-template-columns:88px 38px minmax(0,1fr) 66px;
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:12px; color:var(--dv-buff-ink,#efe9d6);
  font-variant-numeric:tabular-nums;
}
/* the games column measured: "4,174,814" needs 60px at this size and the
   calm template gave it 56 — a fixed width narrower than its own content is
   the whole truncation, in one declaration */
body.svpage.exsession #tab-solve .ot-bookrow:has(.ot-bev){
  grid-template-columns:88px 62px 38px minmax(0,1fr) 66px;
}
body.svpage.exsession #tab-solve .ot-bookrow.eng{ grid-template-columns:76px minmax(0,1fr); }
body.svpage.exsession #tab-solve .ot-bookrow:hover{ background:rgba(233,225,204,.09); }
body.svpage.exsession #tab-solve .ot-bsan{ font-size:12.5px; color:var(--dv-buff-ink,#efe9d6); min-width:0; padding-left:0; }
body.svpage.exsession #tab-solve .ot-bbest{ color:var(--dv-flag-lt,#e0906c); }
body.svpage.exsession #tab-solve .ot-bknown{ color:var(--dv-sage,#a9b8a6); }
/* THE MARK COLUMN (2026-08-18, 13-ot-games orBookRender): what the move
   MEANS against your repertoire leads the row — one glyph in a one-em box
   so the SANs stay aligned. ● in your book (buff, the scoresheet ink) ·
   ! a leak and ▲ a reply you have no answer to / a reply played here that
   is not yours (the flag — what is live or off-book) · ○ the edge of your
   book (sage) · · rare (moss). An alternative you do not play on your own
   move is not a gap: it goes unmarked, and in the STUDY dress its row dims
   (13-ot-games emits .dim under OTS.study only — the explorer is a reading
   room and keeps every master row at full ink). The ✓ this column replaced
   was the ● alone. */
body.svpage.exsession #tab-solve .ot-bmk{
  display:inline-block; width:1.05em; margin-right:.2em; text-align:center;
  font-style:normal; font-size:.85em; vertical-align:baseline;
}
body.svpage.exsession #tab-solve .ot-bmk.cov-m-in{ color:var(--dv-buff,#e9e1cc); }
body.svpage.exsession #tab-solve .ot-bmk.cov-m-gap,
body.svpage.exsession #tab-solve .ot-bmk.cov-m-off,
body.svpage.exsession #tab-solve .ot-bmk.cov-m-leak{ color:var(--dv-flag-lt,#e0906c); }
body.svpage.exsession #tab-solve .ot-bmk.cov-m-edge{ color:var(--dv-sage,#a9b8a6); }
body.svpage.exsession #tab-solve .ot-bmk.cov-m-rare{ color:var(--dv-moss,#5d6b5f); }
body.svpage.exsession #tab-solve .ot-bookrow.dim{ opacity:.6; }
body.svpage.exsession #tab-solve .ot-bookrow.dim:hover{ opacity:1; }
body.svpage.exsession #tab-solve .ot-bpct{ color:var(--dv-sage,#a9b8a6); font-size:12px; min-width:0; }
body.svpage.exsession #tab-solve .ot-bgames{ color:var(--dv-moss,#5d6b5f); font-size:11.5px; min-width:0; }
body.svpage.exsession #tab-solve .ot-bengtag{ color:var(--dv-moss,#5d6b5f); font-size:10.5px; }
body.svpage.exsession #tab-solve .ot-bev{ color:var(--dv-buff-ink,#efe9d6); font-size:11.5px; min-width:0; }
body.svpage.exsession #tab-solve .ot-bev.neg{ color:var(--dv-sage,#a9b8a6); }
/* the result bar: buff for White, a sage wash for the draws, the black
   share is the bar's own ground */
body.svpage.exsession #tab-solve .ot-bbar{ background:rgba(233,225,204,.12); height:5px; min-width:60px; }
body.svpage.exsession #tab-solve .ot-bbar i.w{ background:var(--dv-buff,#e9e1cc); }
body.svpage.exsession #tab-solve .ot-bbar i.d{ background:rgba(233,225,204,.4); }
body.svpage.exsession #tab-solve .ot-bbar i.b{ background:none; }
body.svpage.exsession #tab-solve .ot-bookempty{
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:12px; color:var(--dv-sage,#a9b8a6); padding:2px 4px;
}

/* ---- the scoresheet: the flex organ's scroller (a game on the board).
   The kit's two-column sheet in the T5 puzzle sheet's measure — number in
   moss, moves in buff ink, the move you stand on marked in the flag with
   its underline, no row wash, no card. Played moves are ink; the moves
   still to come are sage. ---- */
body.svpage.exsession #tab-solve #exgSheet.exg-sheet{
  margin:0; padding:0; border:0; border-radius:0; background:none;
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:clamp(12px, 2.4cqi, 14px); line-height:1.5;
  color:var(--dv-buff-ink,#efe9d6); font-variant-numeric:tabular-nums;
}
body.svpage.exsession #tab-solve #exgSheet.ndb-mvlist .mrow{
  grid-template-columns:3.4em 6.6em 6.6em; column-gap:.4em; align-items:baseline;
  background:none;
}
body.svpage.exsession #tab-solve #exgSheet.ndb-mvlist .mrow:hover,
body.svpage.exsession #tab-solve #exgSheet.ndb-mvlist .mrow.currow{ background:none; }
body.svpage.exsession #tab-solve #exgSheet.ndb-mvlist .mrow i,
body.svpage.exsession #tab-solve #exgSheet.ndb-mvlist .mrow.currow i{
  font-style:normal; text-align:right; margin:0;
  font-size:clamp(10px, 2cqi, 11.5px); letter-spacing:.04em;
  color:var(--dv-moss,#5d6b5f);
}
body.svpage.exsession #tab-solve #exgSheet.ndb-mvlist button{
  font:inherit; font-size:inherit; padding:.16em .34em; margin:0; border:0;
  border-radius:0; background:none; text-align:left; cursor:pointer;
  color:var(--dv-sage,#a9b8a6);
}
body.svpage.exsession #tab-solve #exgSheet.ndb-mvlist button.past{ color:var(--dv-buff-ink,#efe9d6); }
body.svpage.exsession #tab-solve #exgSheet.ndb-mvlist button:hover{ background:rgba(233,225,204,.09); color:var(--dv-buff-ink,#efe9d6); }
body.svpage.exsession #tab-solve #exgSheet.ndb-mvlist button.cur{
  background:none; color:var(--dv-flag-lt,#e0906c); font-weight:400;
  box-shadow:inset 0 -1px 0 var(--dv-flag-lt,#e0906c);
}
/* a fork line under its branch move: the line on the board wears a flag
   rule at its left edge, never a fill */
body.svpage.exsession #tab-solve .exg-vrow{
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:11.5px; border-radius:0; padding-left:3.4em;
}
body.svpage.exsession #tab-solve .exg-vrow.von{
  background:none; box-shadow:inset 2px 0 0 var(--dv-flag-lt,#e0906c);
}
body.svpage.exsession #tab-solve .exg-vrow .exg-vind{ color:var(--dv-moss,#5d6b5f); }
body.svpage.exsession #tab-solve .exg-vrow .exg-vln button{ color:var(--dv-sage,#a9b8a6); border-radius:0; }
body.svpage.exsession #tab-solve .exg-vrow .exg-vln button i{ color:var(--dv-moss,#5d6b5f); }
body.svpage.exsession #tab-solve .exg-vrow .exg-vln button.past{ color:var(--dv-buff-ink,#efe9d6); }
body.svpage.exsession #tab-solve .exg-vrow .exg-vln button:hover{ color:var(--dv-buff-ink,#efe9d6); background:rgba(233,225,204,.09); }
body.svpage.exsession #tab-solve .exg-vrow .exg-vln button.cur{
  background:none; color:var(--dv-flag-lt,#e0906c);
  box-shadow:inset 0 -1px 0 var(--dv-flag-lt,#e0906c);
}
body.svpage.exsession #tab-solve .exg-vrow .exg-vdel{ color:var(--dv-flag-lt,#e0906c); }
/* the variation strip under the sheet: what continues from HERE, as
   in-prose words (the .lr-ghost form — an offer inside a sentence, never
   a boxed chip). house-voice.css's !important box for .exg-varre died
   with this block; the session is a door room now. */
body.svpage.exsession #tab-solve .exg-var{
  flex:none; margin:0; padding:8px 0 0; border-top:1px solid rgba(233,225,204,.14);
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:12px; color:var(--dv-sage,#a9b8a6);
}
body.svpage.exsession #tab-solve .exg-varlbl{
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:10px; letter-spacing:.16em; text-transform:uppercase;
  color:var(--dv-moss,#5d6b5f); border:0; padding:0;
}
body.svpage.exsession #tab-solve .exg-varre{
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:12px; letter-spacing:.02em; color:var(--dv-buff-ink,#efe9d6);
  border:0; border-radius:0; background:none; padding:2px 4px; gap:5px;
}
body.svpage.exsession #tab-solve .exg-varre:hover{ color:var(--dv-flag-lt,#e0906c); background:none; }
body.svpage.exsession #tab-solve .exg-varre i,
body.svpage.exsession #tab-solve .exg-varre:hover i{ color:var(--dv-moss,#5d6b5f); font-size:10.5px; }

/* ---- the games at this position (no game on the board): the flex
   organ is the list — a section rule, the count in the head, the
   archive's door as an in-prose word, a search underline and three
   square result chips, then the vgrid taking every remaining pixel. The
   archive rows, when opened, take a scroller of their own beside it. ---- */
body.svpage.exsession #tab-solve #exGames > .ot-bookhead:first-child{
  border-top:1px solid rgba(233,225,204,.14); padding-top:11px;
}
body.svpage.exsession #tab-solve .arc-more{
  margin-left:auto; padding:0; border:0; background:none; cursor:pointer;
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:10px; letter-spacing:.16em; text-transform:uppercase;
  color:var(--dv-sage,#a9b8a6);
}
body.svpage.exsession #tab-solve .arc-more:hover{ color:var(--dv-flag-lt,#e0906c); text-decoration:none; }
body.svpage.exsession #tab-solve .arc-more b{ font-weight:400; }
body.svpage.exsession #tab-solve #exGames .exg-ctlrow{ flex:none; margin:2px 0 8px; gap:10px; }
body.svpage.exsession #tab-solve #exGames .exg-qsm{
  background:none; border:0; border-bottom:1px solid rgba(233,225,204,.22);
  border-radius:0; padding:4px 0; color:var(--dv-buff-ink,#efe9d6);
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:12.5px;
}
body.svpage.exsession #tab-solve #exGames .exg-qsm::placeholder{ color:var(--dv-moss,#5d6b5f); }
body.svpage.exsession #tab-solve #exGames .exg-qsm:focus{ border-bottom-color:var(--dv-flag-lt,#e0906c); }
body.svpage.exsession #tab-solve .exg-rf .res-pill{
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:11px; letter-spacing:.04em; color:var(--dv-sage,#a9b8a6);
  border:1px solid rgba(233,225,204,.22); border-radius:0; background:none;
  padding:2px 8px; font-variant-numeric:tabular-nums;
}
body.svpage.exsession #tab-solve .exg-rf .res-pill:hover{ color:var(--dv-buff,#e9e1cc); border-color:rgba(233,225,204,.4); }
body.svpage.exsession #tab-solve .exg-rf .res-pill.on{
  color:var(--dv-flag-lt,#e0906c); border-color:rgba(224,144,108,.55);
  background:none; outline:0;
}
body.svpage.exsession #tab-solve #exgList{ margin-top:0; }
body.svpage.exsession #tab-solve #exgList .vg-h{
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:10px; letter-spacing:.14em; text-transform:uppercase;
  color:var(--dv-moss,#5d6b5f);
}
body.svpage.exsession #tab-solve #exgList .vg-h.on,
body.svpage.exsession #tab-solve #exgList .vg-h:not(:disabled):hover{ color:var(--dv-sage,#a9b8a6); }
body.svpage.exsession #tab-solve #exgList .vg-h .vg-arrow{ color:var(--dv-flag-lt,#e0906c); }
body.svpage.exsession #tab-solve #exgList .vg-row{
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:12.5px; color:var(--dv-buff-ink,#efe9d6);
  border-bottom:0; border-left:2px solid transparent; background:none;
  font-variant-numeric:tabular-nums;
}
body.svpage.exsession #tab-solve #exgList .vg-row.alt{ background:none; }
body.svpage.exsession #tab-solve #exgList .vg-row:hover{ background:rgba(233,225,204,.09); }
body.svpage.exsession #tab-solve #exgList .vg-row[aria-selected="true"],
body.svpage.exsession #tab-solve #exgList .vg-row.sel,
body.svpage.exsession #tab-solve #exgList .vg-row.sel.alt{
  background:none; box-shadow:none; border-left-color:var(--dv-flag-lt,#e0906c);
  color:var(--dv-flag-lt,#e0906c);
}
body.svpage.exsession #tab-solve #exgList .exg-pl b{ color:inherit; }
body.svpage.exsession #tab-solve #exgList .exg-pl i,
body.svpage.exsession #tab-solve #exgList .exg-y{
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:11px; color:var(--dv-moss,#5d6b5f);
}
/* a result inside a row is a figure, not a badge */
body.svpage.exsession #tab-solve #exgList .res-pill,
body.svpage.exsession #tab-solve .exg-row .res-pill{
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:11px; letter-spacing:.02em; border:0; border-radius:0;
  background:none; padding:0; color:var(--dv-sage,#a9b8a6);
  font-variant-numeric:tabular-nums;
}
body.svpage.exsession #tab-solve .exg-empty,
body.svpage.exsession #tab-solve .exg-idxnote{
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:12px; color:var(--dv-sage,#a9b8a6); padding:6px 0; opacity:1;
}
/* the archive rows the panel lists under the local ones (13c2): explorer
   rows in the room's ink; while open they share the flex organ with the
   local list, half and half, each scrolling inside itself */
body.svpage.exsession #tab-solve .arc-list{ margin-top:8px; }
body.svpage.exsession #tab-solve .arc-list .exg-sec{
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:10px; letter-spacing:.16em; text-transform:uppercase;
  color:var(--dv-moss,#5d6b5f); padding:0 0 6px;
}
body.svpage.exsession #tab-solve .exg-row{
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:12.5px; color:var(--dv-buff-ink,#efe9d6); padding:5px 4px;
  border-bottom:0; border-radius:0;
}
/* one line per game here, as in the vgrid — the panel's stacked-players
   form was drawn for a 232px column, and at 26px a row a scroller of five
   games showed two */
body.svpage.exsession #tab-solve .exg-panel .exg-players{ flex-direction:row; gap:.4em; }
body.svpage.exsession #tab-solve .exg-panel .exg-pl + .exg-pl::before{ content:"— "; color:var(--dv-moss,#5d6b5f); }
body.svpage.exsession #tab-solve .exg-row:hover{ background:rgba(233,225,204,.09); }
body.svpage.exsession #tab-solve .exg-row .exg-pl b{ color:inherit; }
body.svpage.exsession #tab-solve .exg-row .exg-pl i,
body.svpage.exsession #tab-solve .exg-row .exg-y{
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:11px; color:var(--dv-moss,#5d6b5f);
}
/* the crumb (no game on the board): the line walked, buff, one line */
body.svpage.exsession #tab-solve .ot-crumb{
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:12px; letter-spacing:.02em; color:var(--dv-sage,#a9b8a6);
  font-variant-numeric:tabular-nums;
}
/* the flex geometry — wide only; narrow keeps its scrollport (solve-
   session block 5) and the sheet's own 42vh cap above still serves it */
@media (min-width:1000px){
  body.svpage.exsession #tab-solve #exgSheet.exg-sheet{
    flex:1 1 0; min-height:0; max-height:none; overflow-y:auto;
    overscroll-behavior:contain; scrollbar-width:thin;
  }
  body.svpage.exsession #tab-solve #exgList{ flex:1 1 0; min-height:0; }
  body.svpage.exsession #tab-solve .exg-rows{
    flex:1 1 0; min-height:0; overflow-y:auto; overscroll-behavior:contain;
    scrollbar-width:thin;
  }
  body.svpage.exsession #tab-solve .arc-list{
    flex:1 1 0; min-height:0; overflow-y:auto; overscroll-behavior:contain;
    scrollbar-width:thin;
  }
}
/* ====== THE PUZZLE AUTHOR SESSION (16d-pz-author) ==========================
   body.pzauthor — a session dress on the solve page, born in the door
   voice (reports/PUZZLE-DB-PROGRAM-2026-08-21.md §5): the plate keeps
   T5's skeleton and the band its cells (solve-session.css owns both —
   the author's cells are .sv-act like every other and take their face
   there, block 4d), and this file is only what the session ADDS: the one
   organ #pzaOrgan and everything inside it — the palette, the side and
   castle cells, the fields — plus the drag ghost and the promotion
   chooser on the board. `pza-` is machine-guarded to this file
   (tests/css-ownership.test.mjs); no new tokens — every colour is the
   landing's --dv-* with its fallback literal.

   THE ORGAN is the plate's ONE flex organ (the no-scroll law, block 4c's
   recipe): it sits right under the head in T5's order (rank 1 · msg 2 ·
   fact line 3 · ribbon 4), takes the slack, and scrolls inside itself;
   the phase swaps its CONTENT — the editor while you set the board, the
   scoresheet + p. · hint · note while you play the solution — so the
   head above and the engine row and band below never move.

   THE PALETTE restates the band cell's face as its own classes (the ewc
   precedent, never the class): cells of one rank on the lifted pine,
   .26 dividers, .34 rules, open, the inversion on hover, the flag-light
   when ARMED. Two rows of six with one tall erase cell beside them. */
body.pzauthor #tab-solve .solve-side.v2 > #pzaOrgan{
  order:5; margin-top:1.1em;
  display:flex; flex-direction:column; gap:10px;
  flex:1 1 0; min-height:0; overflow-y:auto; overflow-x:hidden;
  overscroll-behavior:contain; scrollbar-width:thin;
}
body.pzauthor #tab-solve #pzaOrgan .pza-setup,
body.pzauthor #tab-solve #pzaOrgan .pza-sol{
  display:flex; flex-direction:column; gap:12px; flex:none;
}
body.pzauthor #tab-solve #pzaOrgan .pza-setup[hidden],
body.pzauthor #tab-solve #pzaOrgan .pza-sol[hidden]{ display:none; }
body.pzauthor #tab-solve #pzaOrgan label{
  display:flex; flex-direction:column; gap:4px; min-width:0;
}
/* the field label — the plate's fact role at its quietest (the wall's
   .ac-lab, the explorer's .ot-bookhead) */
body.pzauthor #tab-solve .pza-lab{
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace);
  font-size:10px; letter-spacing:.14em; text-transform:uppercase;
  color:var(--dv-moss,#5d6b5f);
}

/* ---- the palette: a rank of cells, the band's own grammar ---- */
body.pzauthor #tab-solve .pza-pal{
  display:grid; grid-template-columns:repeat(6, minmax(0,1fr)) 44px;
  grid-auto-rows:50px;
  background:var(--dv-pine-hi,#2b4336);
  border-top:1px solid rgba(233,225,204,.34);
  border-bottom:1px solid rgba(233,225,204,.34);
}
body.pzauthor #tab-solve .pza-pc{
  appearance:none; cursor:pointer; margin:0; padding:6px 0;
  display:flex; align-items:center; justify-content:center;
  background:none; border:0; border-radius:0;
  border-right:1px solid rgba(233,225,204,.26);
  border-bottom:1px solid rgba(233,225,204,.26);
  color:var(--dv-buff-ink,#efe9d6);
  transition:background .12s ease, color .12s ease;
}
/* the rows' last cells and the bottom row draw no trailing rule: the
   rank's own edges are the rules */
body.pzauthor #tab-solve .pza-pc:nth-child(n+8){ border-bottom:0; }
body.pzauthor #tab-solve .pza-pc svg{ width:34px; height:34px; display:block; pointer-events:none; }
body.pzauthor #tab-solve .pza-pc:hover{ background:var(--dv-flag,#a8402c); }
/* ARMED: the flag-light standing, on a lift — the cell you will stamp with */
body.pzauthor #tab-solve .pza-pc.on{
  background:rgba(233,225,204,.10);
  box-shadow:inset 0 0 0 2px var(--dv-flag-lt,#e0906c);
}
body.pzauthor #tab-solve .pza-pc.on:hover{ background:var(--dv-flag,#a8402c); }
body.pzauthor #tab-solve .pza-pc:focus-visible{ outline:2px solid var(--dv-flag-lt,#e0906c); outline-offset:-2px; }
/* the erase cell spans both rows at the rank's end — a glyph, not a piece */
body.pzauthor #tab-solve .pza-erase{
  grid-column:7; grid-row:1 / span 2; border-right:0; border-bottom:0;
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:15px; color:var(--dv-sage,#a9b8a6);
}
body.pzauthor #tab-solve .pza-erase.on{ color:var(--dv-flag-lt,#e0906c); }

/* ---- the side-to-move pair and the castle cells: one row, two groups ---- */
body.pzauthor #tab-solve .pza-row{
  display:flex; align-items:stretch; gap:14px; flex-wrap:wrap;
}
body.pzauthor #tab-solve .pza-side,
body.pzauthor #tab-solve .pza-cr{
  display:flex; height:40px;
  background:var(--dv-pine-hi,#2b4336);
  border-top:1px solid rgba(233,225,204,.34);
  border-bottom:1px solid rgba(233,225,204,.34);
}
body.pzauthor #tab-solve .pza-side{ flex:1 1 auto; }
body.pzauthor #tab-solve .pza-turn,
body.pzauthor #tab-solve .pza-crc{
  appearance:none; cursor:pointer; margin:0;
  display:flex; align-items:center; justify-content:center;
  background:none; border:0; border-radius:0;
  border-right:1px solid rgba(233,225,204,.26);
  font-family:var(--chrome,'Schibsted Grotesk',-apple-system,sans-serif);
  font-size:12px; font-weight:500; letter-spacing:.1em; line-height:1;
  color:var(--dv-buff-ink,#efe9d6); white-space:nowrap;
  transition:background .12s ease, color .12s ease;
}
body.pzauthor #tab-solve .pza-turn{ flex:1 1 0; padding:0 12px; min-width:0; overflow:hidden; text-overflow:ellipsis; }
body.pzauthor #tab-solve .pza-turn:last-child,
body.pzauthor #tab-solve .pza-crc:last-child{ border-right:0; }
body.pzauthor #tab-solve .pza-turn:hover,
body.pzauthor #tab-solve .pza-crc:hover{ background:var(--dv-flag,#a8402c); color:#f2e8d8; }
body.pzauthor #tab-solve .pza-turn.on,
body.pzauthor #tab-solve .pza-crc.on{ color:var(--dv-flag-lt,#e0906c); }
/* the four rights are glyph cells — a fixed hand-sized cell each, the
   letter the FEN uses; one the geometry forbids reads in moss and does
   nothing (its tooltip says why) */
body.pzauthor #tab-solve .pza-crc{
  width:40px; font-family:var(--mono,'Spline Sans Mono',Menlo,monospace);
  font-size:13px; letter-spacing:0;
}
body.pzauthor #tab-solve .pza-crc[aria-disabled="true"]{ color:var(--dv-moss,#5d6b5f); cursor:default; }
body.pzauthor #tab-solve .pza-crc[aria-disabled="true"]:hover{ background:none; color:var(--dv-moss,#5d6b5f); }

/* ---- the fields: the wall's input dress — mono on a 4% lift, a .22
   hairline, square, the flag-light when it has the pen. Answers the
   frame's `#wbView input[type="text"]` roster at a higher specificity. ---- */
body.pzauthor #tab-solve #pzaOrgan input{
  width:100%; box-sizing:border-box; border-radius:0;
  font-family:var(--mono,'Spline Sans Mono',Menlo,monospace); font-size:12px;
  letter-spacing:.02em; line-height:1.3;
  color:var(--dv-buff-ink,#efe9d6); background:rgba(233,225,204,.04);
  border:1px solid rgba(233,225,204,.22); padding:8px 10px;
  transition:border-color .12s ease;
}
body.pzauthor #tab-solve #pzaOrgan input::placeholder{ color:var(--dv-moss,#5d6b5f); opacity:1; }
body.pzauthor #tab-solve #pzaOrgan input:focus{
  outline:none; border-color:var(--dv-flag-lt,#e0906c);
}
/* the meta rows: page is a short cell, hint takes the rest, note is a
   full row of its own */
body.pzauthor #tab-solve .pza-meta{
  display:grid; grid-template-columns:64px minmax(0,1fr); gap:10px;
}
body.pzauthor #tab-solve .pza-meta .pza-note{ grid-column:1 / -1; }

/* ---- the drag ghost: the piece at the board's own square size, riding
   the pointer over everything, touching nothing ---- */
.pza-ghost{
  position:fixed; left:0; top:0; z-index:60; pointer-events:none;
  opacity:.9; filter:drop-shadow(0 2px 4px rgba(0,0,0,.35));
}
.pza-ghost svg{ width:100%; height:100%; display:block; }

/* ---- the promotion chooser, drawn INTO the board's svg (a board
   affordance like the legal dots — never a button form): four squares
   from the promotion square inward, the lifted pine under a flag-light
   ring, the piece on each ---- */
#svBoard svg .pza-promo rect{
  fill:var(--dv-pine-hi,#2b4336); stroke:var(--dv-flag-lt,#e0906c); stroke-width:1.5;
  cursor:pointer;
}
#svBoard svg .pza-promo:hover rect{ fill:var(--dv-flag,#a8402c); }
#svBoard svg .pza-promo use{ pointer-events:none; }
