/* Wourdoboros — one-page explainer */
*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{background:var(--paper);color:var(--ink);font-family:var(--font-body);overflow-x:hidden}
.wrap{max-width:1160px;margin:0 auto;padding:0 var(--gutter-mobile)}
a{color:var(--brick-violet-dark)}
a:hover{color:var(--brick-violet)}

/* dotted paper accent removed per request — .dots is now a no-op (the class stays in the
   hero/band markup harmlessly). */

/* ---- header ---- */
.hdr{position:sticky;top:0;z-index:50;backdrop-filter:blur(14px) saturate(140%);-webkit-backdrop-filter:blur(14px) saturate(140%);background:color-mix(in oklab,var(--paper) 82%,transparent);border-bottom:1px solid color-mix(in oklab,var(--ink) 8%,transparent)}
.hdr-in{display:flex;align-items:center;justify-content:space-between;height:72px;gap:var(--s-4)}
.brand{display:flex;align-items:center;gap:var(--s-3);text-decoration:none;color:var(--ink)}
/* Larger than the 36px the old solid tile mark used: logo-ring-mark.svg is a ring
   with a hollow centre and a little box padding, so it carries less ink per px and
   reads small next to the wordmark at the tile's size. Same reason in .ftr-brand. */
.brand img{width:42px;height:42px;display:block;filter:drop-shadow(0 2px 3px rgba(31,26,20,.16))}
.brand b{font-family:var(--font-display);font-weight:400;font-size:24px;letter-spacing:.01em}
.hdr-nav{display:flex;align-items:center;gap:var(--s-5)}
.hdr-nav .madeby{font-weight:600;font-size:var(--fs-sm);color:var(--ink-3);text-decoration:none}
.hdr-nav .madeby:hover{color:var(--ink)}

/* ---- hero ---- */
.hero{position:relative;padding:var(--s-10) 0 var(--s-9)}
/* Single-column flow with the ring floated into it (see .hero-art) so the headline,
   tiles and lede wrap AROUND the spinner rather than sitting in a rigid second column. */
.hero-grid{display:block}
.hero-grid::after{content:"";display:block;clear:both}   /* contain the floated ring */
.eyebrow-row{display:flex;align-items:center;gap:var(--s-3);margin-bottom:var(--s-5)}
/* Sized so "Find the longest words — or" holds a single row on desktop (mockup "blue box"),
   above the down-shifted ring; it wraps naturally on narrow screens. */
.hero h1{font-family:var(--font-display);font-weight:400;font-size:clamp(32px,3.6vw,48px);line-height:1.12;letter-spacing:-.01em;margin:0}
/* "forge epic chains" rendered as game-style letter tiles inside the headline,
   built to match the flat two-tone brick look of the spinning hero-ring tiles: a
   solid face over a darker bottom "side" lip, no gloss/gradient, ring-matched corner
   radius. Interior letters take the round screen's neutral tile; the chain-link letters
   (the E that ends the first word / starts "epic", and the C that ends "epic" / starts
   "chains") take the ring's orange / sky brand tokens. Sized in em so tiles track the responsive
   headline. The pop-in / double-bounce / first-word-cycling motion is driven by the
   inline script at the end of the page (Web Animations API); this CSS only styles the
   tiles and supplies the no-JS / reduced-motion resting state. */
/* The tiles sit on their own rows under the headline prose. The letter is sized to read at
   roughly the headline's own size (.85em of the h1), which puts the whole phrase at ~1120px
   on a 48px headline — far past the ~684px the copy column ever gets beside the floated
   ring, at any viewport (the page caps at 1160 and the ring takes 440 of it). So a single
   row is unreachable and the layout is authored as the mockup's cascade instead: one word
   per row, each stepped right of the one above by --wt-step. Letting flex-wrap decide the
   breaks instead gives a two-row layout at the widths where the first two words happen to
   fit together, which reads as a mistake rather than a stagger. */
