/* ChessSRS site — design tokens */
/* ============================================================
   SELF-HOSTED FONTS (OFL)

   Geist, Geist Mono and Instrument Serif are the marketing site's faces.
   Instrument Sans and Newsreader are the *app's* faces — its UI text and its study-note
   reading text — copied verbatim from the app repo by scripts/sync-design.js. They are declared
   here but only ever used inside the demo, because the demo has to look like the app rather
   than like the page it sits on.
   ============================================================ */
@font-face {
  font-family: 'Instrument Sans';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('assets/fonts/InstrumentSans-var.ttf') format('truetype');
}
@font-face {
  font-family: 'Newsreader';
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url('assets/fonts/Newsreader-var.ttf') format('truetype');
}
@font-face {
  font-family: 'Geist';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('assets/fonts/Geist-Regular.ttf') format('truetype');
}
@font-face {
  font-family: 'Geist';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('assets/fonts/Geist-Medium.ttf') format('truetype');
}
@font-face {
  font-family: 'Geist';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('assets/fonts/Geist-SemiBold.ttf') format('truetype');
}
@font-face {
  font-family: 'Geist Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('assets/fonts/GeistMono-Regular.ttf') format('truetype');
}
@font-face {
  font-family: 'Geist Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('assets/fonts/GeistMono-Medium.ttf') format('truetype');
}
@font-face {
  font-family: 'Instrument Serif';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('assets/fonts/InstrumentSerif-Regular.ttf') format('truetype');
}
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('assets/fonts/Archivo-var.woff2') format('woff2');
}

/* --mu is the page's quiet text, darkened from #5F584D to clear AA in the one place it is measured
   against something other than --bg: the sticky header sits on a backdrop-filtered blur, so once the
   page is scrolled its effective background darkens to ~#CFCDCA, where the old value reached only
   4.43:1. #564F44 gives 5.10:1 there and 7.29:1 on --bg. */
