@charset "UTF-8";
/* Safrawn material exploration — one cloth that is pressed, impressed and inked.
   Landing, the circle of chapters and the reading state are states of the same surface. */
@font-face { font-family:"Bodoni Moda"; src:url("assets/fonts/bodoni-moda.woff2") format("woff2"); font-weight:400 500; font-display:swap; }
@font-face { font-family:"EB Garamond"; src:url("assets/fonts/eb-garamond.woff2") format("woff2"); font-weight:400 500; font-display:swap; }
@font-face { font-family:"EB Garamond"; src:url("assets/fonts/eb-garamond-italic.woff2") format("woff2"); font-style:italic; font-weight:400; font-display:swap; }
@font-face { font-family:"IBM Plex Mono"; src:url("assets/fonts/ibm-plex-mono.woff2") format("woff2"); font-weight:400; font-display:swap; }

:root {
  --hemH:96px; --hemW:96px;
  --linen-light:#eadfc6; --linen:#ded0b6; --cloth-deep:#c9b795; --cloth-deeper:#b5a179;
  --ink:#211c16; --rust:#7a3a1e;
  --emboss-hi:rgba(255,250,234,.62); --emboss-lo:rgba(84,63,36,.26);
  --ink-ease:cubic-bezier(.3,.6,.2,1);
  --ring-ink:0;            /* 0 = blind impression only, 1 = inked line */
  --sheen:1;               /* idle sheen strength, tunable */
}
html,body { margin:0; padding:0; background:var(--linen); }
html { scrollbar-gutter:stable; }
html[data-state="landing"],html[data-state="map"],html.is-moving { overflow:hidden; }
* { box-sizing:border-box; }
[hidden] { display:none!important; }
body { color:var(--ink); font-family:"EB Garamond",Georgia,serif; font-size:18px; -webkit-tap-highlight-color:transparent; overscroll-behavior-y:none; }
a { color:inherit; text-decoration:none; }
button { font:inherit; color:inherit; cursor:pointer; background:none; border:0; }
a:focus-visible,button:focus-visible { outline:1.5px solid var(--rust); outline-offset:6px; border-radius:2px; }

/* ---------- The cloth ---------- */
.cloth { position:fixed; inset:0; z-index:0; overflow:hidden; pointer-events:none;
  background:radial-gradient(120% 110% at 50% 42%,var(--linen-light) 0%,var(--linen) 42%,var(--cloth-deep) 80%,var(--cloth-deeper) 100%); }
.cloth-weave { position:absolute; inset:-24px; opacity:.5; mix-blend-mode:multiply; transform-origin:var(--press-x,50%) var(--press-y,50%);
  transform:scale(var(--give,1));
  background-image:repeating-linear-gradient(93deg,rgba(120,95,60,.10) 0 1px,transparent 1px 5px),repeating-linear-gradient(1.5deg,rgba(120,95,60,.07) 0 1px,transparent 1px 7px); }
.cloth-light { position:absolute; inset:0; background:radial-gradient(70% 60% at 18% 22%,rgba(150,118,74,.20),transparent 70%),radial-gradient(60% 55% at 84% 78%,rgba(126,96,56,.22),transparent 72%),radial-gradient(40% 40% at 62% 12%,rgba(240,231,210,.5),transparent 70%); }
/* Idle: a slow raking light that crosses the weave, as if the cloth breathes under a lamp. Not water. */
.cloth-sheen { position:absolute; inset:-30% -60%; opacity:calc(.55 * var(--sheen));
  background:linear-gradient(104deg,transparent 38%,rgba(255,247,226,.16) 47%,rgba(255,247,226,.22) 50%,rgba(255,247,226,.16) 53%,transparent 62%);
  animation:sheen 26s cubic-bezier(.45,0,.55,1) infinite; }
html[data-state="chapter"] .cloth-sheen { animation-play-state:paused; opacity:0; transition:opacity 1.2s; }
.cloth-vignette { position:absolute; inset:0; box-shadow:inset 0 0 180px rgba(84,63,36,.28),inset 0 0 40px rgba(84,63,36,.10); }
@keyframes sheen { 0% { transform:translateX(-38%); } 55%,100% { transform:translateX(38%); } }

/* The shaded surface (cloth-gl.js). It draws the same cloth as the layers beneath it, plus relief:
   the dimple of a touch and the fold that travels out from it. Without WebGL the layers beneath show. */
.cloth-gl { position:absolute; inset:0; display:block; width:100%; height:100%; }