.word-tiles{
  --wt-step:2em;
  display:flex;flex-direction:column;align-items:flex-start;
  row-gap:.34em;margin:.5em 0 .3em;font-size:.85em;line-height:1;
}
.wt-word{display:inline-flex;gap:.16em;white-space:nowrap}   /* a word's tiles never split across lines */
.word-tiles .wt-word:nth-child(2){margin-left:var(--wt-step)}
.word-tiles .wt-word:nth-child(3){margin-left:calc(var(--wt-step) * 2)}
.wt{
  /* The round screen's neutral letter tile — LDraw Tan face / Medium Nougat side / Dark
     Brown letter, kept in step with BrickTileLib's STONE_* block (scripts/brick_tile.gd).
     Warm sand rather than stone grey: 9.44:1 against the letter, and it sits on the warm
     paper background without the muddiness the greys had. */
  --wt-face:#D7BA8C; --wt-side:#AA7D55; --wt-ink:#300F06;
  display:inline-flex;align-items:center;justify-content:center;
  width:1.5em;height:1.5em;border-radius:.34em;
  font-family:var(--font-display);font-weight:400;font-size:1em;line-height:1;
  color:var(--wt-ink);text-transform:uppercase;
  background:var(--wt-face);   /* flat solid face, like the ring rects (no gradient) */
  box-shadow:0 .13em 0 var(--wt-side),0 .18em .2em rgba(31,26,20,.22);  /* darker bottom lip + soft drop */
  transform-origin:50% 100%;
}
/* Chain-link tiles use spinner colours that keep BLACK letter text (matching the ring's
   orange "O" and sky "O", both ink-lettered), so every tile in the title reads black. */
.wt--e{--wt-face:var(--brick-orange);--wt-side:var(--brick-orange-dark);--wt-ink:var(--ink)}
.wt--c{--wt-face:var(--brick-sky);   --wt-side:var(--brick-sky-dark);   --wt-ink:var(--ink)}
/* No-JS / reduced-motion fallback: the link tiles keep a gentle idle bounce and the
   whole phrase rests fully visible. When the script takes over it adds `.js` to
   .word-tiles, hides the tiles so it can pop them in, and drives every bounce itself —
   so this idle animation is switched off to avoid fighting the scripted keyframes. */
.wt--link{animation:wt-bounce 2.6s ease-in-out infinite}
.wt--c.wt--link{animation-delay:.55s}   /* the C pair links a beat after the E pair */
.word-tiles.js .wt{opacity:0}
.word-tiles.js .wt--link{animation:none}
@keyframes wt-bounce{
  0%,60%,100%{transform:translateY(0)}
  68%{transform:translateY(-16%)}
  76%{transform:translateY(0)}
  82%{transform:translateY(-7%)}
  88%{transform:translateY(0)}
}
@media (prefers-reduced-motion:reduce){.wt--link{animation:none}}
/* No hard max-width here (unlike a normal column) so the paragraph flows out to the ring
   and its right edge follows the circle's curve — the "wrap with stronger shape" note. */
.hero .lede{font-size:var(--fs-lg);line-height:1.5;color:var(--ink-2);margin:var(--s-5) 0 0;text-wrap:pretty}

