/* The first-visit loader, "Molten pour" (owner, 6 Oct 2026; approved mockup loader-options/curtain-1-pour.html). The markup
   is the first thing in <body> (templates/layout.html), so this is on the very first paint; fable-loader.js runs it.
   Colours and fonts are the site's own tokens (styles.css, fable.css); dark only. It covers EVERY page load until that page
   is ready (owner, 6 Oct evening); html.fl-off hides it only for browser automation or ?loader=0, html.fl-js says the script is running, html.fl-lock holds the page still while it is up. With no script
   at all, the overlay still fades away after 10 s (flGone), so nobody is ever kept out. Only transform, opacity and filter
   animate; the pour itself is a canvas, drawn by the script, that stops once the logo has melted into the seam. */
.fl{--fl-g:clamp(150px,min(27vh,56vw),250px);--fl-ease:cubic-bezier(.65,0,.35,1);--fl-part:cubic-bezier(.72,0,.2,1);
  position:fixed;inset:0;z-index:1500;overflow:hidden;color:var(--ink);font:400 15px/1.55 var(--sans);touch-action:none;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}
/* drawn at the approved size: undo the desktop page scale (styles.css zooms html by .66825 from 1100px) */
@media (min-width:1100px){.fl{zoom:1.49645}}
html.fl-off .fl{display:none!important}
html.fl-lock{overflow:hidden}
html:not(.fl-js) .fl{animation:flGone .6s ease 10s forwards}
.fl p{margin:0}
/* two heavy dark panels that meet, invisibly, down the middle; a faint warmth sits behind the logo */
.fl-pnl{position:absolute;z-index:1;top:0;bottom:0;width:calc(50% + 1px);will-change:transform;
  background:radial-gradient(64% 52% at var(--x) 46%,rgba(67,35,15,.4),rgba(67,35,15,0) 72%),repeating-linear-gradient(90deg,rgba(255,236,214,.014) 0 1px,transparent 1px 4px),var(--bg)}
