/* Self-hosted type, so the first frame never waits on a third party. IBM Plex Mono (OFL) for everything, headings
   included, since 10 Nov 2026; 600 is the headings' weight. Picked 28 Oct 2026 (Nathan's references: harmattan.ai, shield.ai). */
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:400;font-display:swap;src:url(/assets/fonts/ibm-plex-mono-400.woff2) format('woff2')}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:500;font-display:swap;src:url(/assets/fonts/ibm-plex-mono-500.woff2) format('woff2')}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:600;font-display:swap;src:url(/assets/fonts/ibm-plex-mono-600.woff2) format('woff2')}
/* One screen, one terminal session. The page never scrolls; the wheel drives the session.
   Frost: near-black blue, bone, brushed steel, one ice signal rationed to the prompt, the cursor
   and the progress bar. Glass is a flat frosted pane with a hairline. Hard corners.
   Over it, the HUD (hud.js): an instrument, not a uniform. Bone at low alpha, every number real. */
:root{
  --bg:#06080C;--bg-rgb:6,8,12;--fg:#F2F6FA;--muted:#7E8A99;
  --steel:#A3AEBD;--steel-hi:#E6EEF7;--steel-lo:#4C5665;
  --accent:#BFE6FF;--accent-rgb:191,230,255;
  --line:rgba(242,246,250,.12);
  --mono:'IBM Plex Mono','Courier New',monospace;--display:var(--mono);
  --radius:3px;
  color-scheme:dark;
}
*{box-sizing:border-box}
html,body{height:100%}
body{margin:0;background:var(--bg);color:var(--fg);font-family:var(--mono);-webkit-font-smoothing:antialiased;overflow:hidden;overscroll-behavior:none}

/* The intro: the logo, centred and large, forms out of loose sand into dim steel; a scan line leaves it lit bone,
   the ice brackets lock, and the wordmark glides into the bar. Skipped by any input, and by reduced motion.
   The sand (intro.js) is a canvas under the SVG. The SVG's dim layer starts hidden so the first frame never shows
   the crisp mark before the sand; the script shows it instead when there is no WebGL 2. */
#intro{display:none}
html.intro #intro{display:flex;position:fixed;inset:0;z-index:50;align-items:center;justify-content:center;background:var(--bg)}
#intro .sand{position:absolute;inset:0;width:100%;height:100%;display:block;pointer-events:none}
#introMark{position:relative;width:clamp(260px,40vw,600px);height:auto;overflow:visible;transform-origin:0 0;will-change:transform}
html.intro #introMark .dim{opacity:0}
#introMark .rv{transform:translateY(0)}
#introMark .ln{opacity:0}
#introMark .br{opacity:0;transform-box:fill-box;transform-origin:center;transform:scale(1.07)}
@keyframes iline{0%{opacity:0;transform:translateY(0)}6%{opacity:1}88%{opacity:1}100%{opacity:0;transform:translateY(189px)}}
html.intro .brand .wm,html.intro .hint{opacity:0}

.bar{position:fixed;top:0;left:0;right:0;z-index:3;display:flex;justify-content:space-between;align-items:center;
  padding:16px max(20px,env(safe-area-inset-right,0px)) 0 max(20px,env(safe-area-inset-left,0px));
  font-size:.68rem;letter-spacing:.22em;text-transform:uppercase;opacity:0;transition:opacity .9s ease .3s}