/* store CTA cluster (PRIMARY) */
.cta-stores{display:flex;flex-wrap:wrap;gap:var(--s-4);margin-top:var(--s-8)}
.store-btn{display:flex;align-items:center;gap:14px;min-height:66px;padding:0 24px 0 20px;border:0;border-radius:var(--r-card);text-decoration:none;cursor:pointer;user-select:none;transform-origin:50% 100%;transition:transform var(--dur-fast) var(--ease-out),box-shadow var(--dur-fast) var(--ease-out),filter var(--dur-fast)}
.store-btn .glyph{width:30px;height:30px;flex:0 0 auto}
.store-btn .st{display:flex;flex-direction:column;line-height:1.1;text-align:left}
.store-btn .st .k{font-size:11px;font-weight:600;letter-spacing:.09em;text-transform:uppercase;opacity:.8}
.store-btn .st .v{font-family:var(--font-display);font-weight:400;font-size:20px;letter-spacing:.01em}
.store-btn.ios{--f:var(--brick-yellow);--s:var(--brick-yellow-dark);--t:var(--brick-yellow-light);color:var(--ink)}
.store-btn.and{--f:var(--brick-sky);--s:var(--brick-sky-dark);--t:var(--brick-sky-light);color:var(--ink)}
.store-btn{background:linear-gradient(180deg,color-mix(in oklab,var(--t) 92%,white) 0%,var(--f) 24%,var(--f) 80%);box-shadow:inset 0 4px 0 rgba(255,255,255,.32),inset 0 -8px 0 0 var(--s),0 6px 0 var(--s),0 8px 16px rgba(31,26,20,.16)}
.store-btn:hover{filter:brightness(1.04)}
.store-btn:active{transform:translateY(4px);box-shadow:inset 0 3px 0 rgba(255,255,255,.2),inset 0 -6px 0 0 var(--s),0 2px 0 var(--s),0 3px 8px rgba(31,26,20,.14)}
.store-btn.soon{cursor:default;pointer-events:none;filter:none;--f:var(--paper-2);--s:var(--paper-3);--t:#fff;color:var(--ink-4);box-shadow:inset 0 0 0 2px var(--paper-3),0 3px 0 var(--paper-3)}
.store-btn.soon .glyph{opacity:.4}
.store-btn.soon .st .v{color:var(--ink-3)}
.soon-tag{margin-left:auto;font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-3);background:var(--paper);border-radius:var(--r-pill);padding:4px 9px;box-shadow:inset 0 0 0 1.5px var(--paper-3)}

.cta-note{margin-top:var(--s-4);font-size:var(--fs-sm);color:var(--ink-3);min-height:1em}
.demo-link{display:inline-flex;align-items:center;gap:6px;margin-top:var(--s-6);font-weight:600;font-size:var(--fs-sm);color:var(--ink-2);text-decoration:none;border-bottom:2px solid color-mix(in oklab,var(--ink) 22%,transparent);padding-bottom:2px}
.demo-link:hover{color:var(--ink);border-color:var(--ink)}
.demo-link .ar{transition:transform var(--dur-base) var(--ease-out)}
.demo-link:hover .ar{transform:translateX(3px)}

/* hero ring — floated into the copy so text wraps around it */
.hero-art{
  position:relative;
  float:right;
  width:min(46%,440px);
  /* Shifted down a touch (mockup "pink circle") so the first headline line clears above
     it and the tiles + lede wrap the upper-left; circle shape-outside makes the wrap hug
     the ring instead of a bounding box (mockup "black line"). */
  margin:4.75rem 0 1.25rem 2.25rem;
  shape-outside:circle(50%);
  shape-margin:16px;
}
.hero-art .ring{width:100%;height:auto;filter:drop-shadow(0 18px 40px rgba(31,26,20,.16))}
/* The whole ring of tiles revolves around the SVG centre... */
.hero-art .ring .ring-rot{transform-box:view-box;transform-origin:250px 250px;animation:spin 60s linear infinite}
/* ...while every tile counter-rotates about its own centre at the same rate,
   so the tiles (and their letters) always stay upright. */
.hero-art .ring .tile{transform-box:fill-box;transform-origin:center;animation:spin 60s linear infinite reverse}
.hero-art .ring text{font-family:var(--font-display);font-weight:400}
@keyframes spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.hero-art .ring .ring-rot,.hero-art .ring .tile{animation:none}}
.hero-art .core{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);text-align:center}
.hero-art .core .cw{font-family:var(--font-display);font-size:clamp(28px,4vw,46px);color:var(--ink);letter-spacing:.02em}
.hero-art .core .cs{font-size:var(--fs-sm);color:var(--ink-3);font-weight:600;margin-top:2px}

