/* Motion from the Tallis concept site, re-coloured for Studio Who (27 Oct 2026).
   Loader battens, crosshair cursor, word reveals, batten shutters, drawing to built,
   the live 3D build, the film player and the section dots. Tallis variable names are
   kept so the shared scripts work unchanged; their values are Studio Who's. */
:root { --paper: #fafaf8; --render: #efe9df; --charcoal: #152d48; --batten: #f19d3e; --line: rgba(21,45,72,.14); --muted: rgba(21,45,72,.62);
  --sans: 'DM Sans', 'Helvetica Neue', Arial, sans-serif; --mono: 'DM Sans', 'Helvetica Neue', Arial, sans-serif; --ease: cubic-bezier(.2,.7,.1,1) }
.mono { font: 600 11px/1.6 var(--sans); letter-spacing: .16em; text-transform: uppercase }
html.lenis, html.lenis body { height: auto }
.lenis.lenis-smooth { scroll-behavior: auto !important }
.veil { position: fixed; inset: 0; z-index: 60; background: var(--paper); display: grid; place-items: center; pointer-events: none; opacity: 0; transition: opacity .6s var(--ease) }
.veil.on { opacity: 1; pointer-events: auto }
.veil .word { font: 600 15px var(--sans); letter-spacing: .24em; text-transform: uppercase; display: flex; overflow: hidden }
.veil .word span { display: inline-block; transform: translateY(110%) }
.veil.loading .word span { animation: rise .9s var(--ease) forwards }
.veil .bar { position: absolute; left: 50%; top: calc(50% + 22px); width: 120px; height: 1px; background: var(--line); transform: translateX(-50%); overflow: hidden }
.veil .bar i { position: absolute; inset: 0; background: var(--charcoal); transform: scaleX(0); transform-origin: left; transition: transform .4s var(--ease) }
@keyframes rise { to { transform: none } }
/* ---------- custom cursor (desktop only) ---------- */
.cursor { position: fixed; z-index: 70; left: 0; top: 0; width: 10px; height: 10px; margin: -5px 0 0 -5px; border-radius: 50%; background: #fff; mix-blend-mode: difference; pointer-events: none; display: grid; place-items: center; transition: width .4s var(--ease), height .4s var(--ease), margin .4s var(--ease), opacity .3s }
.cursor span { font: 500 10px var(--mono); letter-spacing: .1em; text-transform: uppercase; color: #000; opacity: 0; transition: opacity .2s }
.cursor.big { width: 76px; height: 76px; margin: -38px 0 0 -38px }
.cursor.big span { opacity: 1 }
.cursor.hide { opacity: 0 }
@media (hover: none), (pointer: coarse) { .cursor { display: none } }
/* The 3D build, pinned while you scroll through the six stages */
.built { position: relative; height: 560vh; background: var(--paper) }
.built .pin { position: sticky; top: 0; height: 100vh; height: 100svh; overflow: hidden }
.built canvas { position: absolute; inset: 0; width: 100% !important; height: 100% !important }
.built .photo { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; pointer-events: none }
.built .pin::after { content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none; background: linear-gradient(90deg, rgba(20,22,24,.55) 0%, rgba(20,22,24,0) 55%); opacity: 0; transition: opacity .6s }
.built.real .pin::after { opacity: 1 }
.built.static .pin::after { display: none }
.built .head { position: absolute; z-index: 2; left: var(--gutter); top: 84px; display: grid; gap: 8px; max-width: 360px }
.built .head h2 { font-size: clamp(22px, 2.2vw, 30px); line-height: 1.15; letter-spacing: -.01em }
.built ol { position: absolute; z-index: 2; left: var(--gutter); bottom: 22px; list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; width: min(340px, calc(100% - 2 * var(--gutter))) }
.built li { display: grid; grid-template-columns: 30px 1fr; gap: 0 10px; color: var(--muted); transition: color .4s }
.built li p { grid-column: 2; max-height: 0; overflow: hidden; opacity: 0; font-size: 14px; color: var(--charcoal); transition: max-height .6s var(--ease), opacity .4s }
.built li.on { color: var(--charcoal) }
.built li.on p { max-height: 80px; opacity: 1; padding-block: 2px 8px }
.built .progress { position: absolute; z-index: 2; right: var(--gutter); bottom: 26px; width: 120px; height: 1px; background: var(--line) }
.built .progress i { position: absolute; inset: 0; background: var(--charcoal); transform-origin: left; transform: scaleX(0) }
.built.real .head, .built.real ol, .built.real .progress { color: #fff }
.built.real li p { color: #fff }
.built.real .progress { background: rgba(255,255,255,.35) } .built.real .progress i { background: #fff }
/* Without 3D (no WebGL, or motion turned off): the six stage stills in a grid */
.built.static { height: auto; padding-block: clamp(80px, 10vw, 160px) }
.built.static .pin { position: static; height: auto; overflow: visible }
.built.static canvas, .built.static .photo, .built.static .progress { display: none }
.built.static .head { position: static; margin: 0 var(--gutter) 40px }
.built.static ol { position: static; margin: 0 var(--gutter); width: auto; display: grid; grid-template-columns: repeat(3, 1fr); gap: 32px 24px }
.built.static li { grid-template-columns: 1fr; color: var(--charcoal) }
.built.static li p { max-height: none; opacity: 1; grid-column: 1 }
.built.static li img { display: block !important; width: 100%; aspect-ratio: 16 / 10; object-fit: contain; background: var(--render); margin-bottom: 10px }
.built li img { display: none }
/* ---------- reveal states (only once the script has started) ---------- */
.js [data-reveal] { opacity: 0; transform: translateY(26px) }
.js [data-words] .w { display: inline-block; overflow: hidden; vertical-align: top }
.js [data-words] .w > span { display: inline-block; transform: translateY(105%) }
/* ---------- drawing to built ---------- */
.drawn { position: relative; height: 320vh; background: var(--paper) }
.drawn .pin { position: sticky; top: 0; height: 100vh; height: 100svh; overflow: hidden; display: grid; place-items: center }
/* Drawing, model and photo share one frame cut to the dusk photo's shape, rendered from its solved camera,
   so they line up exactly. The frame fills the screen (like object-fit: cover). */
.drawn .box { --ar: 2560 / 1440; --w: max(100%, calc(100svh * var(--ar))); position: absolute; top: 50%; width: var(--w); aspect-ratio: var(--ar); transform: translateY(-50%);
  left: clamp(calc(100% - var(--w)), calc(50% - var(--fx, .5) * var(--w)), 0px) }   /* centred on the house; a page can set --fx to the house's place across the photo (0 to 1) */
.drawn .box img, .drawn .box .lines, .drawn .box .lines svg { position: absolute; inset: 0; width: 100%; height: 100% }
.drawn .box img { opacity: 0 }
.drawn .lines { color: var(--charcoal) }
.drawn .cap { position: absolute; z-index: 2; left: var(--gutter); top: 84px; display: grid; gap: 8px; transition: color .6s }
.drawn .cap h2 { font-size: clamp(22px, 2.2vw, 30px); line-height: 1.15; letter-spacing: -.01em; max-width: 14ch }
.drawn .steps { position: absolute; z-index: 2; left: var(--gutter); bottom: 22px; display: flex; gap: 22px; color: var(--muted); transition: color .6s }
.drawn .steps span { transition: color .4s }
.drawn .steps span.on { color: var(--charcoal) }
.drawn.real .cap, .drawn.real .steps, .drawn.real .steps span.on { color: #fff }
.drawn.real .pin::after { opacity: 1 }
.drawn .pin::after { content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none; background: linear-gradient(90deg, rgba(20,22,24,.5), rgba(20,22,24,0) 55%); opacity: 0; transition: opacity .6s }
.drawn.still { height: auto; padding-block: clamp(80px, 10vw, 160px) }
.drawn.still .pin { position: static; height: auto; display: block }
.drawn.still .cap { position: static; margin: 0 var(--gutter) 32px }
.drawn.still .box { position: relative; left: auto; top: auto; transform: none; margin: 0 auto; width: min(100% - 2 * var(--gutter), 1200px) }
.drawn.still .box .model { opacity: .55 }
.drawn.still .photo, .drawn.still .steps { display: none }
/* ---------- cinematic film player ---------- */
.player { position: fixed; inset: 0; z-index: 80; background: #091828; color: #fff; display: grid; grid-template-rows: auto 1fr auto; visibility: hidden; opacity: 0; transition: opacity .5s ease, visibility 0s .5s }
.player.open { visibility: visible; opacity: 1; transition: opacity .5s ease }
.player .top, .player .bottom { padding: 18px var(--gutter); display: flex; align-items: center; justify-content: space-between; gap: 16px }
.player video { width: 100%; height: 100%; object-fit: contain; min-height: 0 }
.player button { background: none; border: 0; color: #fff; cursor: pointer; padding: 6px 0 }
.player .bar { position: relative; flex: 1; height: 28px; cursor: pointer }
.player .bar .track { position: absolute; left: 0; right: 0; top: 13px; height: 1px; background: rgba(255,255,255,.3) }
.player .bar .fill { position: absolute; left: 0; top: 13px; height: 1px; background: #fff; width: 0 }
.player .bar .ch { position: absolute; top: 0; transform: translateX(-1px); border-left: 1px solid rgba(255,255,255,.5); height: 28px; padding-left: 6px; font: 500 10px/1 var(--mono); letter-spacing: .1em; text-transform: uppercase; color: rgba(255,255,255,.7); background: none }
.player .bar .ch.on { color: #fff }
.player .time { font-variant-numeric: tabular-nums; min-width: 92px; text-align: right }
.player .slats { position: absolute; inset: 0; z-index: 2; display: flex; pointer-events: none }
.player .slats i { flex: 1; background: #152d48; transform: scaleX(1); transform-origin: left; transition: transform .7s var(--ease) calc(var(--i) * 50ms) }
.player.open .slats i { transform: scaleX(0) }
/* ---------- batten shutters on photos, string-line headings ---------- */
.shutter { position: absolute; inset: 0; display: flex; pointer-events: none; z-index: 1 }
.shutter i { flex: 1; background: var(--paper); transform-origin: right }
.has-shutter { position: relative; overflow: hidden }
.string-wrap { position: relative; display: inline-block }
.string { position: absolute; left: 0; right: 0; bottom: .08em; height: 1px; background: currentColor; transform: scaleX(0); transform-origin: left; opacity: .6 }
/* ---------- veil as battens (loader and page changes) ---------- */
.veil { background: transparent }
.veil .slats { position: absolute; inset: 0; display: flex }
.veil .slats i { flex: 1; background: #091828; transform: scaleY(0); transform-origin: top; transition: transform .55s var(--ease) calc(var(--i) * 40ms) }
.veil.on .slats i { transform: scaleY(1); transform-origin: bottom }
.veil .word, .veil .bar { position: relative; z-index: 1; transition: opacity .3s }
.veil:not(.on) .word, .veil:not(.on) .bar { opacity: 0 }
.veil { opacity: 1; transition: none }
.veil:not(.on) { pointer-events: none }
/* ---------- crosshair cursor ---------- */
.cursor { width: 18px; height: 18px; margin: -9px 0 0 -9px; border-radius: 50%; background: transparent; border: 1px solid transparent; transition: width .4s var(--ease), height .4s var(--ease), margin .4s var(--ease), border-color .3s, opacity .3s }
.cursor::before, .cursor::after { content: ""; position: absolute; left: 50%; top: 50%; background: #fff; transform: translate(-50%, -50%); transition: opacity .2s }
.cursor::before { width: 18px; height: 1px }
.cursor::after { width: 1px; height: 18px }
.cursor.big { border-color: #fff; background: transparent }
.cursor.big::before, .cursor.big::after { opacity: 0 }
.cursor span { color: #fff }
.guide [hidden], .player[hidden] { display: none !important }
/* Squarer and tall screens: the whole frame as a band across the middle, words on the page colour around it,
   so nothing in the drawing is cut off. Full-bleed only on wide screens (wider than 3:2). From Tallis, 2 Nov 2026. */
@media (max-aspect-ratio: 3/2) {
  .drawn .box { --w: min(100%, calc((100svh - 250px) * 16 / 9)); left: calc(50% - var(--w) / 2); top: calc(190px + (100svh - 250px - var(--w) * 9 / 16) / 2); transform: none }   /* in the space under the heading, above the steps */
  .drawn .pin::after { display: none }
  .drawn.real .cap, .drawn.real .steps, .drawn.real .steps span.on { color: var(--charcoal) }
  .drawn.real .steps { color: var(--muted) }
}
.built .x-note { opacity: 0; font-size: 14px; color: var(--muted); max-width: 30ch }
.built.static .x-note { display: none }
/* ---------- Section dots on the right edge: one per section, the current one stretched ---------- */
.section-dots { position: fixed; z-index: 45; right: max(6px, calc(var(--gutter) - 14px)); top: 50%; transform: translateY(-50%); display: grid; color: #fff; mix-blend-mode: difference; transition: opacity .4s }
.section-dots button { position: relative; width: 28px; height: 24px; border: 0; padding: 0; background: none; color: inherit; cursor: pointer }
.section-dots button::before { content: ""; position: absolute; right: 11px; top: 50%; width: 5px; height: 5px; border-radius: 3px; background: currentColor; opacity: .45; transform: translateY(-50%); transition: height .5s var(--ease), opacity .3s }
.section-dots button.on::before { height: 16px; opacity: 1 }
.section-dots button:hover::before, .section-dots button:focus-visible::before { opacity: 1 }
.section-dots span { position: absolute; right: 30px; top: 50%; transform: translate(6px, -50%); font: 500 11px/1 var(--mono); letter-spacing: .1em; text-transform: uppercase; white-space: nowrap; opacity: 0; pointer-events: none; transition: opacity .3s, transform .4s var(--ease) }
.section-dots button:hover span, .section-dots button:focus-visible span { opacity: 1; transform: translate(0, -50%) }
.menu-open .section-dots { opacity: 0; pointer-events: none }
@media (hover: none), (pointer: coarse) { .section-dots span { display: none } }
@media (max-width: 600px) { .section-dots { right: 0 } .section-dots button { height: 20px } }
/* phones and tablets, from the Tallis rules */
@media (max-width: 980px) { .built.static ol { grid-template-columns: 1fr 1fr } }
@media (max-width: 600px) {
  .built .head { top: 70px; right: var(--gutter) } .built ol { bottom: 18px } .built .progress { display: none } .built.static ol { grid-template-columns: 1fr }
  .player .bar .ch { font-size: 0; padding-left: 0 } .player .time { min-width: 0 } .drawn .steps { gap: 14px } .mono { font-size: 12px }
}
@media (prefers-reduced-motion: reduce) {
  .js [data-reveal] { opacity: 1; transform: none } .js [data-words] .w > span { transform: none } .veil { transition: none }
  .player, .player .slats i, .veil .slats i { transition: none } .player .slats { display: none }
}