html.ready .bar{opacity:1}
.brand{display:flex;align-items:center;gap:12px;text-decoration:none;color:var(--fg)}
.brand{color:var(--fg)}
.brand .wm{display:block;height:31px;width:auto;overflow:visible}
/* The bar wordmark rests locked. Hover replays the scan over it: it drops to dim, the line passes down and relights it, the brackets lock again. */
.brand .wm .rv{transform:translateY(189px)}
.brand .wm .ln{opacity:0}
.brand .wm .br{transform-box:fill-box;transform-origin:center}
.brand:hover .wm .rv,.brand:focus-visible .wm .rv{animation:wrv .9s cubic-bezier(.45,0,.25,1)}
.brand:hover .wm .ln,.brand:focus-visible .wm .ln{animation:iline .9s cubic-bezier(.45,0,.25,1)}
.brand:hover .wm .br,.brand:focus-visible .wm .br{animation:wlock .9s cubic-bezier(.2,.7,.2,1)}
@keyframes wrv{from{transform:translateY(0)}to{transform:translateY(189px)}}
@keyframes wlock{0%,60%{opacity:.2;transform:scale(1.07)}100%{opacity:1;transform:scale(1)}}
.right{display:flex;align-items:center;gap:14px}
.book{color:var(--bg);text-decoration:none;font-weight:500;border-radius:var(--radius);padding:9px 16px;
  background:linear-gradient(180deg,var(--steel-hi) 0%,#B8C3D1 55%,var(--steel) 100%);transition:filter .25s}
.book:hover,.book:focus-visible{filter:brightness(1.08);outline:none}

#stage{position:fixed;inset:0;z-index:2;opacity:0;transition:opacity .9s ease .2s}
html.ready #stage{opacity:1}
.page{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  padding:12vh max(20px,env(safe-area-inset-right,0px)) 12vh max(20px,env(safe-area-inset-left,0px));
  opacity:0;transform:translateY(26px);visibility:hidden;pointer-events:none;
  transition:opacity .22s ease,transform .22s ease,visibility 0s .22s}
.page.active{opacity:1;transform:none;visibility:visible;pointer-events:auto;transition:opacity .45s ease .22s,transform .45s ease .22s,visibility 0s .22s}
.page.past{transform:translateY(-26px)}
.col{width:100%;max-width:calc(clamp(.95rem,1.3vw,1.2rem)*41);position:relative;isolation:isolate;display:flex;flex-direction:column;gap:28px}

.serif{margin:0;font-family:var(--display);font-weight:300;font-size:clamp(1.6rem,3.1vw,2.9rem);line-height:1.12;letter-spacing:-.01em;text-wrap:balance;opacity:0}
.page.done .serif[data-after]{animation:rise 1.1s cubic-bezier(.2,.7,.15,1) both}   /* homepage headings are scanned in from the scroll position instead (app.js) */
/* The heading's scan: an ice line, the logo's, passes down and the heading is lit above it. app.js moves it (--scan) and clips the rest. */
.serif::before{content:"";position:absolute;left:-.3em;right:-.3em;top:calc(var(--scan,0%) - 1px);height:1px;background:var(--accent);box-shadow:0 0 10px rgba(var(--accent-rgb),.55);opacity:0;pointer-events:none}
.serif.scanning::before{opacity:1}

/* Section codes: each page opens with its sequence number and a one-word code. Stamped with the page, never typed. */
.eyebrow{margin:0 0 -12px;display:flex;align-items:center;gap:12px;font-size:.68rem;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}
.eyebrow::before{content:"";width:18px;height:1px;background:var(--steel-lo)}

/* The HUD (hud.js): trackers, links and the instrument frame on one canvas over the session. It never takes a pointer;
   its session ruler replaces the progress bar, which stays as the fallback if the script never runs. */
#hud{position:fixed;inset:0;width:100%;height:100%;z-index:4;pointer-events:none;display:block}
/* The cloud (cloud.js): the team as sand on the contact page, drawn behind the session in the page's own black */
#cloud{position:fixed;inset:0;width:100%;height:100%;z-index:1;pointer-events:none;display:block}
html.hud #progress{display:none}
/* Grain: one tile of noise, made once at the screen's own density (app.js), laid over the black and the cloud and under
   the session, and jumped to a new offset ten times a second, as film grain does. Bone, barely there. It fades in from
   the first frame, while the logo forms: through the intro it lies over the intro's own black, then drops under the
   session as the intro hands over. Reduced motion (no intro): it is simply there, still. Without the script there is no
   tile, and nothing shows. */
#grain{position:fixed;inset:0;z-index:1;pointer-events:none;opacity:.05;background-image:var(--grain,none);background-size:var(--gs,160px) var(--gs,160px);
  animation:grain 1s steps(1,end) infinite,grain-in 3s ease-in-out}   /* as long as the logo takes to form (intro.js) */
html.intro #grain{z-index:51}
@keyframes grain-in{from{opacity:0}}
@keyframes grain{
  0%{background-position:0 0}10%{background-position:-37px 61px}20%{background-position:83px -24px}30%{background-position:-112px -77px}
  40%{background-position:29px 118px}50%{background-position:-64px 23px}60%{background-position:140px 95px}70%{background-position:-9px -131px}
  80%{background-position:57px 46px}90%{background-position:-98px 104px}}
@media (prefers-reduced-motion:reduce){#grain{animation:none}}
@keyframes rise{from{opacity:0;transform:translateY(18px);filter:blur(8px)}to{opacity:1;transform:none;filter:blur(0)}}
.serif::after{content:"";display:block;width:40px;height:1px;margin-top:14px;background:var(--steel-lo)}

.log{display:flex;flex-direction:column;gap:8px;font-size:clamp(.95rem,1.3vw,1.2rem);line-height:1.6;color:var(--fg)}
.log p{margin:0;min-height:1.6em;white-space:pre-wrap}
/* Links are ice, the colour of things you can touch, with an ice underline; they light to bone on hover.
   A text underline (not a border) so the "> " prompt and the cursor, both inline blocks, are never underlined. Links that leave the site carry a small arrow. */
.log a{color:var(--accent);text-decoration:underline;text-decoration-color:rgba(var(--accent-rgb),.5);text-decoration-thickness:1px;text-underline-offset:.3em;transition:color .25s,text-decoration-color .25s}
.log a:hover,.log a:focus-visible{color:var(--fg);text-decoration-color:var(--fg);outline:none}
.log a[target="_blank"].full:not(.typing)::after{content:"\2197";display:inline-block;margin-left:.45em;color:var(--accent);opacity:.85;transition:color .25s}
.log a[target="_blank"]:hover::after,.log a[target="_blank"]:focus-visible::after{color:var(--fg)}
.sel{user-select:all}
/* The prompt glyph is drawn, not typed: it appears with the first character of a line and leaves with it. */
.log p[data-type].on::before,.log p>[data-type]:first-child.on::before{content:"> ";color:var(--accent);display:inline-block;white-space:pre;border:0}
.typing>.tx::after,.page.done .cursor::after{content:"";display:inline-block;width:.5em;height:1em;margin-left:.18em;margin-right:-.68em;vertical-align:-.12em;background:var(--accent);animation:blink 1s steps(1) infinite}
@keyframes blink{50%{opacity:0}}

.glass,.sheet-inner{background:linear-gradient(180deg,rgba(255,255,255,.06),rgba(255,255,255,.02));
  -webkit-backdrop-filter:blur(18px) saturate(1.15);backdrop-filter:blur(18px) saturate(1.15);
  border:1px solid var(--line);border-radius:var(--radius);box-shadow:inset 0 1px 0 rgba(255,255,255,.14)}
/* The prompt component, an instrument framed as the HUD frames the screen: no pane, a ruled line carrying the prompt's
   real size, a hairline under it all and a crosshair at each corner. Inside: two lines on what it does (lit on hover;
   click to read it all), the scale it rates on, one primary action with a quiet way to read it all, and the brief. */
.file{position:relative;display:flex;flex-direction:column;gap:24px;padding:0 0 24px;color:var(--muted);opacity:0;transform:translateY(8px);transition:opacity .45s ease,transform .45s ease;
  background:linear-gradient(var(--line),var(--line)) 0 100%/100% 1px no-repeat}
.file .head{display:flex;align-items:center;gap:14px;height:12px;padding:0 18px 0 0;font-size:.62rem;font-weight:500;letter-spacing:.08em;line-height:1;text-transform:uppercase;color:var(--muted)}
.file .head i{flex:1;align-self:stretch;
  background:linear-gradient(var(--line),var(--line)) 0 50%/100% 1px no-repeat,
    repeating-linear-gradient(90deg,rgba(242,246,250,.16) 0 1px,transparent 1px 16px) 0 calc(50% + 2px)/100% 3px no-repeat,
    repeating-linear-gradient(90deg,rgba(242,246,250,.3) 0 1px,transparent 1px 80px) 0 calc(50% + 2px)/100% 5px no-repeat}
.file .peek{position:relative;display:flex;flex-direction:column;gap:4px;font-size:clamp(.82rem,1.02vw,.98rem);line-height:1.6;color:var(--steel);cursor:pointer;transition:color .3s}
.file .peek p{margin:0}
.file .peek .hook{color:var(--fg);white-space:nowrap}
.file .peek:hover{color:var(--fg)}
/* The receipt's scan: the headings' ice line passes down the quoted lines and leaves them lit for a moment */
.file .peek::after{content:"";position:absolute;left:-.6em;right:-.6em;top:0;height:1px;background:var(--accent);box-shadow:0 0 10px rgba(var(--accent-rgb),.55);opacity:0;pointer-events:none}
.file.scan .peek::after{animation:sweep .7s cubic-bezier(.45,0,.25,1)}
.file.scan .peek{animation:lit 1.4s ease-out}
@keyframes sweep{0%{top:0;opacity:1}85%{opacity:1}100%{top:100%;opacity:0}}
@keyframes lit{0%,45%{color:var(--fg)}100%{color:var(--steel)}}
/* The scale: a ruler, 0 to 3, numbered under each level. The HUD hunts along it (LVL ? · UNRATED). With the tally,
   each level carries a bar for its share of results and the count reads out on the right. */
.gauge{display:flex;align-items:flex-end;flex-wrap:wrap;gap:10px 22px;margin:10px 0}   /* room over the scale for a title, under it for the hunting tracker's label */
.gauge .cap{font-size:.62rem;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);line-height:1;padding-bottom:2px}
.gauge .scale{position:relative;flex:1 1 260px;max-width:480px;display:grid;grid-template-columns:repeat(4,1fr)}
.gauge .lv{display:flex;flex-direction:column;align-items:center;justify-content:flex-end;cursor:default}   /* one baseline, whatever the bars */
.gauge .pc,.gauge .lv i{display:none}
.gauge .lv b{position:relative;width:100%;padding:10px 0 2px;text-align:center;font-weight:500;font-size:.74rem;line-height:1;color:var(--steel);transition:color .2s;
  border-top:1px solid var(--steel-lo);background:repeating-linear-gradient(90deg,rgba(242,246,250,.16) 0 1px,transparent 1px 12.5%) 0 0/100% 3px no-repeat}
.gauge .lv b::before{content:"";position:absolute;left:50%;top:-4px;width:1px;height:8px;background:var(--steel)}
.gauge .lv.on b{color:var(--fg)}
/* A level's title, on hover (a tap on a phone): small caps on the dark, a hairline down to its level, the letters
   scrambling in like a heading's (app.js) */
.gauge .tip{position:absolute;left:0;bottom:calc(100% + 10px);z-index:2;padding:5px 8px;white-space:pre;font-size:.62rem;font-weight:500;letter-spacing:.08em;line-height:1;text-transform:uppercase;
  color:var(--fg);background:rgba(var(--bg-rgb),.9);border:1px solid var(--line);opacity:0;transition:opacity .12s;pointer-events:none}
.gauge .tip b{font-weight:500;color:var(--muted)}
.gauge .tip::after{content:"";position:absolute;left:var(--at,50%);top:100%;width:1px;height:10px;background:var(--steel-lo)}
.gauge .tip.on{opacity:1}
.gauge.tally .pc{display:block;margin-bottom:4px;font-size:.58rem;line-height:1;color:var(--muted)}
.gauge.tally .lv i{display:block;width:20px;height:calc(2px + var(--h,0)*24px);margin-bottom:4px;background:rgba(242,246,250,.14);border-top:1px solid rgba(242,246,250,.5)}
.gauge .field{margin:0 0 0 auto;display:flex;flex-direction:column;align-items:flex-end;gap:5px;font-size:.62rem;font-weight:500;letter-spacing:.08em;line-height:1;text-transform:uppercase;color:var(--muted)}
.gauge .field b{color:var(--fg);font-weight:500}
.file .row{display:flex;align-items:center;gap:24px;flex-wrap:wrap}
.file .row [data-copy]{font-size:.74rem;padding:12px 22px}   /* the one action: a size up from the bar's chip */
/* The brief: what follows the click. Copying ticks the first step in ice and lights the next. */
.brief{margin:-10px 0 0;padding:0;list-style:none;display:flex;flex-wrap:wrap;gap:6px 18px;font-size:.62rem;font-weight:500;letter-spacing:.08em;line-height:1.4;text-transform:uppercase;color:var(--muted)}
.brief li{display:flex;align-items:center;gap:7px}
.brief i{width:6px;height:6px;border:1px solid var(--steel-lo)}
.brief b{font-weight:500;color:var(--steel-lo)}
.brief.copied li:first-child{color:var(--accent)}
.brief.copied li:first-child i{background:var(--accent);border-color:var(--accent)}
.brief.copied li:nth-child(2){color:var(--fg)}
.brief.copied li:nth-child(2) i{border-color:var(--accent);animation:blink 1s steps(1) infinite}
@media (prefers-reduced-motion:reduce){.brief.copied li:nth-child(2) i{animation:none}}
.file::before{content:"";position:absolute;left:-7px;right:-7px;top:-1px;bottom:-7px;pointer-events:none;--x:rgba(242,246,250,.3);
  background:linear-gradient(var(--x),var(--x)) 0 7px/15px 1px no-repeat,linear-gradient(var(--x),var(--x)) 7px 0/1px 15px no-repeat,
    linear-gradient(var(--x),var(--x)) 100% 7px/15px 1px no-repeat,linear-gradient(var(--x),var(--x)) calc(100% - 7px) 0/1px 15px no-repeat,
    linear-gradient(var(--x),var(--x)) 0 calc(100% - 7px)/15px 1px no-repeat,linear-gradient(var(--x),var(--x)) 7px 100%/1px 15px no-repeat,
    linear-gradient(var(--x),var(--x)) 100% calc(100% - 7px)/15px 1px no-repeat,linear-gradient(var(--x),var(--x)) calc(100% - 7px) 100%/1px 15px no-repeat}
.file.show{opacity:1;transform:none}
.actions{display:flex;gap:10px}


.sheet{position:fixed;inset:0;z-index:20;display:flex;align-items:center;justify-content:center;padding:4vh max(20px,env(safe-area-inset-right,0px)) 4vh max(20px,env(safe-area-inset-left,0px));
  background:rgba(var(--bg-rgb),.55);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
.sheet[hidden]{display:none}
.sheet-inner{width:min(860px,100%);max-height:90vh;display:flex;flex-direction:column;overflow:hidden;background:linear-gradient(180deg,rgba(var(--bg-rgb),.86),rgba(var(--bg-rgb),.8))}
.prompt-bar{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;padding:10px 16px;border-bottom:1px solid var(--line);
  font-size:.68rem;letter-spacing:.22em;text-transform:uppercase;color:var(--muted)}
.reels{display:grid;grid-template-columns:repeat(2,1fr);gap:12px;opacity:0;transform:translateY(8px);transition:opacity .45s ease,transform .45s ease}
.reels.show{opacity:1;transform:none}
.reels a{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:12px 16px;
  font-size:.72rem;letter-spacing:.22em;text-transform:uppercase;color:var(--muted);text-decoration:none;transition:border-color .3s,color .3s}
.reel .sheet-inner{width:auto;max-width:min(860px,100%)}
.reel video{display:block;max-width:100%;max-height:75vh;background:#000;cursor:pointer}
.sheet pre{margin:0;padding:18px 18px 22px;overflow:auto;white-space:pre-wrap;font-family:var(--mono);font-size:.86rem;line-height:1.6;color:var(--fg);opacity:.92}

/* The film (staging only; app.js). A thumbnail fixed bottom left, inside the HUD's frame and clear of its clock: the
   film's own frame, an ice bracket at two corners like the chips, and what a press does. Then theatre mode: the session
   dims and blurs away, and the screen grows out of the thumbnail with a ruled line under it for time and seeking. */
.film{position:fixed;left:40px;bottom:56px;z-index:5;width:clamp(190px,17vw,290px);padding:0;margin:0;border:1px solid var(--line);border-radius:0;background:#000;cursor:pointer;
  opacity:0;transform:translateY(8px);pointer-events:none;transition:opacity .6s ease,transform .6s ease,border-color .25s,box-shadow .25s}
.film.show{opacity:1;transform:none;pointer-events:auto}
.film img{display:block;width:100%;height:auto;aspect-ratio:16/9;object-fit:cover;opacity:.78;transition:opacity .25s}
.film .tag{position:absolute;left:0;right:0;bottom:0;display:flex;justify-content:space-between;align-items:center;padding:18px 9px 7px;
  font-family:var(--mono);font-size:.66rem;font-weight:500;letter-spacing:.08em;line-height:1;text-transform:uppercase;color:var(--muted);
  background:linear-gradient(rgba(var(--bg-rgb),0),rgba(var(--bg-rgb),.92))}
.film .go{color:var(--accent);text-shadow:0 0 8px rgba(var(--accent-rgb),.4)}
/* The play button, drawn (a ▶ glyph turns into an emoji on some phones) */
.film .mark{position:absolute;left:50%;top:50%;width:46px;height:46px;margin:-27px 0 0 -23px;border:1px solid rgba(var(--accent-rgb),.8);
  background:rgba(var(--bg-rgb),.62);box-shadow:0 0 18px rgba(var(--accent-rgb),.22);transition:background .25s,box-shadow .25s}
.film .mark::before{content:"";position:absolute;left:50%;top:50%;margin:-8px 0 0 -5px;border:solid transparent;border-width:8px 0 8px 13px;border-left-color:var(--accent)}
.film .mark::after{content:"";position:absolute;inset:-1px;border:1px solid var(--accent);opacity:0;pointer-events:none}
.film:hover .mark,.film:focus-visible .mark{background:rgba(var(--accent-rgb),.16);box-shadow:0 0 26px rgba(var(--accent-rgb),.4)}
/* So it is noticed: the play button pulses, a ring leaving it every 2.6 s. Nothing else on the thumbnail moves. */
.film.show .mark::after{animation:film-ring 2.6s ease-out .7s infinite}
@keyframes film-ring{0%{transform:scale(1);opacity:.85}55%,100%{transform:scale(1.7);opacity:0}}
.film::before,.film::after,.again::before,.again::after,.theatre .screen::before,.theatre .screen::after{content:"";position:absolute;z-index:1;width:7px;height:7px;border:0 solid var(--accent);pointer-events:none}
.film::before,.again::before,.theatre .screen::before{left:-1px;top:-1px;border-top-width:1px;border-left-width:1px}
.film::after,.again::after,.theatre .screen::after{right:-1px;bottom:-1px;border-bottom-width:1px;border-right-width:1px}
.film:hover,.film:focus-visible{outline:none;border-color:rgba(var(--accent-rgb),.7);box-shadow:0 0 22px rgba(var(--accent-rgb),.22)}
.film:hover img,.film:focus-visible img{opacity:1}
/* On the contact page the thumbnail's corner goes to the prompt, for whoever came past it: the question it answers, the
   same Copy button as the prompt page, and what to do with it. Same place and width as the thumbnail it takes over from. */
.again{position:fixed;left:40px;bottom:56px;z-index:5;width:clamp(190px,17vw,290px);display:flex;flex-direction:column;align-items:flex-start;gap:12px;padding:14px 14px 13px;
  border:1px solid var(--line);background:rgba(var(--bg-rgb),.6);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
  font-size:.62rem;font-weight:500;letter-spacing:.08em;line-height:1.5;text-transform:uppercase;color:var(--muted);
  opacity:0;transform:translateY(8px);pointer-events:none;transition:opacity .6s ease,transform .6s ease}
.again.show{opacity:1;transform:none;pointer-events:auto}
.again p{margin:0}
.again .ask{color:var(--fg)}
.theatre{position:fixed;inset:0;z-index:25;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px;
  padding:4vh max(20px,env(safe-area-inset-right,0px)) 4vh max(20px,env(safe-area-inset-left,0px))}
.theatre[hidden]{display:none}
.theatre::before{content:"";position:absolute;inset:0;background:rgba(var(--bg-rgb),.94);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);opacity:0;transition:opacity .45s ease}
.theatre.on::before{opacity:1}
.theatre .screen,.theatre .ctrl{position:relative;width:min(100%,calc((100vh - 150px)*16/9),1280px)}
.theatre .screen{aspect-ratio:16/9;background:#000;border:1px solid var(--line);transform-origin:0 0;transition:transform .45s cubic-bezier(.2,.7,.2,1)}
.theatre .screen::before,.theatre .screen::after{width:10px;height:10px}
.theatre video{display:block;width:100%;height:100%;cursor:pointer;outline:none}
.theatre .play{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);padding:10px 22px;opacity:0;pointer-events:none;transition:opacity .25s,border-color .25s,box-shadow .25s,color .25s}
.theatre.on.paused .play{opacity:1;pointer-events:auto}
.theatre .ctrl{display:flex;align-items:center;gap:16px;opacity:0;transition:opacity .3s ease .15s;font-size:.62rem;font-weight:500;letter-spacing:.08em;line-height:1;text-transform:uppercase;color:var(--muted)}
.theatre.on .ctrl{opacity:1}
.theatre .time{white-space:nowrap}
.theatre .time b{color:var(--fg);font-weight:500}
.theatre .track{position:relative;flex:1;height:16px;cursor:pointer;background:linear-gradient(var(--line),var(--line)) 0 50%/100% 1px no-repeat}
.theatre .track i{position:absolute;left:0;top:50%;width:0;height:2px;margin-top:-1px;background:var(--accent);box-shadow:0 0 8px rgba(var(--accent-rgb),.5)}
@media (prefers-reduced-motion:reduce){.film,.again,.theatre .screen,.theatre::before,.theatre .ctrl{transition:none}.film.show .mark::after{animation:none}}
@media (max-width:640px){.again{left:12px;bottom:14px;width:176px;gap:10px;padding:11px 11px 10px;font-size:.56rem}.film{left:12px;bottom:14px;width:152px}.film .tag{padding:14px 7px 6px;font-size:.55rem}.film .mark{width:36px;height:36px;margin:-22px 0 0 -18px}.film .mark::before{margin:-6px 0 0 -4px;border-width:6px 0 6px 10px}}
#progress{position:fixed;top:0;right:0;width:2px;height:0;z-index:5;background:var(--accent);transition:height .12s linear}
.hint{position:fixed;left:50%;bottom:28px;transform:translateX(-50%);z-index:3;margin:0;font-size:.66rem;letter-spacing:.3em;text-transform:uppercase;color:var(--muted);animation:pulse 2.4s ease-in-out infinite;transition:opacity .6s}
.hint.off{opacity:0;animation:none}
@media (max-width:640px){.hint{transition:opacity .6s,left .6s ease}body:has(.film.show) .hint{left:calc(50% + 82px)}body:has(.again.show) .hint{left:calc(50% + 94px)}}   /* a phone: once the film's thumbnail (or the prompt chip after it) is up, centred in the room beside it */
@keyframes pulse{50%{opacity:.3}}
.foot{margin:0;font-size:.68rem;letter-spacing:.26em;text-transform:uppercase;color:var(--muted)}

/* The cursor is a selection: four corner brackets around a dot. They frame anything clickable, snap inward on click, and a ring ripples out. */
@media (pointer:fine){
  html.cur,html.cur *{cursor:none!important}
  #cur{position:fixed;left:0;top:0;z-index:30;pointer-events:none;opacity:0;transition:opacity .3s;will-change:transform}
  #cur.on{opacity:1}
  #cur .c{position:absolute;width:7px;height:7px;border:0 solid var(--accent);transition:border-color .12s,width .2s,height .2s}
  #cur .tl{left:0;top:0;border-top-width:1.5px;border-left-width:1.5px}
  #cur .tr{right:0;top:0;border-top-width:1.5px;border-right-width:1.5px}
  #cur .bl{left:0;bottom:0;border-bottom-width:1.5px;border-left-width:1.5px}
  #cur .br{right:0;bottom:0;border-bottom-width:1.5px;border-right-width:1.5px}
  #cur .dot{position:absolute;left:50%;top:50%;width:3px;height:3px;margin:-1.5px 0 0 -1.5px;background:var(--accent);transition:opacity .2s}
  #cur.hot .dot{opacity:0}
  #cur.hot .c{width:10px;height:10px}
  #cur.down .c{border-color:var(--fg)}
  .ripple{position:fixed;left:0;top:0;z-index:29;pointer-events:none;width:56px;height:56px;margin:-28px 0 0 -28px;border:1px solid var(--accent);animation:ripple .55s ease-out forwards}
  @keyframes ripple{from{transform:scale(.25);opacity:1}to{transform:scale(1.4);opacity:0}}
}

@media (max-width:640px){
  .gauge .field{order:-1;flex-basis:100%;flex-direction:row;justify-content:flex-start;gap:16px;margin:0 0 4px}   /* the tally reads above the scale, clear of the label under it */
  .brand .wm{height:26px}   /* as on the reading pages: leaves the book chip room on a 360px phone */
  .col{margin-left:0}
  .log{font-size:.92rem}
  .sheet pre{font-size:.8rem}
  .reels{grid-template-columns:1fr}
  .page{padding-top:10vh;padding-bottom:10vh}
}
@media (prefers-reduced-motion:reduce){
  .page,.page.active{transition-duration:.01s}
  .hint{animation:none}
  .page.done .serif[data-after]{animation-duration:.01s}
}

/* Type and the book button, locked 28 Oct 2026; one face since 10 Nov 2026. Headings in IBM Plex Mono semibold caps;
   the session, labels and buttons in Plex Mono too. The wordmark is its own drawing (Nov 2026), not set in any face. */
.serif{font-weight:600;text-transform:uppercase;line-height:.98;letter-spacing:-.005em;font-size:clamp(1.3rem,2.3vw,2.1rem)}
.bar,.file,.prompt-bar,.reels a,.foot,.hint,
.file button,.prompt-bar button,.reels .go,.theatre button,.again button{letter-spacing:.08em;font-weight:500}

/* Buttons. Every button is the HUD chip from the brand deck: glass, an ice hairline with corner brackets like the
   file chips and the cursor, a faint glow; hover is the lock, with one scan line passing down it. Nothing moves at rest. */
.book,.file button,.prompt-bar button,.reels a,.theatre button,.again button{position:relative;color:var(--accent);font:inherit;font-family:var(--mono);font-size:.68rem;font-weight:500;letter-spacing:.08em;text-transform:uppercase;text-decoration:none;white-space:nowrap;cursor:pointer;border-radius:0;padding:9px 16px;
  background:linear-gradient(180deg,rgba(var(--accent-rgb),0),rgba(var(--accent-rgb),.32),rgba(var(--accent-rgb),0)) 0 -6px/100% 3px no-repeat,rgba(var(--bg-rgb),.42);
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
  border:1px solid rgba(var(--accent-rgb),.3);
  box-shadow:0 0 14px rgba(var(--accent-rgb),.08),inset 0 0 12px rgba(var(--accent-rgb),.05);
  text-shadow:0 0 8px rgba(var(--accent-rgb),.4);transition:border-color .25s,box-shadow .25s,color .25s}
/* A testimonial tile is one whole button; "▶ play" stays inside it as a plain ice label so a phone, with no hover and no cursor, still says what a tap does. */
.reels a{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:14px 18px;color:var(--muted);text-shadow:none}
.reels .go{color:var(--accent);text-shadow:0 0 8px rgba(var(--accent-rgb),.4)}
@media (hover:none){.reels a{border-color:rgba(var(--accent-rgb),.55)}}
.book::before,.book::after,.file button::before,.file button::after,.prompt-bar button::before,.prompt-bar button::after,.reels a::before,.reels a::after,.theatre button::before,.theatre button::after,.again button::before,.again button::after{content:"";position:absolute;width:7px;height:7px;border:0 solid var(--accent);pointer-events:none}
.book::before,.file button::before,.prompt-bar button::before,.reels a::before,.theatre button::before,.again button::before{left:-1px;top:-1px;border-top-width:1px;border-left-width:1px}
.book::after,.file button::after,.prompt-bar button::after,.reels a::after,.theatre button::after,.again button::after{right:-1px;bottom:-1px;border-bottom-width:1px;border-right-width:1px}
.book:hover,.book:focus-visible,.file button:hover,.file button:focus-visible,.prompt-bar button:hover,.prompt-bar button:focus-visible,.reels a:hover,.reels a:focus-visible,.theatre button:hover,.theatre button:focus-visible,.again button:hover,.again button:focus-visible{
  filter:none;color:var(--fg);border-color:rgba(var(--accent-rgb),.7);outline:none;
  box-shadow:0 0 22px rgba(var(--accent-rgb),.22),inset 0 0 14px rgba(var(--accent-rgb),.09);animation:scan .7s cubic-bezier(.3,.6,.2,1) 1}
@keyframes scan{from{background-position:0 -6px,0 0}to{background-position:0 calc(100% + 6px),0 0}}
@media (prefers-reduced-motion:reduce){.book:hover,.file button:hover,.prompt-bar button:hover,.reels a:hover,.theatre button:hover,.again button:hover{animation:none}}

/* The secondary action is a plain ice link, not a second chip */
.file button.link{background:none;border:0;border-bottom:1px solid rgba(var(--accent-rgb),.55);box-shadow:none;padding:2px 0;text-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none;color:var(--accent);transition:color .25s,border-color .25s}
.file button.link::before,.file button.link::after{content:none}
.file button.link:hover,.file button.link:focus-visible{color:var(--fg);border-bottom-color:var(--fg);box-shadow:none;animation:none}
/* Copied: the chip locks */
.file button.done{color:var(--fg);border-color:var(--accent);box-shadow:0 0 22px rgba(var(--accent-rgb),.28),inset 0 0 14px rgba(var(--accent-rgb),.1)}
#sheet .prompt-bar{justify-content:flex-end}

/* The whole line is always in the page, for search engines and screen readers; the part not yet typed waits in place, invisible */
.log .rest{opacity:0}
/* Visually hidden, still read by search engines and screen readers */
/* A scrambling heading: the flicker sits on top, the real text holds the space underneath */
.serif{position:relative}
.serif .sc{position:absolute;left:0;top:0;width:100%}
.serif.scrambling .real{visibility:hidden}
.vh{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
/* Footer links on the last page */
.foot a{color:inherit;text-decoration:underline;text-decoration-color:rgba(var(--accent-rgb),.4);text-underline-offset:.3em;transition:color .25s}
.foot a:hover,.foot a:focus-visible{color:var(--accent);outline:none}