/* ---- section frame ---- */
.sec{padding:var(--s-10) 0}
.sec-head{text-align:center;max-width:640px;margin:0 auto var(--s-8)}
.sec-head h2{font-family:var(--font-display);font-weight:400;font-size:clamp(30px,4vw,44px);line-height:1.05;letter-spacing:-.01em;margin:var(--s-3) 0 0}
.sec-head p{margin:var(--s-4) auto 0;color:var(--ink-2);font-size:var(--fs-md);max-width:52ch}

/* ---- how it works ---- */
.steps{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s-6)}
.step{background:var(--paper);border-radius:var(--r-card);padding:var(--s-7) var(--s-6);box-shadow:var(--shadow-card);position:relative}
.step .n{position:absolute;top:var(--s-6);right:var(--s-6);font-family:var(--font-display);font-size:44px;color:var(--paper-3);line-height:1}
.step .tiles{display:flex;gap:6px;margin-bottom:var(--s-5)}
/* Reuse the hero headline tiles' flat two-tone brick finish (solid face, darker bottom
   lip, ring-matched corner radius) instead of the glossy design-system default, so every
   letter tile on the page reads as the same object. */
.step .tiles .tile{
  border-radius:9px;
  background:var(--tile-face);
  box-shadow:0 3px 0 var(--tile-side),0 5px 7px rgba(31,26,20,.20);
}
/* The round screen's neutral tile, matching the hero headline's non-anchor tiles (see .wt).
   Card words use this for their inner letters; their first/last letters stay coloured
   "anchor" tiles (white text) via the brand .tile--* classes. */