/* ---------- Surface: landing + circle ---------- */
main { position:relative; z-index:1; }
.surface { position:fixed; inset:0; z-index:2; pointer-events:none; }
html[data-state="chapter"]:not(.is-moving) .surface { visibility:hidden; }
.loom { position:absolute; inset:0; width:100%; height:100%; overflow:visible; }
/* Inside the circle the parchment is bleached, as if it had lain in the sun: faint across the whole
   inside, a little more around the wordmark, never past the line. The fill is a radial gradient in
   the page's own coordinates (set per frame) and the weave shows through it. */
.loom-disc { stroke:none; }
.loom-rim,.loom-rim-light { fill:none; }
.loom-rim { stroke:rgb(84 63 36 / calc(.10 + .24 * var(--ring-ink))); stroke-width:1; }
.loom-rim-light { stroke:var(--emboss-hi); stroke-width:1.2; transform:translate(.6px,1px); }
.loom-spokes line { stroke:rgba(84,63,36,calc(.11 * var(--ring-ink))); stroke-width:1; }
.landing-hit { position:absolute; inset:0; pointer-events:auto; cursor:pointer; }
html:not([data-state="landing"]) .landing-hit { display:none; }
.landing-hit:focus-visible { outline-offset:-16px; }

.sigil { position:absolute; left:0; top:0; width:0; height:0; font-size:100px; transform-origin:0 0; will-change:transform; }
.rim .sigil { position:absolute; }
.sigil-word { position:absolute; left:0; top:0; transform:translate(-50%,-56%); white-space:nowrap; font-family:"Bodoni Moda","EB Garamond",Georgia,serif; font-weight:400; font-size:1em; line-height:1; letter-spacing:.12em; text-indent:.12em; text-transform:lowercase; pointer-events:none; }
.sigil-word .ltr { display:inline-block; text-indent:0; transform-origin:50% 62%; }
html[data-state="map"] .sigil-word { pointer-events:auto; cursor:pointer; }
.flyer { position:fixed; z-index:4; left:0; top:0; margin:0; transform-origin:0 0; pointer-events:none; white-space:nowrap; font-family:"Bodoni Moda",Georgia,serif; font-weight:400; color:var(--ink); will-change:transform; }
.threads { position:absolute; left:0; bottom:.48em; width:.744em; height:.9em; transform:translateX(-50%); overflow:visible; opacity:var(--threads,1); }
.threads path { fill:var(--rust); transform-box:fill-box; transform-origin:50% 100%; }
.threads path:nth-child(1) { animation:sway 11s ease-in-out infinite; }
.threads path:nth-child(2) { animation:sway 14s ease-in-out -4s infinite; }
.threads path:nth-child(3) { animation:sway 9s ease-in-out -2s infinite; }
@keyframes sway { 0%,100% { transform:rotate(-.6deg); } 50% { transform:rotate(.7deg); } }

/* Ink: --ink is how much ink an element has taken (0 blind, 1 inked); --emb is the blind impression,
   strongest half-way. Both are driven per frame as the fold reaches each element. */
.ring-box { position:absolute; left:50%; top:50%; width:min(78vmin,780px); height:min(78vmin,780px); transform:translate(-50%,-50%); }
/* A chapter mark: the dot sits at the end of its spoke, at the mark's anchor point; the words sit
   beyond the dot, away from the centre, on whichever side the mark lies. */
.mark { --ink:1; --emb:0; position:absolute; display:block; width:0; height:0; pointer-events:auto; cursor:pointer; color:rgb(33 28 22 / var(--ink)); }
.mark-body { position:absolute; left:0; top:0; display:flex; align-items:center; gap:12px; padding:10px 12px;
  text-shadow:0 1px 0 rgb(255 250 234 / calc(.62 * var(--emb))),0 -.5px 0 rgb(84 63 36 / calc(.26 * var(--emb))); }