.fl-l{left:0;--x:100%}.fl-r{right:0;width:50%;--x:0%}
/* the hot seam: a bright bronze line on each inner edge, and the heat it throws onto the panel face */
.fl-pnl::after{content:"";position:absolute;top:0;bottom:0;width:2px;opacity:0;transform:scaleY(0);transform-origin:50% 46%;
  background:linear-gradient(180deg,transparent,#a86c3c 14%,#f8d49a 34%,#fff0cc 46%,#f8d49a 60%,#a86c3c 84%,transparent);
  box-shadow:0 0 10px 1px rgba(248,212,154,.6),0 0 36px 6px rgba(218,140,70,.26),0 0 90px 16px rgba(218,140,70,.1)}
.fl-l::after{right:0}.fl-r::after{left:0}
.fl-pnl::before{content:"";position:absolute;inset:0;opacity:0;
  background:radial-gradient(min(260px,34vw) 62% at var(--x) 46%,rgba(226,140,70,.24),rgba(150,72,28,.08) 45%,rgba(67,35,15,0) 78%)}
.fl-flare{position:absolute;z-index:2;left:50%;top:46%;width:min(46vw,340px);height:150vh;opacity:0;pointer-events:none;transform:translate(-50%,-50%);
  background:radial-gradient(closest-side,rgba(255,236,204,.32),rgba(218,150,80,.13) 45%,rgba(218,150,80,0));mix-blend-mode:screen}
/* the page shows through the parting panels dim (brightness .35) and comes up to full over 1.45 s */
.fl-dim{position:absolute;inset:0;z-index:0;background:#000;opacity:.65}

.fl-stage{position:absolute;z-index:3;left:50%;top:46%;width:calc(var(--fl-g)*1.4);height:calc(var(--fl-g)*1.4);transform:translate(-50%,-50%)}
.fl-art{position:absolute;inset:0}
.fl-cv{position:absolute;inset:0;width:100%;height:100%}
/* the glow behind the letter fades out before the canvas's own edge (in the mockup its square edge showed faintly); the
   soft margin stays clear of the logo, which starts 14% in */
.fl-cv,.fl-mini canvas{-webkit-mask-image:linear-gradient(180deg,transparent,#000 12%,#000 88%,transparent),linear-gradient(90deg,transparent,#000 12%,#000 88%,transparent);-webkit-mask-composite:source-in;
  mask-image:linear-gradient(180deg,transparent,#000 12%,#000 88%,transparent),linear-gradient(90deg,transparent,#000 12%,#000 88%,transparent);mask-composite:intersect}
/* the cold letter, before the canvas draws (and with no script): near-black with a faint warm rim, as the canvas starts */
.fl-logo{position:absolute;left:14.2857%;top:14.2857%;width:71.4286%;height:71.4286%;max-width:none;filter:brightness(.19) drop-shadow(0 0 9px rgba(206,160,118,.17))}
.fl.live .fl-logo{visibility:hidden}
.fl-cap{position:absolute;left:50%;top:calc(var(--fl-g)*1.11 + 18px);transform:translateX(-50%);display:flex;flex-direction:column;align-items:center;gap:14px;white-space:nowrap;text-align:center}
.fl-prep{padding-left:.52em;font:500 12px/1 var(--mono);letter-spacing:.52em;text-transform:uppercase;color:rgba(207,194,181,.82)}
.fl-dots i,.cl-dots i{font-style:normal;color:var(--brand);animation:flBreathe 1.8s ease-in-out infinite}
.fl-dots i:nth-child(2),.cl-dots i:nth-child(2){animation-delay:.22s}.fl-dots i:nth-child(3),.cl-dots i:nth-child(3){animation-delay:.44s}
.fl-enter{font:500 11px/1 var(--mono);letter-spacing:.08em;color:var(--muted);opacity:0;visibility:hidden;transform:translateY(4px);transition:opacity .6s,transform .6s,visibility 0s .6s}
.fl-enter.on{opacity:1;visibility:visible;transform:none;transition:opacity .6s,transform .6s}
.fl-go{margin-left:.3em;padding:6px 2px;border:0;background:none;font:inherit;letter-spacing:inherit;color:var(--brand-text-solid);cursor:pointer;text-decoration:underline;text-decoration-color:rgba(235,185,122,.35);text-underline-offset:4px}
.fl-go:hover{color:var(--brand-hi);text-decoration-color:currentColor}
.fl-go:focus-visible{outline:1px solid var(--brand);outline-offset:3px;border-radius:2px}

/* intro: the cold letter fades up, the word follows (from the first paint, script or not) */
.fl-art{animation:flColdIn 1s ease both}
.fl-cap{animation:flRise .8s var(--fl-ease) .3s both}
/* reveal: the seam ignites from the logo, the logo melts into its light, the panels slide apart, the page comes up */
.fl.out{pointer-events:none}
.fl.out .fl-cap{animation:flCapOut .35s ease forwards}
.fl.out .fl-pnl::after{animation:flIgnite .5s var(--fl-ease) forwards,flEdgeCool 1.2s ease-in .6s forwards}
.fl.out .fl-pnl::before{animation:flFaceHeat .6s ease .1s forwards}
.fl.out .fl-flare{animation:flFlare 1.3s ease-out .05s forwards}
.fl.out .fl-art{animation:flIntoLight .8s cubic-bezier(.4,0,.7,.2) .05s forwards}
.fl.out .fl-l{animation:flPartL 1.2s var(--fl-part) .5s forwards}
.fl.out .fl-r{animation:flPartR 1.2s var(--fl-part) .5s forwards}
.fl.out .fl-dim{animation:flUndim 1.45s var(--fl-part) .5s both}
/* the page's own parts (fable-loader.js sets each one's transform-origin to the logo's centre on screen). They sit beside
   .fl, not inside it, so none of its --fl-* values reach them: the easing is written out here (it is --fl-part). A var()
   that doesn't resolve makes the whole animation invalid, and the page would only undim, never zoom (build test checks). */
.fl-rise{animation:flPageIn 1.45s cubic-bezier(.72,0,.2,1) .5s both}
/* a later page of the session: the same reveal, quicker (fable-loader.js QUICK_OUT_MS) */
.fl.quick.out .fl-pnl::after{animation:flIgnite .25s var(--fl-ease) forwards,flEdgeCool .6s ease-in .3s forwards}
.fl.quick.out .fl-pnl::before{animation:flFaceHeat .3s ease .05s forwards}
.fl.quick.out .fl-flare{animation:flFlare .7s ease-out forwards}
.fl.quick.out .fl-art{animation:flIntoLight .4s cubic-bezier(.4,0,.7,.2) forwards}
.fl.quick.out .fl-l{animation:flPartL .7s var(--fl-part) .2s forwards}
.fl.quick.out .fl-r{animation:flPartR .7s var(--fl-part) .2s forwards}
.fl.quick.out .fl-dim{animation:flUndim .8s var(--fl-part) .2s both}
.fl-rise.fl-rise-quick{animation:flPageIn .8s cubic-bezier(.72,0,.2,1) .2s both}
/* a later page that was ready almost at once: no curtain, a short fade (SKIP_OUT_MS) */
.fl.skip{opacity:0;transition:opacity .18s ease;pointer-events:none}
/* zoomed, the page is 3% wider than the screen. Clip it (overflow-x: clip makes no scroller, so the page still scrolls and
   the header still sticks), or a phone widens its layout to fit it and the whole screen shrinks and jumps (fable-loader.js) */
html.fl-rising,html.fl-rising body{overflow-x:clip}

/* calm (prefers-reduced-motion, or a canvas that won't draw): a still logo, still dots, and one soft fade */
.fl.calm .fl-cv{display:none}
.fl.calm .fl-logo{filter:drop-shadow(0 8px 18px rgba(0,0,0,.55))}
.fl.calm .fl-art,.fl.calm .fl-cap{animation:flSoft .6s ease both}
.fl.calm .fl-dots i{animation:none;opacity:.6}
.fl.calm .fl-dim{display:none}
.fl.calm.out{opacity:0;transition:opacity .6s ease}
.fl.calm.out .fl-pnl,.fl.calm.out .fl-pnl::before,.fl.calm.out .fl-pnl::after,.fl.calm.out .fl-flare,.fl.calm.out .fl-art{animation:none}
@media (prefers-reduced-motion:reduce){
  .fl-cv{display:none}
  .fl-logo{filter:drop-shadow(0 8px 18px rgba(0,0,0,.55))}
  .fl-art,.fl-cap{animation:flSoft .6s ease both}
  .fl-dots i,.cl-dots i{animation:none;opacity:.6}
  .fl-dim{display:none}
}

/* the small pour (FableLoader.mini) inside a page's loading card: the logo's box is the host, the canvas 1.4× it */
.fl-mini{position:absolute;inset:0;display:block;pointer-events:none}
.fl-mini img{position:absolute;inset:0;width:100%;height:100%;max-width:none;filter:brightness(.19) drop-shadow(0 0 4px rgba(206,160,118,.17))}
.fl-mini canvas{position:absolute;left:-20%;top:-20%;width:140%;height:140%}
.fl-mini.live img{visibility:hidden}
.fl-mini.calm img{filter:drop-shadow(0 4px 10px rgba(0,0,0,.5))}
.fl-mini.calm canvas{display:none}
@media (prefers-reduced-motion:reduce){.fl-mini img{filter:drop-shadow(0 4px 10px rgba(0,0,0,.5))}.fl-mini canvas{display:none}}

@keyframes flColdIn{from{opacity:0;transform:scale(.97)}to{opacity:1;transform:none}}
@keyframes flRise{from{opacity:0;transform:translate(-50%,8px)}to{opacity:1;transform:translateX(-50%)}}
@keyframes flSoft{from{opacity:0}}
@keyframes flBreathe{0%,100%{opacity:.15}50%{opacity:.95}}
@keyframes flCapOut{to{opacity:0}}
@keyframes flIgnite{from{opacity:0;transform:scaleY(0)}to{opacity:1;transform:scaleY(1)}}
@keyframes flEdgeCool{from{opacity:1}to{opacity:.55}}
@keyframes flFaceHeat{to{opacity:1}}
@keyframes flFlare{0%{opacity:0;transform:translate(-50%,-50%) scaleX(.9)}40%{opacity:1}100%{opacity:0;transform:translate(-50%,-50%) scaleX(.15)}}
@keyframes flIntoLight{0%{opacity:1;filter:brightness(1) blur(0)}45%{opacity:1;filter:brightness(1.9) blur(1px)}100%{opacity:0;filter:brightness(2.8) blur(7px);transform:scale(.9,1.06)}}
@keyframes flPartL{to{transform:translateX(calc(-100% - 120px))}}
@keyframes flPartR{to{transform:translateX(calc(100% + 120px))}}
@keyframes flUndim{from{opacity:.65}to{opacity:0}}
@keyframes flPageIn{from{transform:scale(1.03)}to{transform:none}}
@keyframes flGone{to{opacity:0;visibility:hidden;pointer-events:none}}