.tile--stone{--tile-face:#D7BA8C;--tile-side:#AA7D55;color:#300F06}
.step h3{font-family:var(--font-body);font-weight:700;font-size:var(--fs-lg);margin:0 0 var(--s-2)}
.step p{color:var(--ink-2);font-size:var(--fs-base)}

/* ---- screenshots ---- */
.shots-sec{background:var(--paper-2);border-radius:var(--r-sheet);margin:0 auto;padding:var(--s-10) 0}
.shots{display:flex;gap:var(--s-6);justify-content:center;flex-wrap:wrap;padding:0 var(--gutter-mobile)}
.phone{position:relative;width:250px;padding:9px;background:linear-gradient(160deg,#2a2620,#141210);border-radius:42px;box-shadow:0 22px 48px rgba(31,26,20,.28),inset 0 0 0 2px rgba(255,255,255,.06);flex:0 0 auto}
/* 9:16 is the game's own design viewport (720x1280, project.godot [display]),
   so the reels that play in here (reel.css / reel.js) are neither letterboxed
   nor stretched. container-type:size is what lets a reel scale itself to the
   frame with 100cqw and no JS. */
.phone .screen{position:relative;border-radius:33px;overflow:hidden;aspect-ratio:9/16;background:var(--paper-3);container-type:size}
.phone .notch{position:absolute;top:9px;left:50%;transform:translateX(-50%);width:82px;height:22px;background:#141210;border-radius:999px;z-index:3;pointer-events:none}
.phone image-slot{position:absolute;inset:0}
/* The whole frame is the link to the playable demo — a bigger target than a
   text link, and the reel inside it is the advert. */
.phone-link{display:block;text-decoration:none;color:inherit;transition:transform var(--dur-med) var(--ease-out),box-shadow var(--dur-med) var(--ease-out)}
.phone-link:hover{transform:translateY(-4px);box-shadow:0 28px 56px rgba(31,26,20,.32),inset 0 0 0 2px rgba(255,255,255,.10)}
.phone-link:focus-visible{outline:4px solid var(--brick-sky);outline-offset:6px}
@media (prefers-reduced-motion:reduce){.phone-link{transition:none}.phone-link:hover{transform:none}}
/* Real screenshots dropped into the phone screens. Also the fallback under a
   live reel: reel.js adds .reel-live once it has actually built one, so a
   missing/failed/reduced-motion reel leaves the screenshot showing rather than
   an empty frame. */
.shot-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}
.screen.reel-live .shot-img{opacity:0}
/* Static placeholder for the phone screens until real screenshots are dropped in
   (replaces the design-time image-slot.js editor). Swap for <img> when ready. */
.shot-ph{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;text-align:center;padding:0 22px;background:linear-gradient(160deg,var(--paper-2),var(--paper-3));background-image:radial-gradient(var(--paper) 1.3px,transparent 1.5px);background-size:22px 22px;color:var(--ink-3);font-weight:600;font-size:var(--fs-sm);line-height:1.4}
.shot-cap{text-align:center;margin-top:var(--s-4);font-size:var(--fs-sm);font-weight:600;color:var(--ink-3)}

/* ---- bottom CTA band ---- */
.band{position:relative;overflow:hidden;background:linear-gradient(180deg,var(--brick-navy),var(--brick-navy-dark));border-radius:var(--r-sheet);padding:var(--s-10) var(--s-8);text-align:center;color:var(--paper)}
.band h2{font-family:var(--font-display);font-weight:400;font-size:clamp(30px,4vw,48px);color:var(--paper);margin:0}
.band p{color:color-mix(in oklab,var(--paper) 78%,var(--brick-navy));font-size:var(--fs-md);margin:var(--s-4) 0 0}
.band .cta-stores{justify-content:center;margin-top:var(--s-8)}
.band .cta-note{color:color-mix(in oklab,var(--paper) 64%,var(--brick-navy))}
.band .band-demo{margin-top:var(--s-6)}
.band .band-demo a{color:color-mix(in oklab,var(--paper) 80%,var(--brick-navy));border-color:color-mix(in oklab,var(--paper) 40%,transparent)}
.band .band-demo a:hover{color:var(--paper);border-color:var(--paper)}

/* ---- footer ---- */
.ftr{padding:var(--s-9) 0 var(--s-8)}
.ftr-in{display:flex;flex-wrap:wrap;gap:var(--s-6);align-items:center;justify-content:space-between}
.ftr-brand{display:flex;align-items:center;gap:var(--s-3)}
.ftr-brand img{width:36px;height:36px}
.ftr-brand .fb-txt{font-size:var(--fs-sm);color:var(--ink-3);line-height:1.4}
.ftr-brand .fb-txt b{color:var(--ink-2);font-weight:700;font-family:var(--font-body)}
.ftr-links{display:flex;flex-wrap:wrap;gap:var(--s-5)}
.ftr-links a{font-size:var(--fs-sm);font-weight:600;color:var(--ink-3);text-decoration:none}
.ftr-links a:hover{color:var(--ink)}
/* Build stamp: flex-basis:100% drops it onto its own row under the brand/links
   pair rather than competing with them for the space-between row. */
.ftr-build{flex-basis:100%;margin:0;font-size:var(--fs-sm);color:var(--ink-4);line-height:1.4}
.ftr-build .build-sha{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
.ftr-build .build-sep{margin:0 .5ch}

/* contact button (brick ghost) */
.btn-contact{display:inline-flex;align-items:center;gap:8px;min-height:44px;padding:0 20px;border-radius:var(--r-tight);font-family:var(--font-body);font-weight:700;font-size:var(--fs-sm);color:var(--ink);text-decoration:none;background:transparent;box-shadow:inset 0 0 0 2.5px var(--ink);transition:transform var(--dur-fast) var(--ease-out)}
.btn-contact:hover{color:var(--ink);background:color-mix(in oklab,var(--ink) 6%,transparent)}
.btn-contact:active{transform:translateY(2px)}

@media (max-width:860px){
  /* Ring stops floating and centers above the copy (it's first in source order now). */
  .hero-art{float:none;shape-outside:none;width:min(74%,300px);margin:0 auto var(--s-6)}
  .hero-copy{clear:both}
  .steps{grid-template-columns:1fr}
  .hdr-nav .madeby{display:none}
}

/* Phone widths: the headline is already at its clamp floor (32px) but the column keeps
   shrinking, so the deepest row ("chains" + two steps of indent) would run off the right
   edge. Ease the tile size and the step back until a 320px screen holds it. */
@media (max-width:520px){
  .word-tiles{--wt-step:1.4em;font-size:.66em}
}