.mark[data-dir="down"] .mark-body { flex-direction:column; }
.mark[data-dir="up"] .mark-body { flex-direction:column-reverse; }
.mark[data-dir="right"] .mark-body { flex-direction:row; }
.mark[data-dir="left"] .mark-body { flex-direction:row-reverse; }
.mark-text { display:flex; flex-direction:column; align-items:center; gap:8px; }
.mark[data-dir="right"] .mark-text { align-items:flex-start; text-align:left; }
.mark[data-dir="left"] .mark-text { align-items:flex-end; text-align:right; }
.mark[data-lean="right"] .mark-body { align-items:flex-start; } .mark[data-lean="right"] .mark-text { align-items:flex-start; text-align:left; }
.mark[data-lean="left"] .mark-body { align-items:flex-end; } .mark[data-lean="left"] .mark-text { align-items:flex-end; text-align:right; }
.mark-dot { flex:none; width:6px; height:6px; border-radius:50%; background:currentColor; box-shadow:0 1px 0 rgb(255 250 234 / calc(.62 * var(--emb))); transition:transform .4s var(--ink-ease); }
.mark-label { font:9px/1.2 "IBM Plex Mono",monospace; letter-spacing:.2em; text-transform:uppercase; white-space:nowrap; color:rgb(33 28 22 / calc(.82 * var(--ink))); }
.mark-title { font-family:"Bodoni Moda",Georgia,serif; font-size:clamp(19px,2.9vmin,27px); line-height:1.08; white-space:nowrap; }
@media (hover:hover) { .mark:hover { color:rgb(122 58 30 / var(--ink)); } .mark:hover .mark-dot { transform:scale(1.5); } }
.mark:focus-visible { color:rgb(122 58 30 / var(--ink)); outline-offset:10px; }
/* While a finger is on a mark it takes rust, its dot swells, and it settles into the dimple; it lifts as the finger leaves. */
.mark-text { transition:transform .28s var(--ink-ease); }
.mark.is-held { color:rgb(122 58 30 / var(--ink)); }
.mark.is-held .mark-dot { transform:scale(1.5) translateY(1px); }
.mark.is-held .mark-text { transform:translateY(2px) scale(.985); }
.mark.is-flying .mark-title { visibility:hidden; }
/* A chapter you have read leaves its dot hollow and its title a shade quieter for the rest of the visit (decided 5 Oct). */
.mark.is-read .mark-dot { background:transparent; box-shadow:inset 0 0 0 1px currentColor,0 1px 0 rgb(255 250 234 / calc(.62 * var(--emb))); }
.mark.is-read .mark-title { opacity:.72; }
/* Step 11: touch. The things that answer a finger show no tap flash, callout or selection; on the cover and the
   circle a finger that moves is still a press (two fingers can still zoom); the circle's wordmark gets a
   thumb-sized target; a bottom rim clears the home indicator. */
.landing-hit,.mark,.sigil-word,.rim,.selvedge a,.art-pair { -webkit-tap-highlight-color:transparent; -webkit-touch-callout:none; -webkit-user-select:none; user-select:none; }
html[data-state="landing"],html[data-state="map"] { touch-action:pinch-zoom; }
.sigil-word::before { content:""; position:absolute; left:0; right:0; top:-.55em; bottom:-.55em; }   /* in em: the wordmark is drawn at 100px and scaled */
.rim[data-side="bottom"] { height:calc(var(--hemH) + env(safe-area-inset-bottom,0px)); }
html[data-state="landing"] .mark,html[data-state="chapter"] .mark { pointer-events:none; }
.mark-exhibit { left:50%; top:17%; } .mark-statement { left:83%; top:38%; } .mark-materials { left:72%; top:79%; } .mark-updates { left:28%; top:79%; } .mark-founders { left:17%; top:38%; }

/* ---------- Ink: content is impressed blind, then takes ink ---------- */
.reading-body :is(h1,p,.spec,.principle,.material-row,.material-row-last,.founder,.image-captions,.image-caption,.origin-wordmark,.origin-meaning,.contact-link) {
  transition:color .62s var(--ink-ease),text-shadow .95s var(--ink-ease); }
.blind,.blind * { color:rgba(33,28,22,0)!important; text-shadow:0 1px 0 var(--emboss-hi),0 -.5px 0 var(--emboss-lo); }
/* The travelling title keeps its ink: it is already inked when it lands. */
.reading [data-fly] { color:var(--ink); }
.blind [data-fly]:not(.is-waiting) { color:var(--ink)!important; text-shadow:none; }
.reading-body :is(.art-pair,.detail-image) { transition:opacity .9s var(--ink-ease),filter 1.1s var(--ink-ease); }
.reading-body :is(.blind .art-pair,.blind .detail-image,.art-pair.blind,.detail-image.blind) { opacity:.16; filter:grayscale(1) contrast(.55) brightness(1.08); }