:root{--bg:#F5F3EF;--bg2:#ECE9E3;--sf:#fff;--ln:#17140f1f;--tx:#17140F;--mu:#564F44;--ac:#9A5F0B;--bb:#17140F;--bt:#F5F3EF;
--serif:"Instrument Serif",Georgia,"Times New Roman",serif;--sans:Geist,Inter,system-ui,-apple-system,"Segoe UI",sans-serif;--mono:"Geist Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
--g:clamp(20px,4vw,48px);--sp:clamp(88px,12vw,168px);--r:20px;
box-sizing:border-box;padding-top:env(safe-area-inset-top,0px);padding-bottom:env(safe-area-inset-bottom,0px)}
@media(prefers-color-scheme:dark){:root:not([data-theme="light"]){--bg:#0F0D0B;--bg2:#17140F;--sf:#1D1A15;--ln:#ffffff1a;--tx:#F3EFE8;--mu:#A69E91;--ac:#E2A84B;--bb:#F3EFE8;--bt:#0F0D0B}}
:root[data-theme="dark"]{--bg:#0F0D0B;--bg2:#17140F;--sf:#1D1A15;--ln:#ffffff1a;--tx:#F3EFE8;--mu:#A69E91;--ac:#E2A84B;--bb:#F3EFE8;--bt:#0F0D0B}
*,*::before,*::after{box-sizing:inherit}
html{scroll-behavior:smooth;scroll-padding-top:calc(88px + env(safe-area-inset-top,0px));-webkit-text-size-adjust:100%}
body{margin:0;background:var(--bg);color:var(--tx);font:400 17px/1.6 var(--sans);-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
h1,h2,h3,p,figure,ul,dl,dd{margin:0}ul{padding:0;list-style:none}img{display:block;max-width:100%;height:auto}
a{color:inherit;text-underline-offset:.2em}
:focus-visible{outline:2px solid var(--ac);outline-offset:3px;border-radius:4px}
.mk-sr{position:absolute;left:-9999px}.mk-sr:focus{left:12px;top:12px;z-index:50;background:var(--bb);color:var(--bt);padding:10px 16px;border-radius:99px}
.ic{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;flex:none}
.c{width:min(100% - 2*var(--g),1200px);margin-inline:auto}
.serif{font-family:var(--serif);font-weight:400}
.mono{font-family:var(--mono);font-size:13px;letter-spacing:.01em}
.mu{color:var(--mu)}

/* ============================================================
   DEMO-ONLY ADDITIONS

   assets/demo-reference.css is the app's design/reference/styles.css, generated verbatim by
   scripts/sync-design.js. It is never hand-edited — anything the demo needs on top of it lives
   in this block, so the next sync cannot silently drop it.

   The Analyze screen's move list. The app's Analyze action pushes StudyScreen, which has no
   counterpart in the reference stylesheet, so the list reuses the reference's own `.t-san`
   notation type and only the ply buttons need rules of their own.
   ============================================================ */
.set-col .t-san .ply{border:0;background:none;padding:2px 3px;border-radius:7px;color:var(--ink2);font:inherit}
.set-col .t-san .ply:hover{background:var(--hair2);color:var(--ink)}
.set-col .t-san .ply.on{background:var(--accent-soft);color:var(--accent)}

/* Top-bar colour squares (_ColourSquare in the app's top_bar.dart). The generated reference
   stylesheet still renders the old scope-name button, so the squares have no counterpart there:
   20px squares on 44px touch targets, the active side ringed in the accent. The white square stays
   light and the black square stays dark in both themes, with a hairline to hold them off the bar. */
.sqs{display:flex;align-items:center;gap:2px;margin-left:-10px}
.sq{display:grid;place-items:center;width:44px;height:44px;border:0;background:none;border-radius:8px;cursor:pointer}
.sq:hover{background:var(--hair2)}
.sq i{display:block;width:20px;height:20px;border-radius:5px;background:#fff;border:1px solid var(--hair)}
.sq-b i{background:#151A22}
.app[data-theme="dark"] .sq-w i{background:#ECEEF1}
.app[data-theme="dark"] .sq-b i{background:#10141B}
.sq.on i{border:2px solid var(--accent)}

/* The drawer's Import PGN pill (SrsPillButton, expanded) and the search empty state. */
.imp{padding:10px 18px 14px}
.imp .pill{width:100%;justify-content:center}
.no-results{padding:28px;text-align:center;font-size:15px;color:var(--ink2)}

/* The app's tokens are scoped to `.app`, but the reference stylesheet paints `.frame` — which is
   its parent, and so resolves `--bg` against the *marketing* page's palette. Without this the demo
   is a light-themed app sitting on the page's dark background, and every text colour is measured
   against the wrong surface. */
.frame>.app{background:var(--bg);color:var(--ink)}

/* Below ~1000px the desktop frame stops being a usable preview, so stop pretending it is one.

   `index.html` renders `<div class="frame" data-device="desktop">` at every width, and the app's
   own rule for that variant is `aspect-ratio:1280/800`. Frame height is therefore width * 0.625,
   and the app sizes the board as `--b: min(100cqw - 24px, 100cqh - 340px)` — it reserves 340px of
   container height below the board. Pasted into a phone-width column that frame is 324x202px, so
   `202 - 340` goes negative and the board clamps to **0x0**: 32 pieces in the DOM, nothing on
   screen, and no tap target. On an 810px iPad the frame is 438px tall and the board survives as a
   98px postage stamp. Both are the marketing page's fault, not the app's.

   The app ships three frame variants and its base rule is already the *narrow* stacked layout
   (`@container app (max-width:720px)` switches to side-by-side). So all that is needed is real
   height: the demo then renders in the same layout the app uses on a phone. Switching
   `data-device` to `phone` instead would demand a `.statusbar` the demo never emits and a fixed
   390px width, which overflows a 390px viewport.

   `height`, not `min-height`: `.app` is `position:absolute;inset:0`, so the frame has no in-flow
   content to give it a height and `min-height` would be the only thing holding it open. */
@media (max-width:1000px){
  .frame[data-device="desktop"]{aspect-ratio:auto;height:660px}
}

/* header */
.hd{position:sticky;top:env(safe-area-inset-top,0px);z-index:30;background:color-mix(in srgb,var(--bg) 84%,transparent);-webkit-backdrop-filter:saturate(1.5) blur(16px);backdrop-filter:saturate(1.5) blur(16px);border-bottom:1px solid transparent;transition:border-color .2s}
.hd.on{border-color:var(--ln)}
.hd .c{display:flex;align-items:center;justify-content:space-between;height:68px;gap:20px}
.logo{display:flex;align-items:center;gap:10px;font-weight:600;font-size:17px;letter-spacing:-.02em;text-decoration:none}
.nv{display:flex;align-items:center;gap:6px}
.nv>a:not(.btn){font-size:15px;color:var(--mu);text-decoration:none;padding:8px 12px;border-radius:99px;transition:color .15s,background .15s}
.nv>a:not(.btn):hover{color:var(--tx);background:var(--bg2)}
.ib{display:grid;place-items:center;width:40px;height:40px;border-radius:50%;border:0;background:none;color:var(--mu);cursor:pointer}
.ib:hover{color:var(--tx);background:var(--bg2)}
.mm{display:none;position:relative}.mm summary{list-style:none;cursor:pointer}.mm summary::-webkit-details-marker{display:none}
.mm div{position:absolute;right:0;top:48px;min-width:220px;background:var(--sf);border:1px solid var(--ln);border-radius:16px;padding:8px;box-shadow:0 20px 50px -20px #0006}
.mm a{display:block;padding:12px 14px;border-radius:10px;text-decoration:none}.mm a:hover{background:var(--bg2)}

/* buttons */
.btn{display:inline-flex;align-items:center;gap:9px;font:500 15px/1 var(--sans);text-decoration:none;padding:15px 22px;border-radius:99px;border:1px solid var(--ln);transition:transform .2s,background .2s}
.btn:hover{transform:translateY(-1px)}.btn.p{background:var(--bb);color:var(--bt);border-color:var(--bb)}.btn.s:hover{background:var(--bg2)}.btn.sm{padding:11px 18px;font-size:14px}
.cta{display:flex;flex-wrap:wrap;gap:10px}

/* hero */
.hero{padding:clamp(64px,11vw,148px) 0 clamp(48px,6vw,80px)}
.mk-meta{display:inline-flex;gap:10px;align-items:center;color:var(--mu);margin-bottom:28px}
.mk-meta i{width:7px;height:7px;border-radius:50%;background:var(--ac)}
h1{font:400 clamp(52px,8.2vw,120px)/.98 var(--serif);letter-spacing:-.025em;max-width:12em}
.lede{font-size:clamp(18px,1.7vw,21px);line-height:1.55;color:var(--mu);max-width:44ch;margin:30px 0 36px}
.stage{background:var(--bg2);border:1px solid var(--ln);border-radius:28px;padding:clamp(12px,2.6vw,36px)}
.stage img{width:100%;border-radius:12px;box-shadow:0 0 0 1px var(--ln),0 40px 80px -30px #0008}
.stage figcaption{display:flex;justify-content:space-between;gap:16px;padding:16px 4px 0;color:var(--mu)}

/* sections */
.sec{padding-top:var(--sp)}
h2{font:400 clamp(36px,4.8vw,68px)/1.04 var(--serif);letter-spacing:-.02em;max-width:15em}
.big{font:400 clamp(30px,4.4vw,60px)/1.12 var(--serif);letter-spacing:-.015em;max-width:21em}
.two{display:grid;grid-template-columns:1fr 1fr;gap:var(--g);margin-top:48px;color:var(--mu);max-width:860px}
.kick{color:var(--ac);margin-bottom:18px;display:block}

/* story */
.story{display:grid;grid-template-columns:1fr 1.1fr;gap:clamp(32px,6vw,96px);margin-top:56px;border-top:1px solid var(--ln)}
.st{min-height:68vh;display:flex;flex-direction:column;justify-content:center}
.js .st{opacity:.65;transition:opacity .5s}.js .st.act{opacity:1}
.st h3{font:400 clamp(40px,5vw,68px)/1 var(--serif);letter-spacing:-.02em;margin:0 0 16px;color:var(--tx)}
.st p{color:var(--tx);max-width:30ch}
.st p.sub{color:var(--mu)}
.stg{position:sticky;top:calc(50vh - 250px);height:500px;margin-top:calc(34vh - 250px)}
.js .pn{position:absolute;inset:0;opacity:0;transform:translateY(14px);transition:opacity .6s,transform .6s cubic-bezier(.16,1,.3,1)}
.js .pn.on{opacity:1;transform:none}
.pn{display:flex;flex-direction:column;justify-content:center;gap:14px}
.pn>.card{background:var(--sf);border:1px solid var(--ln);border-radius:var(--r);padding:28px;overflow:auto}
.pgn{font:400 15px/1.95 var(--mono);color:var(--tx);white-space:pre}.pgn i{font-style:normal;color:var(--mu)}.pgn b{font-weight:500;color:var(--ac)}
.pn img{width:100%;max-width:500px;margin-inline:auto;border-radius:10px;box-shadow:0 0 0 1px var(--ln),0 40px 70px -30px #0007}
.pn small{text-align:center;color:var(--mu)}
.q div{display:flex;justify-content:space-between;gap:16px;padding:16px 0;border-bottom:1px solid var(--ln)}.q div:last-child{border:0}.q .d{color:var(--ac)}.q span{color:var(--mu)}

/* principles + lists */
.grid{display:grid;grid-template-columns:1fr 1fr;gap:0 clamp(32px,6vw,96px);margin-top:56px;border-top:1px solid var(--ln)}
.grid>div{padding:32px 0 40px;border-bottom:1px solid var(--ln)}
.grid h3,.dl h3{font:400 clamp(26px,2.6vw,34px)/1.1 var(--serif);margin-bottom:10px}
.grid p{color:var(--mu);max-width:38ch}
.split{display:grid;grid-template-columns:1fr 1fr;gap:var(--g);align-items:start}
.dl{background:var(--sf);border:1px solid var(--ln);border-radius:var(--r);padding:clamp(24px,3.4vw,44px)}
.dl ol{margin:24px 0 0;padding:0;list-style:none;counter-reset:s;color:var(--mu)}
.dl li{counter-increment:s;display:flex;gap:16px;padding:14px 0;border-top:1px solid var(--ln)}
.dl li::before{content:counter(s);font:500 13px/1.9 var(--mono);color:var(--ac);width:16px}
.dl .cta{margin-top:28px}
/* Download menu: a small platform popover on the same primary block. One
   button, one menu, one click per file — no intermediate pages. */
.dl-cta{position:relative}
/* The menu is shared: every Download entry (nav, hero, section) opens this
   one popover anchored under the entry that was clicked (position:fixed set
   from its viewport rect), so the visitor never travels to find their file. */
.dl-menu{position:fixed;z-index:60;min-width:280px;max-width:calc(100vw - 16px);background:var(--sf);border:1px solid var(--ln);border-radius:16px;padding:8px;box-shadow:0 20px 50px -20px #0006}
.dl-menu[hidden]{display:none}
.dl-menu a{display:flex;align-items:center;gap:12px;padding:12px 14px;border-radius:10px;text-decoration:none;font-weight:500}
.dl-menu a:hover{background:var(--bg2)}
.dl-tag{display:inline-block;font-size:12px;color:var(--ac);border:1px solid var(--ac);border-radius:99px;padding:3px 12px;white-space:nowrap}
/* Reassurance facts beside the button: established claims only, no dev noise. */
.dl-facts{margin:24px 0 0;padding:0;list-style:none;color:var(--mu)}
.dl-facts li{padding:14px 0;border-top:1px solid var(--ln)}
#dl-note{font-size:13px}
#dl-sub{min-height:3.2em}
.lk a{display:flex;justify-content:space-between;align-items:center;gap:16px;padding:22px 0;border-bottom:1px solid var(--ln);text-decoration:none;font:400 clamp(22px,2.4vw,30px)/1.2 var(--serif)}
.lk a:first-child{border-top:1px solid var(--ln)}.lk a span{display:block;font:400 14px/1.4 var(--sans);color:var(--mu);margin-top:4px}
.lk .ic{transition:transform .2s;color:var(--mu)}.lk a:hover .ic{transform:translate(3px,-3px);color:var(--tx)}

/* faq */
.faq{margin-top:48px;border-top:1px solid var(--ln);max-width:860px}
.faq details{border-bottom:1px solid var(--ln)}
.faq summary{display:flex;justify-content:space-between;gap:20px;padding:24px 0;cursor:pointer;list-style:none;font:400 clamp(22px,2.2vw,28px)/1.25 var(--serif)}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:"+";font:300 28px/1 var(--sans);color:var(--mu);transition:transform .25s}
.faq details[open] summary::after{transform:rotate(45deg)}
.faq p{color:var(--mu);padding:0 40px 26px 0;max-width:62ch}

/* footer */
.ft{margin-top:var(--sp);border-top:1px solid var(--ln);padding:64px 0 40px;font-size:15px}
.fc{display:grid;grid-template-columns:1.6fr repeat(3,1fr);gap:var(--g)}
.ft h3{font:600 13px/1 var(--sans);color:var(--mu);margin-bottom:18px}
.ft li{margin-bottom:10px}.ft a{text-decoration:none}.ft a:hover{text-decoration:underline}
.fb{display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap;margin-top:56px;padding-top:24px;border-top:1px solid var(--ln);color:var(--mu);font-size:14px}

@media(max-width:860px){
.nv>a:not(.btn){display:none}.mm{display:block}
.story,.split,.grid,.fc{grid-template-columns:1fr}.two{grid-template-columns:1fr}
/* Phone-width page overflow came from the story grid: the PGN panel's
   unbreakable `white-space:pre` line sets the .stg track's min-content width,
   and grid items default to min-width:auto, so the track (and with it every
   .st) stretched to ~391px on a 320px column. Let the tracks shrink; the
   cards already scroll internally (overflow:auto). Desktop untouched. */
.story>*{min-width:0}
.js .st{opacity:1;min-height:0;padding:56px 0 20px}.stg{position:static;height:auto;margin:0 0 40px}.js .pn{position:static;opacity:1;transform:none;margin-bottom:28px}}
@media(prefers-reduced-motion:reduce){*,*::before,*::after{transition:none!important;animation:none!important;scroll-behavior:auto!important}}
@media print{.hd,.stg{display:none}}

/* ============================================================
   cursor-spotlight hero (home only)

   full-viewport photographic hero: a matte black knight base with
   an ornate golden-knight reveal under a cursor spotlight. everything
   is Archivo, all copy lowercase. the only motion is the spotlight.
   ============================================================ */
.spot-hero{position:relative;height:100vh;overflow:hidden;background:#0D0B09;color:#F2EDE4;font-family:Archivo,Geist,Inter,system-ui,-apple-system,"Segoe UI",sans-serif;border-radius:0}
.spot-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center;transform:translateZ(0);border-radius:0}
.spot-base{user-select:none;-webkit-user-select:none}
.spot-ghost{opacity:.1;pointer-events:none}
.spot-reveal{opacity:0;transition:opacity .4s ease-out;will-change:opacity;pointer-events:none;-webkit-mask-image:radial-gradient(closest-side,#000 62%,transparent 100%);mask-image:radial-gradient(closest-side,#000 62%,transparent 100%);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:110px 140px;mask-size:110px 140px}
.spot-scrim{position:absolute;inset:0;pointer-events:none;background:linear-gradient(180deg,rgba(13,11,9,.55) 0%,rgba(13,11,9,.12) 45%,rgba(13,11,9,.6) 100%)}
.spot-content{position:relative;z-index:3;height:100%;display:flex;flex-direction:column;padding:44px 64px 40px;pointer-events:none}
.spot-content h1{margin:0}
.spot-head{margin-top:40px;font-family:Archivo,Geist,Inter,system-ui,-apple-system,"Segoe UI",sans-serif;font-size:clamp(52px,7.4vw,104px);font-weight:500;letter-spacing:-.02em;line-height:.98;text-transform:lowercase;text-align:left}
.spot-head .ln{display:block}
@media(max-width:640px){
.spot-content{padding-left:20px;padding-right:20px}
}