/* ---------- Reading state ---------- */
.reading { position:relative; z-index:1; min-height:100svh; padding:0; }
.reading-body { max-width:1440px; margin:0 auto; padding:40px 5vw 64px; }
.reading[data-side="top"] .reading-body { padding-top:calc(var(--hemH) + 32px); }
.reading[data-side="bottom"] .reading-body { padding-bottom:calc(var(--hemH) + 40px); }
.reading[data-side="left"] .reading-body { padding-left:calc(var(--hemW) + 3vw); }
.reading[data-side="right"] .reading-body { padding-right:calc(var(--hemW) + 3vw); }
.reading[data-side="top"] .exhibit-visual { top:calc(var(--hemH) + 16px); }
/* The rim: the edge of the circle leaning into the screen on the side opposite the pressed chapter,
   with the wordmark on it. It stays with you as you read; pressing it is the way back. */
.rim { position:fixed; z-index:6; display:block; cursor:pointer; }
.rim[data-side="top"] { left:0; right:0; top:0; height:var(--hemH); }
  .rim[data-side="bottom"] { left:0; right:0; bottom:0; height:calc(var(--hemH) + env(safe-area-inset-bottom,0px)); }
.rim[data-side="left"] { top:0; bottom:0; left:0; width:var(--hemW); }
.rim[data-side="right"] { top:0; bottom:0; right:0; width:var(--hemW); }
html:not([data-state="chapter"]) .rim,html.is-moving .rim { display:none; }
.hem-arc { position:absolute; inset:0; width:100%; height:100%; overflow:visible; }
.rim .loom-rim { stroke:rgba(84,63,36,.34); transition:stroke .35s; }
.rim .loom-rim-light { stroke:var(--emboss-hi); }
.rim .sigil { pointer-events:none; }
@media (hover:hover) { .rim:hover .loom-rim { stroke:var(--rust); } .rim:hover .sigil-word { color:var(--rust); } }
.rim:focus-visible { outline-offset:-8px; }

/* ---------- Selvedge: quiet service links at the cloth's edge ---------- */
.selvedge { position:fixed; z-index:7; right:clamp(12px,3vw,32px); bottom:max(10px,env(safe-area-inset-bottom)); display:flex; gap:12px; }
.selvedge a { display:flex; align-items:center; min-height:44px; padding:0 4px; font:9px/1.5 "IBM Plex Mono",monospace; letter-spacing:.08em; color:var(--ink-label); }
@media (hover:hover) { .selvedge a:hover { color:var(--rust); } }
html[data-state="chapter"] .selvedge,html.is-moving .selvedge { position:static; justify-content:center; padding-bottom:max(18px,env(safe-area-inset-bottom)); }

.no-js-note { position:relative; z-index:3; max-width:680px; margin:0 auto; padding:70vh 6vw 130px; text-align:center; font-size:16px; line-height:1.5; }

/* ---------- Tuning panel (?tune) ---------- */
.tune { position:fixed; z-index:50; left:12px; top:12px; bottom:12px; width:236px; overflow:auto; padding:12px 14px; border-radius:8px; background:rgba(33,28,22,.9); color:#efe5cf; font:11px/1.4 "IBM Plex Mono",monospace; }
.tune label { display:grid; grid-template-columns:1fr 46px; gap:0 8px; margin:5px 0; }
.tune input { grid-column:1 / -1; width:100%; accent-color:#c46a3c; }
.tune b { display:block; margin-bottom:6px; font-weight:400; letter-spacing:.14em; text-transform:uppercase; color:#d9a77f; }
.tune button { margin-top:8px; color:#d9a77f; }

@media (max-width:600px) {
  .ring-box { width:calc(100vw - 24px); height:min(114vw,490px); min-height:355px; }
  .mark-body { gap:8px; padding:8px 6px; } .mark-text { gap:6px; }
  .mark-label { font-size:8px; letter-spacing:.06em; }
  .mark-title { font-size:19px; }
  .mark-exhibit { top:14%; } .mark-statement { left:84%; top:36%; } .mark-founders { left:16%; top:36%; } .mark-materials,.mark-updates { top:78%; }
  :root { --hemH:84px; --hemW:56px; }
  .reading-body { padding:24px 6vw 48px; }
}
@media (max-width:350px) {
  .mark-label { font-size:7px; letter-spacing:.02em; } .mark-title { font-size:18px; }
  .mark-statement { left:85%; } .mark-founders { left:15%; }
}
/* Reduced motion (step 12): no fold, no dimple and no idle motion — states simply swap (material.js); the few
   fades that remain are switched off too. */
@media (prefers-reduced-motion:reduce) {
  *,*::before,*::after { animation:none!important; transition:none!important; scroll-behavior:auto!important; }
  .cloth-sheen,.threads path { animation:none!important; }
  .reading-body :is(.art-pair,.detail-image),.mark-dot,.mark-text,.rim .loom-rim { transition:none; }
}
